我们有时候需要抽离一些模块,这些模块中可能包含input,而我们的子模块数据又来源于父组件中。这时候如何双向同步就成了不得不面对的问题。我们通过一个简单的实例来看看。
第一种解法就是父组件传值,子组件通过:value="num" @input="updateNum",然后每次子组件里input的值发生改变的时候 emit('update:num', event.target.value)事件。
<div class="wrap">
<div class="list_item" v-for="(item,index) of skuData.list">
{{item.id}}
<Ipt v-model:num="item.num" />
</div>
</div>
<button @click="test">查看数据</button>
const skuData=ref({
list:[
{id:"0001",num:1},
{id:"0002",num:2},
{id:"0003",num:3},
{id:"0004",num:4},
]
})
----------------------------------------------
子组件
<template>
<div>
<p>input数据</p>
<input type="text" :value="num" @input="updateNum" />
</div>
</template>
const emit=defineEmits(['update:num'])
const props=defineProps({
modelValue: {
type: Object,
required: true
},
num: {
type: Number,
default: 0
}
})
const updateNum=(event) =>{
emit('update:num', event.target.value)
}
第二种解法其实同理,只不过父子组件中双向同步的不是一个具体的num值而是一个对象。
<div class="wrap">
<div class="list_item" v-for="(item,index) of skuData.list">
{{item.id}}
<Ipt v-model="skuData.list[index]" />
</div>
</div>
<button @click="test">查看数据</button>
const skuData=ref({
list:[
{id:"0001",num:1},
{id:"0002",num:2},
{id:"0003",num:3},
{id:"0004",num:4},
]
})
---------------------------------------------------
子组件
template>
<div>
<p>input数据</p>
<input type="text" v-model="localValue.num"/>
</div>
</template>
<script setup lang="ts">
import { defineProps, defineEmits, watch } from 'vue'
const props = defineProps({
modelValue: {
type: Object,
required: true
}
})
const emit = defineEmits(['update:modelValue'])
const localValue = props.modelValue // 直接使用 props.modelValue
watch(
() => props.modelValue,
(newVal) => {
localValue.num = newVal.num // 确保直接更新 localValue
},
{ deep: true, immediate: true }
)
watch(localValue, (newValue) => {
emit('update:modelValue', newValue) // 向父组件发出更新
})
这时候当我们更改子组件中input的值的时候父组件的值也会同步更改。不过有一点要注意。
const localValue = props.modelValue 这里不要用const localValue =ref( props.modelValue)同时,更改子组件里input的值以后,父组件的数据格式变成了{id:"0001",num:3,value:{d:"0001",num:3,}},
这里3是更改以后的值。多了一个value。这是vue3自动响应式处理的结果。
推荐使用方式一