将 ref 与道具一起使用

Using ref with props

我有一个 组件 A 和一个嵌套的 组件 B组件A加载一个字符串列表,组件B有一个SELECT元素,当组件A时填充 加载完成。此时应该选择SELECT的第一个选项。 After this moment, when other options are selected, Component B should emit update event with selection data, so that Component A 'knows' 选择了什么选项。由于 A 应该控制 B,这个选项通过 props.[=15= 传回给 B ]

在我下面的实现中,只有选择的初始值被组件 B 接收,当列表被加载时,它被成功填充,但是 selectedOption 值没有被控制 属性 .所以,它不起作用。

实现这个的正确方法是什么?

组件 A:

<template>
  <component-b :list="list" :selected="selected" @update="onUpdate">
</template>

<script lang="ts">
import { defineComponent, ref } from 'vue';
export default defineComponent({
  setup: () => {
    const list = ref<string[]>([]);
    const selected = ref('');

    load().then(data => {       // some load function returning a promise
      selected.value = data[0]; // data is never empty
      list.value = data;
    });

    const onUpdate = (data: string) => selected.value = data;

    return { list, selected, onUpdate };
  }
})
</script>

组件 B:

<template>
  <select v-model="selectedOption" @change="onChange">
    <option v-for="item of props.list" />{{item}</option>
  </select>
</template>

<script lang="ts">
import { defineComponent, ref, PropType } from 'vue';
export default defineComponent({
  emits: ['update'],
  props: {
    selected: {
      type: String
    },
    list: {
      type: Object as PropType<String[]>
    }
  }
  setup: (props, { emit }) => {
    const selectedOption = ref(props.selected); // this doesn't work when loading is finished and props are updated
    
    const onChange = () => emit('update', selectedOption.value);

    return { selectedOption, onChange, props }
  }
});
</script>

谢谢。

在组件 B 中,您不需要同时添加 v-model 和 @change。

 <select :value="selected" @change="onChange">
   <option v-for="item in list">{{ item }}</option>
 </select>

然后在 onChange 中从 select 获取值并发出:

const onChange = (event) => emit('update', event.target.value);

ComponentB.vue中,selectedOptionref只是初始化props.selected的值,但它本身是 非反应性 (即 ref 不会自动跟踪 props.selected):

const selectedOption = ref(props.selected); // not reactive to props.selected

您可以使用 watchEffect 解决此问题,将任何新值复制到 selectedOption(每当 props.selected 更改时自动发生):

watchEffect(() => selectedOption.value = props.selected);

旁注: setup() 不需要显式 return props 因为它们已经可以通过名称用于模板.您的模板可以更改为:

<!-- <option v-for="item of props.list">{{ item }}</option> -->

                         reference props directly by name
<option v-for="item of list">{{ item }}</option>

demo