.sync原理(Vue组件父子传值)

使用前提:

首先,我们需要明确的是,子父组件之间通讯,子组件是不能直接改变父组件的值的。(父组件是大佬,小弟不能改变大佬的值,但是父组件可以改变子组件的值)

作用:

通过某种方式,子组件可以”直接“改变父组件的值。

场景:

控制弹框的显示与关闭。在父组件中打开子组件弹框,然后在点击子组件中的按钮关闭弹框。

方法:

1. 一般我们子父传值的处理如下:

  注意:子组件向父组件传值时,父组件中@changeVisibleState="changeVisible"中,方法名不要加括号!!!!@changeVisibleState="changeVisible()"

// 父组件
<template>
    <div class="parent-file">
        <input type="button" value="打开子组件" @click="show">
        <!-- 子组件插槽 -->
        <child @changeVisibleState="changeVisible" :visible="childShow"/>
    </div>
</template>

<script>
import child from "./child"
    export default {
        data () {
            return {
                childShow: false
            }
        },
        components: {
            child
        },
        methods: {
            show(){
                this.childShow = true;
            },
            changeVisible (val) {
                this.childShow = val;
            }
        }
    }
</script>
// 子组件
<template>
    <div class="child-file">
        <input type="button" value="点我隐身" @click="doClose" v-show="visible">
    </div>
</template>

<script>
    export default {
        props: [ 'visible' ],
        methods: {
            doClose () {
                this.$emit("changeVisibleState", false)
            }
        }
    }
</script>

2. 改进:

这样的写法没错,但是显的比较臃肿,明明我只是要改一个值,就不能简单点?

答案是,当然是可以的。

大家肯定会想,那我不能直接改变父组件的值?想v-model那样,多爽。

vue也是考虑到了这点,所以提供了一个更好的解决方案

// 父组件
//  先把方法写到行内,箭头函数的写法。
//  方法名为什么是update:visible,是下面子组件的emit方法定义的。
<template>
    <div class="parent-file">
        <input type="button" value="打开子组件" @click="show">
        <!-- 子组件插槽 -->
        <child @update:visible="(val)=>{ childShow = val }" :visible="childShow"/>
    </div>
</template>

<script>
import child from "./child"
    export default {
        data () {
            return {
                childShow: false
            }
        },
        components: {
            child
        },
        methods: {
            show(){
                this.childShow = true;
            },
            // 以简化代码
            // changeVisible (val) {
            //     this.childShow = val;
            // }
        }
    }
</script>
// 子组件
<template>
    <div class="child-file">
        <input type="button" value="点我隐身" @click="doClose" v-show="visible">
    </div>
</template>

<script>
    export default {
        props: [ 'visible' ],
        methods: {
            doClose () {
                // 修改前代码
                // this.$emit("changeVisibleState", false)

                // 改变写法
                this.$emit("update:visible",false);
            }
        }
    }
</script>

3. 最后:

对于 @update:visible="(val)=>{childShow = val}" :visible="childShow",vue提供了一个语法糖,将其替换成 :visible.sync = "childShow" ,这样是不是看起来简洁多了。

那么就变成了:

// 父组件
<template>
    <div class="parent-file">
        <input type="button" value="打开子组件" @click="show">
        <!-- 子组件插槽 -->
        <child :visible.sync = "childShow"/>
    </div>
</template>

<script>
import child from "./child"
    export default {
        data () {
            return {
                childShow: false
            }
        },
        components: {
            child
        },
        methods: {
            show(){
                this.childShow = true;
            },
            // 以简化代码
            // changeVisible (val) {
            //     this.childShow = val;
            // }
        }
    }
</script>
// 子组件
<template>
    <div class="child-file">
        <input type="button" value="点我隐身" @click="doClose" v-show="visible">
    </div>
</template>

<script>
    export default {
        props: [ 'visible' ],
        methods: {
            doClose () {
                // 修改前
                // this.$emit("changeVisibleState", false)

                // 改变写法
                // 注意:emit中的函数名,一定要以这种格式"update:props"命名,其中props就是我们子父之间通讯的值
                this.$emit("update:visible", false);
            }
        }
    }
</script>
posted @ 2019-09-30 16:57  X_LLin  阅读(2147)  评论(0编辑  收藏  举报