- A+
所属分类:Web前端
背景
再很多场景中,我们可能想在子组件中修改父组件的数据,但事实上,vue不推荐我们这么做,因为数据的修改不容易溯源。
Vue2写法
在vue2中,我们使用.sync
修饰符+自定义事件'update:xxx'
,来使父子组件数据同步。
// 父组件 <template> <div> <h2>我是父组件,我有{{ money }}¥</h2> <hr> <!-- 这里使用.sync修饰符,使**子组件pmoney**与**父组件money**同步 --> <Son :pmoney.sync="money" /> </div> </template> <script> import Son from "./son.vue"; export default { components: { Son, }, data() { return { money: 1000 // 父组件数据 }; }, }; </script>
// 子组件 <template> <div> <h2>我是子组件,我爹有{{ pmoney }}¥</h2> <!-- 触发**update:pmoney**这个自定义事件,事件参数就是要更改的值 --> <button @click="$emit('update:pmoney', pmoney - 100)">用了100¥</button> </div> </template> <script> export default { props: { // 定义父组件传进来的数据 pmoney: { type: Number, default: 0 }, }, }; </script>
这里不作过多说明,有需要请自行了解。
Vue3写法
vue3的写法与vue2基本一致。最大的区别就是,使用v-model
代替.sync
修饰符。
// 父组件 <template> <div> <!-- 父组件的数据 --> <h2>我是父组件,我有{{ money }}¥</h2> <hr> <!-- 使用子组件 --> <!-- 这里v-model的作用相当于vue2的.sync修饰符 --> <Son v-model:pmoney="money" /> <!-- 也可以绑定多组数据 --> <!-- <Son v-model:pmoney1="money" v-model:pmoney2="money" /> --> </div> </template> <script setup lang="ts"> import { ref } from 'vue'; // 引入子组件 import Son from './son.vue'; // 父组件的数据 const money = ref(1000); </script>
// 子组件 <template> <div> <!-- 使用props中的数据 --> <h3>我是子组件,我爹有{{ pmoney }}¥</h3> <!-- 这里通过自定义事件,向父组件传递变更后的值,由父组件监听事件并修改数据 --> <button @click="emit('update:pmoney', pmoney - 100)">我使用了100¥</button> </div> </template> <script setup lang="ts"> // 定义props,接收父组件的数据 defineProps(['pmoney']); // 定义emits,用于触发父组件的事件 const emit = defineEmits(['update:pmoney']); </script>
原理剖析
下面的v-model:pmoney
实际是v-bind:pmoney
属性绑定和@update:pmoney
事件绑定的语法糖。
这里事件绑定的@update:
是固定的,这就是子组件的自定义事件要加update:
前缀的原因。
<Son v-model:pmoney="money" />
相当于
<Son :pmoney="money" @update:pmoney="money = $event" />
$event
:子组件通过自定义事件传给父组件的值。
父子组件数据同步的本质
本质是子组件通过自定义事件向父组件传参数,子组件触发自定义事件并传值,父组件监听自定义事件并取值,同时修改原本的数据,因为v-bind数据绑定,子组件数据也会更新到最新的值。