vue自定义组件实现双向绑定

场景:

我们比较常用的父子组件之间的交互方式:
父组件通过props将数据流入到子组件;
子组件通过$emit将更新后的数组发送的父组件;

今天,我们通过另一种方式实现交互,参考input框的v-model,实现自定义组件的双向数据绑定。
即:父组件值改变,子组件的值跟着改变;反之,子组件值发生变化,父组件值随之变化


子组件定义:

由于不能直接修改props属性值,我们这里定义valueData,通过监听实时接收value值,通过click方法修改valueData。
这里注意model语法糖prop 是接收的props属性value,保持一致。event是先上传递的事件名。

代码如下:

<template>
    <div>
        <div>{
     {
      `子组件值: ${
       value}` }}</div>
        <div @click="click">点击此处修改值</div>
    </div>
</template>

<script>
export default {
     
    name: "",
    model: {
     
        prop: "value",
        event: "change"
    },
    props: {
     
        value: Number
    },
    components: {
     },
    data() {
     
        return {
     
            valueData: ""
        };
    },
    watch: {
     
        value(newValue, oldValue) {
     
            this.valueData = newValue;
            console.log(`子组件值:${
       newValue}`);
        }
    },
    created() {
     
    },
    mounted() {
     
    },
    methods: {
     
        click() {
     
            this.valueData++;
            this.$emit("change", this.valueData);
        }
    }
};
</script>
<style lang='less' scoped>
</style>

父组件定义:

父组件通过v-model绑定text值,名称不一定是value,可以是其他任意符合命名规范的字符串,这里是text。
子组件通过change事件更新数据后,v-mode绑定值随之变化。
或者父组件修改text值后,子组件value值随之变化。

代码如下:

<template>
    <div>
        <div>{
     {
      `父组件值:${
       text}` }}</div>
        <div @click="click">点击此处修改值</div>


        <span>-----------------------------------------------------------</span>

        <test-children v-model="text"></test-children>

    </div>
</template>

<script>
import TestChildren from "@/views/TestChildren";

export default {
     
    name: "",
    components: {
      TestChildren },
    data() {
     
        return {
     
            text: 1
        };
    },
    created() {
     
    },
    mounted() {
     
    },
    watch: {
     
        text(newValue, oldValue) {
     
            console.log(`父组件值:${
       newValue}`);
        }
    },
    methods: {
     
        click() {
     
            this.text--;

        }
    }
};
</script>
<style lang='less' scoped>
</style>

结果:

直接copy代码到自己项目测试。无论是通过父组件改变值,还是子组件改变值。两个组件通过v-mode绑定的值始终保持一致。

答疑:

有同学就问了 ,这不是和通过props向下流入数据,再通过$emit方式向上传递数据一样么也能实现我这种双向绑定的效果。 其实不然,如果不通过v-model,那么我们势必会在父组件写这样的代码:
<test-children @change="changeText"></test-children>

然后在通过定义changeText方法修改text值。
试想,当我们的页面比较复杂,引用组件量比较庞大,页面中就需要多定义这样十几、二十几个方法。可阅读行大大降低,增加了维护成本。

扩展:

vue2.3之后提供了sync方式,也能实现双向绑定

父组件中的写法:

<test-children :value.sync="text"></test-children>

子组件中不需要使用下面model定义,直接删除即可。

model: {
prop: “value”,
event: “change”
},

向父组件传递数据使用如下方式:

this.$emit("update:value", this.valueData);

总结

每天记录一点,从小小菜鸟变小菜鸟!!!

你可能感兴趣的:(javascript,vue.js)