在 Vue 3 中加载异步选项时自动 select 第一个 <select> 选项

Auto-select first <select> option when loading async options in Vue 3

我有一个 <select> HTML 元素,我想 v-model 绑定到 Vue.js 3 的 setup() 方法中的 ref 值.因此,当用户 select 选择不同的选项时,Form.ProductID ref 会更新。

这里是 <select> 代码:

<select v-model="Form.ProductID" id="ProductID" name="ProductID">
  <option value="1">Option A</option>
  <option value="2">Option B</option>
  <option value="3">Option C</option>
</select>

setup()

export default {
  name: "ComponentProductSelector",
  setup() {
    const Form = ref({
      ProductID: '2',
      Price: null,
      Currency: null
    })

    onMounted(() => Form.value.ProductID)
    document.querySelector("#ProductID option:first-of-type")
  }
}

在 vue devtools 中首次加载时,它显示数据为:

Form (Object Ref) 
    ProductID: "[object HTMLOptionElement]"

当我 select <select> 元素中的一个选项时,Form.ProductID 按预期更新并显示我 select 编辑的选项,例如:

 Form (Object Ref) 
        ProductID: 3

问题是在页面第一次加载时,<select> 元素没有 select 使用 value="2" 选择选项,即使我在 [=20] 中硬编码它=].它只是显示一个空白选项!但是,如果我将 <select> 元素更改为以下代码,则它会:

<select ref="Form.ProductID" id="ProductID" name="ProductID">
  <option value="1">Option A</option>
  <option value="2">Option B</option>
  <option value="3">Option C</option>
</select>

现在 value="2" 的选项在渲染组件时默认为 selected,但是 Form.ProductID 的实际值不会更新并且 vue devtools 继续显示 ProductID: "[object HTMLOptionElement]"作为数据。

如何使用 v-model 和组件加载时的默认选项 select 让 <select> 元素正常工作?

回答关于如何在异步加载时 select 第一个选项的评论中更新的问题。加载数据后,将 Form 的值设置为选项数组中的第一项(克隆以避免改变它),而不是手动操作输入 DOM.

例如:

<select v-model="Form.ProductID" id="ProductID" name="ProductID" v-if="options">
  <option v-for="option in options" :key="option.ProductID" :value="option.ProductID">
    {{ option.ProductID }}
  </option>
</select>
setup() {
  const options = ref(null);
  const Form = ref(null);

  axios.get('...').then(response => {
    options.value = response.data;
    Form.value = { ...options.value[0] };    // Clone and select first option
  });
  return { options, Form }
}

<select> 上有一个 v-if 延迟渲染,直到数据准备好。

这是一个演示:

const { createApp, ref } = Vue;
const app = createApp({
  setup() {
    const options = ref(null);
    const Form = ref(null);
    
    axios.get('https://jsonplaceholder.typicode.com/posts').then(response => {
      options.value = response.data;
      Form.value = { ...options.value[0] };    // Clone and select first option
    });
    return { options, Form }
  }
});
app.mount("#app");
<div id="app">
  <select v-model="Form.id" id="ProductID" name="ProductID" v-if="options">
    <option v-for="option in options" :key="option.id" :value="option.id">
      {{ option.id }}
    </option>
  </select>
</div>

<script src="https://unpkg.com/vue@next"></script>
<script src="https://unpkg.com/axios"></script>