将 ref 与 props 一起使用

Mic*_*sky 3 vue.js vuejs3 vue-composition-api

我有一个Component A和一个嵌套的Component B组件 A加载一个字符串列表,组件 B有一个元素,当组件 A完成加载SELECT时会填充该元素。此时应选择第一个选项。此后,当选择其他选项时,组件 B应发出带有选择数据的事件,以便组件 A “知道”选择了哪个选项。由于A应该控制B,因此该选项通过 props 传递回BSELECTupdate

在我下面的实现中,组件 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>
Run Code Online (Sandbox Code Playgroud)

组分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>
Run Code Online (Sandbox Code Playgroud)

谢谢。

ton*_*y19 7

在 中ComponentB.vueselectedOption'sref初始化为 的值props.selected,但它本身不是反应性的(即,ref不会props.selected自动跟踪):

const selectedOption = ref(props.selected); // not reactive to props.selected
Run Code Online (Sandbox Code Playgroud)

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

watchEffect(() => selectedOption.value = props.selected);
Run Code Online (Sandbox Code Playgroud)

旁注: setup()不需要显式返回,props因为它们已经可按名称用于模板。您的模板可以更改为:

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

                         reference props directly by name
<option v-for="item of list">{{ item }}</option>
Run Code Online (Sandbox Code Playgroud)

演示