Vue规定父组件可以通过prop将值传递给子组件,但不允许子组件直接修改prop的值。如果子组件可以任意修改父组件的内容,那势必会带来数据的混乱,从而造成维护的困扰!

看一个父子组件传递消息的例子:
image.png

常规写法

父组件代码:

<template>
  <div>
    <input type="button" value="我是父组件中的按钮" @click="show" />
    <child @upIsShow="changeIsShow" v-show="isShow" />
  </div>
</template>

<script>
import child from "./child";
export default {
  //import 引入的组件需要注入到对象中才能使用
  components: { child },
  props: {},
  data() {
    //这里存数据
    return {
      isShow: false,
    };
  },
  //计算属性
  computed: {},
  //监控data中数据变化
  watch: {},
  //方法
  methods: {
    show() {
      this.isShow = true;
    },
    changeIsShow(bol) {
      this.isShow = bol;
    },
  },
};
</script>

子组件代码:

<template>
  <div>
    我是一个子组件
    <input type="button" value="点我隐身" @click="upIsShow" />
  </div>
</template>

<script>
export default {
  //import 引入的组件需要注入到对象中才能使用
  components: {},
  props: {},
  data() {
    //这里存数据
    return {};
  },
  //计算属性
  computed: {},
  //监控data中数据变化
  watch: {},
  //方法
  methods: {
    upIsShow() {
      this.$emit("upIsShow", false);
    },
  },
};
</script>

改写方法

将父组件中的事件名@upIsShow修改为@update:isShow,并且将方法改写为匿名函数,一切正常。
父组件代码:

<template>
  <div>
    <input type="button" value="我是父组件中的按钮" @click="show" />
    <child @update:isShow="obj=>isShow=obj" v-show="isShow" />
  </div>
</template>

子组件代码:

    upIsShow() {
      this.$emit("update:isShow", false);
    }

语法糖

<child :isShow.sync="isShow" v-show="isShow"/>

以上代码其实就是下面代码的简写形式:

<child @update:isShow="obj=>isShow=obj" v-show="isShow" />

用了sync后,子组件传值给父组件时,需要调用$emit("update:xxxx", ...)。官方推荐这种update:my-prop-name 的模式来替代事件触发,目的是为了优雅而不粗鲁的实现父子组件间的双向绑定!

Q.E.D.

知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议