You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue3选项API中含select的子组件v-model不生效问题求助

问题

使用Vue3选项API开发货币转换器时,子组件的<select>无法在父组件响应式数据变化时同步更新。具体表现为:

  • 通过v-model绑定子组件后,点击交换按钮切换currency_1和currency_2的值,子组件的选中状态未同步变化
  • 期望实现:父组件数据更新时,子组件<select>自动同步选中值,同时保持v-model的双向绑定功能

原因分析

  1. 响应式属性未正确声明:父组件中currency_1、currency_2、currencies、temp_currency均未在data()中声明,直接通过this.xxx添加的属性不属于Vue的响应式系统,数据变化时无法触发视图更新。
  2. 子组件的v-model逻辑本身是正确的,但由于父组件数据非响应式,导致modelValue props无法实时更新,进而无法同步到<select>的选中状态。

解决方案

1. 父组件补充响应式属性声明

在data()中明确声明所有需要响应式的属性,确保Vue能追踪其变化:

data() {
  return {
    currencies_loaded: false,
    amount: null,
    timeoutId: null,
    // 新增以下响应式属性
    currencies: {},
    currency_1: '',
    currency_2: '',
    temp_currency: ''
  }
},

2. 子组件代码(可保持现有逻辑,或优化props校验)

子组件的v-model实现符合Vue3选项API规范,无需修改核心逻辑,可添加props类型校验增强健壮性:

<script>
export default {
  props: {
    modelValue: {
      type: String,
      required: true
    },
    currencies: {
      type: Object,
      required: true
    }
  },
  emits: ['update:modelValue'],
  data() {
    return {
      compteur: 0
    }
  },
}
</script>

<template>
  <select class="currency_selector" :value="modelValue"
          @input="$emit('update:modelValue', $event.target.value)">
    <option v-for="(value, currency) in currencies" :key="value.id"
            :value="currency">
      {{ currency }}-{{ value.currency_name }}
    </option>
  </select>
</template>

修改后的父组件完整代码

<script>
import CurrencySelector from './components/CurrencySelector.vue';
export default {
  components: {
    CurrencySelector
  },
 
  data() {
    return {
      currencies_loaded: false,
      amount: null,
      timeoutId: null,
      currencies: {},
      currency_1: '',
      currency_2: '',
      temp_currency: ''
    }
  },
  created(){
    fetch('http://localhost:8000/api/currencies/list')
      .then(response => {
        if (response.ok) {
          return response.json(); 
        } else {
          throw new Error('Request failed');
        }
      })
      .then(currencies => {
        this.currencies = currencies.data;
        this.currency_1 = Object.keys(this.currencies)[7];
        this.currency_2 = Object.keys(this.currencies)[0];
        this.currencies_loaded = true;
      })
      .catch(error => {
        console.error(error);
      });
  },
  
  methods: {
    amount_modified(event){
      clearTimeout(this.timeoutId);
      this.timeoutId = setTimeout(() => {
        if(event.target.value){
          fetch(`http://localhost:8000/api/exchange/pairs/${this.currency_1}/${this.currency_2}`)
            .then(response => {
              if (response.ok) {
                return response.json(); 
              } else {
                throw new Error('Request failed');
              }
            })
            .then(data => {
              console.log(data);
            })
            .catch(error => {
              console.error(error);
            });
        }
      }, 500);
    },
    swap_handler(){
      this.temp_currency = this.currency_1;
      this.currency_1 = this.currency_2;
      this.currency_2 = this.temp_currency;
    },
    convertion_init(event) {
     
    }
  }
}
</script>

<template>
  <div id="main_container" v-if="currencies_loaded">
    <div id="selector_container">
      <input type="text" @input="amount_modified" class="inputs" inputmode="decimal" autocomplete="off" id="amount">

      <div class="inputs">
        <label for="currency_1">DE</label>
        <CurrencySelector id="currency_1" :currencies="currencies" v-model="currency_1"/>
      </div>
      
      <button type="button" @click="swap_handler" id="swap_currencies">
        <img id="swap_arrow" src="./img/svgviewer-output.svg" alt="交换货币">
      </button>
      
      <div class="inputs">
        <label for="currency_2">VERS</label>
        <CurrencySelector id="currency_2" :currencies="currencies" v-model="currency_2"/>
      </div>
    </div>
  </div>
</template>

<style scoped>
/* 样式保持不变 */
</style>

关键说明

  • 所有需要响应式追踪的属性必须在data()中初始化,Vue选项API不会自动将后续添加的this属性转为响应式
  • 子组件通过:value="modelValue"绑定props,@input触发update:modelValue事件,完全符合Vue3的v-model自定义组件规范,父组件的响应式数据更新后会自动同步到子组件的<select>选中状态

内容的提问来源于stack exchange,提问作者Baptiste Dara

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 23:54:59