官方文档v-model:v3.cn.vuejs.org/guide/migra…
(1). 父组件A调用子组件B,父组件通过 v-model ="msg" 来绑定值,子组件需要通过内置的默认值 modelValue 来接收。
(2). 对于父组件而言,v-model="msg",相当于 :modelValue="msg" 、@update:modelValue="msg=$event" (赋值的同时,监听到子组件的变化,收到最新值$event,并且赋值给 msg)
(3). 对于子组件而言,也可以通过 v-model="modelValue"来赋值(前提是input、select等标签),此时将自动监听modelVaule的变化,拿到变化值需要通过 emit对外传递。 通过中转自动监听modelValue的变化有两种方式:
A. 通过computed属性处理一下modelValue值,然后再给v-model绑定
B. 通过watch监听modelValue值,变化的时候emit对外传递。
(4). 对于子组件而言,v-model="modelValue" 也等价于 :modelValue="modelValue[xx]" @update:modelValue="handleValueChange($event, x)"然后在handelValueChange方法中实现对外emit
(5). 父组件中也可以通过v-model绑定其它值,不用默认的modelValue传递,比如: v-model:title="msg",等价于 :title="msg", @update:title="msg=$event" ,子组件在props中通过title接收到父组件传递的值。
父组件 App.vue
<template>
<div class="app">
{{ msg }}
<hr />
<!-- 这里故意给modelValue改名字为msg 子组件需要通过 msg来接收 -->
<home v-model:msg="msg"></home>
<hr />
<!-- 这里没有改名字 那么子组件 要通过默认的props接收 -->
<about v-model="msg"></about>
</div>
</template>
<script>
import Home from "@/components/Home.vue";
import About from "@/components/About.vue";
import { ref } from "vue";
export default {
name: "App",
components: {
Home,
About,
},
setup() {
const msg = ref("App");
return {
msg,
};
},
};
</script>
<style></style>
子组件 Home.vue
<template>
<div>
{{ msg }}
<!-- 注意这里,是通过value绑定值,修改值通过发射事件去修改 -->
<input type="text" :value="msg" @input="inputChange" />
</div>
</template>
<script>
export default {
props: {
// 因为父组件重新命名了, 这里我们要通过msg来接收
msg: {
type: String,
default: "",
},
},
emits: ["update:msg"],
setup(props, { emit }) {
// 通过发射事件去修改值
const inputChange = (event) => {
// 因为改了名字 所以是update:msg 默认的 update:modelValue
emit("update:msg", event.target.value);
};
return {
inputChange,
};
},
};
</script>
<style lang="scss" scoped></style>
子组件About.vue
<template>
<!-- 这里为了保证单项数据流,我们重新copy了一份数据 -->
<div>{{ modelValue }} <input type="text" v-model="modelValueCopy" /></div>
</template>
<script>
import { ref, watch } from "vue";
export default {
props: ["modelValue"],
emits: ["update:modelValue"],
setup(props, { emit }) {
// 如果是对象 那么需要 ref( {...props.modelValue});
// 如果是对象 并且是多层次的 需要深拷贝
const modelValueCopy = ref(props.modelValue);
// 如果是对象,那么要deep:true 深度监听
// 如果我们拷贝的数据发生变化,我们就发射事件,并且把值带过去,这种方法很巧妙
watch(modelValueCopy, (newValue) => {
emit("update:modelValue", newValue);
});
return {
modelValueCopy,
};
},
};
</script>
<style lang="scss" scoped></style>
最终效果: