• 开发过程中经常需要子组件去修改父组件传过来的值,但是vue是单向数据流
  • vue是单向数据流,子组件要想修改父组件的值可以通过.sync,通过update事件$emit出去

如果子组件直接修改父组件接受到的值

Vue.component("ComponentA", {
            props: ["step"],
            methods: {
                handleClick() {
                    this.step++;
                },
            },
            data() {
                return {

                };
            },
            template: `<div>
        子组件{{step}}
        <button @click="handleClick">click</button>
        </div>`,
        });
        app = new Vue({
            el: `#app`,
            template: `
        <div>父组件{{step}}
            <ComponentA :step="step">
            </ComponentA>
        </div>`,
            data: {
                msg: "App",
                step: 1
            },
        });

在这里插入图片描述

正确的做法

        Vue.component("ComponentA", {
            props: ["step"],
            methods: {
                handleClick() {
                    this.$emit('update:step', this.step + 1)
                },
            },
            data() {
                return {

                };
            },
            template: `<div>
        子组件{{step}}
        <button @click="handleClick">click</button>
        </div>`,
        });
        app = new Vue({
            el: `#app`,
            template: `
        <div>父组件{{step}}
            <ComponentA :step.sync="step">
            </ComponentA>
        </div>`,
            data: {
                msg: "App",
                step: 1
            },
        });

在这里插入图片描述

  • 需要注意的地方,父组件绑定数据需要加上.sync;子组件通过$emit通知父组件改变值时事件必须为update,切后边必须写上更新的数据源update:step

但是

  • 当我把this.$emit('update:step', this.step + 1)改写成this.$emit('update:step', this.step ++)或者this.$emit('update:step', ++this.step)时,又报错不允许修改父组件的数据
  • 那么这里就相当于是a+1 、 a++、++a的经典问题了,此处省略1万字…

问题终归是要解决的

  • 既然不能直接修改父组件的值那么通过中间变量就可以修改,再把中间变量更新给原属于源
Vue.component("ComponentA", {
            props: ["step"],
            methods: {
                handleClick() {
                    this.count++;
                    this.$emit('update:step', this.count)
                },
            },
            data() {
                return {
                    count: this.step
                };
            },
            template: `<div>
        子组件{{step}}
        <button @click="handleClick">click</button>
        </div>`,
        });
        app = new Vue({
            el: `#app`,
            template: `
        <div>父组件{{step}}
            <ComponentA :step.sync="step">
            </ComponentA>
        </div>`,
            data: {
                msg: "App",
                step: 1
            },
        });
  • 当然,这是一个语法糖,当子组件中没有触发$emit的事件时,可以通过watch、computed的get/set去触发。
Logo

前往低代码交流专区

更多推荐