拆解实现
父组件
<template><div></div><Son :name="name" @inputChange="inputChange"></Son>{{ name }}
</template><script setup>
import {ref} from 'vue'
import Son from './son2.vue'const name=ref("张三")const inputChange=(value)=>{name.value=value
}
</script><style scoped></style>
子组件
<template><div><input type="text" :value="name" @input="inputChange"></div>
</template><script setup>
defineProps(['name'])const inputChange=({target:{value}})=>{
emit('inputChange',value)
}
const emit=defineEmits(['inputChange'])</script><style scoped></style>
然后进行改造成我们想要的v-model形式
父组件这边
<template><div></div><!-- <Son :name="name" @inputChange="inputChange"></Son> --><Son v-model:aaa="name" age="18"></Son>{{ name }}
</template><script setup>
import {ref} from 'vue'
import Son from './son2.vue'const name=ref("张三")const inputChange=(value)=>{name.value=value
}
</script><style scoped></style>
注意和之前的父组件内容进行对比
再来到子组件这里
<template><div><!-- <input type="text" :value="name" @input="inputChange"> --><input type="text" :value="aaa" @input="inputChange"></div>
</template><script setup>
// defineProps(['name'])// const emit=defineEmits(['inputChange'])
//v-model必须要使用update:开头
//然后跟上对应的v-model的属性名
const emit=defineEmits(['update:aaa'])
//这个时候defineProps接收的是v-model传过来的值
//注意:v-model传功来的属性和父子传值的属性不能重名//aaa 就是v-model的值
//age 就是 父子传值的属性defineProps(['aaa','age'])const inputChange=({target:{value}})=>{
emit('update:aaa',value),
console.log({target:{value}});
console.log("value",value);
console.log("target",event.target);
//{target:{value}} 解构赋值
console.log(event.target.value===value);
}</script><style scoped></style>
这样就完成了自定以组件的双向绑定。
其中,有几个需要注意的地方,就是使用defineProps()时,注意区分v-model的值和父子传值的属性。
还有就是那个update:aaa中的update,这里使用update是vue框架官方的写法,如果想要叫其他值,就还需要父组件传递对应的事件@custom-update:myValue="someData = $event",过程也比较繁琐,这里只是说明为什么那里要叫update。在实际的开发中还是使用这种固定命名的比较便于开发。