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

Posted

技术标签:

【中文标题】在 Vue 3 中加载异步选项时自动选择第一个 <select> 选项【英文标题】:Auto-select first <select> option when loading async options in Vue 3 【发布时间】:2021-06-04 15:09:25 【问题描述】:

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

这里是&lt;select&gt; 代码:

<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]"

当我在 &lt;select&gt; 元素中选择一个选项时,Form.ProductID 会按预期更新并显示我选择了哪个选项,例如:

 Form (Object Ref) 
        ProductID: 3

问题是在第一次加载页面时,&lt;select&gt; 元素没有选择带有value="2" 的选项,即使我在setup() 中对其进行了硬编码。它只是显示一个空白选项!但是,如果我将 &lt;select&gt; 元素更改为以下代码,则可以:

<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"的选项,但是Form.ProductID的实际值不会更新,vue devtools继续将ProductID: "[object HTMLOptionElement]"显示为数据。

如何让&lt;select&gt; 元素使用v-model 工作,并在组件加载时选择默认选项?

【问题讨论】:

肯定有不同的问题,应该可以工作jsfiddle.net/sh0ber/zrj18f69 @shob 你是对的,这是一段代码:onMounted(() =&gt; Form.value.ProductID = document.querySelector("#ProductID option:first-of-type") 默认选择第一个选项。是否可以让Form.value.ProductID等于第一个选项onMounted的值? 为什么不将Form.ProductID 设置为 1? @shob 因为我不能总是知道 ID 是什么。它们最终将来自数据库作为 json 【参考方案1】:

回答 cmets 中关于异步加载时如何选择第一个选项的更新问题。加载数据后,将 Form 的值设置为 options 数组中的第一项(克隆以避免变异),而不是手动操作输入 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 

&lt;select&gt; 上有一个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>

【讨论】:

不客气!我做了一个小更新。首先克隆选项很重要,或者为Form 创建一个新对象并一个一个添加属性,克隆任何引用类型。否则更改表单输入会更改选项 #1 的选项数据

以上是关于在 Vue 3 中加载异步选项时自动选择第一个 <select> 选项的主要内容,如果未能解决你的问题,请参考以下文章

使用 Typescript 在 vue.js 中加载 JSON 文件

在Vue中加载页面时从列表中调用json

选择选项时自动加载选项 PHP/MySQL

发布到 npm 时无法在 Vue 中加载样式

在 Vue.js 中加载时未检查复选框

在tableview中加载异步图像,它们在每次滚动时消失