vue3中自定义组件的双向绑定

发布于:2024-12-19 ⋅ 阅读:(9) ⋅ 点赞:(0)

我们有时候需要抽离一些模块,这些模块中可能包含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自动响应式处理的结果。

推荐使用方式一