vue中如何实现双向绑定的3中方法(.sync/v-model和普通交互)

目录

参考文章

需求

1、第一步、全局子组件定义child

2、第二步、放官网select例子

3、第三步、普通的父子交互方法

1.1在上面的基础例子上的methods里面添加commit方法:

1.2在父页面中利用方法去获取子页面内容:

1.3实际效果gif

4、第四步、sync的watch方法

5、第五步、v-model的双向绑定

1.1、声明传过来的值付赋给什么属性

1.2、this.$emit

 1.3、子页面增加v-model和event绑定

总结

全局代码

1、child.js

2、demo.html

3、效果图



  • 参考文章

  1. vue 实现父组件和子组件之间的数据双向绑定

  2. 深入理解vue 修饰符sync【 vue sync修饰符示例】

  3. 彻底明白VUE修饰符sync

  • 需求

当子页面数据发生变化的时候,父页面的结果也需要更新,由于数据是单向传递,是不可以直接需改父页面的数据,那么我们该怎么操作呢?本篇文章可以利用2种方式(sync、v-model)实现效果都是一样的,区别在于一个要在父页面声明传递的数据对象,一个是在子页面去解析传递的对象是给什么data里面的属性。

我们从官网element-ui中拿一个select下拉框来做实验:

1、第一步、全局子组件定义child

Vue.component("child", {
    data: function () {
        return {}
    },
    template: ``,
    methods:{}
});

2、第二步、放官网select例子

Vue.component("child", {
    data: function () {
        return {
            options: [{
                value: '选项1',
                label: '黄金糕'
            }, {
                value: '选项2',
                label: '双皮奶'
            }, {
                value: '选项3',
                label: '蚵仔煎'
            }, {
                value: '选项4',
                label: '龙须面'
            }, {
                value: '选项5',
                label: '北京烤鸭'
            }],
            value: ''
        }
    },
    template: `
                <div>
                    <el-select v-model="value" placeholder="请选择">
                        <el-option
                          v-for="item in options"
                          :key="item.value"
                          :label="item.label"
                          :value="item.value">
                        </el-option>
                    </el-select>
                </div>
               `,
    methods: {
        
    }
});

3、第三步、普通的父子交互方法

1.1在上面的基础例子上的methods里面添加commit方法:

 methods: {
        commit() {
            this.$emit('output', this.value);
        },
    }

1.2在父页面中利用方法去获取子页面内容:

<p style="font-size: 13px">父组件2:{{foo}}</p>
<child :give="foo" @output="output"></child>

......

let vue = new Vue({
    el: '#app',
    data: {
        foo: null,
    },
    methods: {
    output(data){
        this.foo = data;
        console.log('通过方法获取子对象属性变化:', foo);
    },

......

1.3实际效果gif

4、第四步、sync的watch方法

这里give是外部需要传入的数据,this.value是子页面不断修改的数据。

如果当你写完这个,你的html页面就可以利用下面➷➷➷➷➷➷实现数据交互。从这个我们可以知道当使用sync的时候要在父页面明确声明你传值给谁

<child :give.sync="foo"></child>
props: ['give'],
    watch: {
        'give': function (newVal, oldVal) {
            this.value = newVal;
        },
        value: function (newVal, oldVal) {
            this.$emit("update:give", newVal);
        }
    },

5、第五步、v-model的双向绑定

1.1、声明传过来的值付赋给什么属性

解释例子传参,

model: {
    prop: '父接收属性',
    event: 'commit(普通方法定义接收值)'
},

如在上面所说的最普通实现父子交互是:

<child :give="foo" @output="output"></child>

 从这个我们可以将参数补充进去:

model: {
    prop: 'give',// 即:give
    event: 'output'// 即@output
},

1.2、this.$emit

如果你在使用v-model中没有添加commit方法是需要添加的

 methods: {
        commit() {
            this.$emit('output', this.value);
        },
    }

 1.3、子页面增加v-model和event绑定

​​​​​​......

<el-select v-model="value" placeholder="请选择" @change="commit">

......

上面3个效果都是等同的,看你想要用什么去实现了。

  • 总结

1、普通方法

使用简单,但是需要在父页面中定义接收方法,需要子methods里面使用emit,如果说自定义组件比较多,父页面的方法就会很臃肿;

<child :give="foo" @output="output"></child>

2、sync

使用简单,但是需要在父页面中定义具体传参值,在watch中使用emit,如果自定义组件比较多,每个页面传值定义的单词又不一样,容易晕眩;

<child :give.sync="foo"></child>

3、v-model

使用简单,父页面几乎不需要干什么,将具体绑定都什么对象由子页面去分析,需要定义model,在methods里面使用emit,也比较简洁。

<child v-model="foo"></child>
  • 全局代码

  • 1、child.js

Vue.component("child", {
    data: function () {
        return {
            options: [{
                value: '选项1',
                label: '黄金糕'
            }, {
                value: '选项2',
                label: '双皮奶'
            }, {
                value: '选项3',
                label: '蚵仔煎'
            }, {
                value: '选项4',
                label: '龙须面'
            }, {
                value: '选项5',
                label: '北京烤鸭'
            }],
            value: ''
        }
    },
    props: ['give'],
    watch: {
        'give': function (newVal, oldVal) {
            this.value = newVal;
        },
        value: function (newVal, oldVal) {
            this.$emit("update:give", newVal);
        }
    },
    model: {
        prop: 'give',
        event: 'commit'
    },
    template: `
                <div>
                    <el-select v-model="value" placeholder="请选择" @change="commit">
                        <el-option
                          v-for="item in options"
                          :key="item.value"
                          :label="item.label"
                          :value="item.value">
                        </el-option>
                    </el-select>
                </div>
               `,
    methods: {
        commit() {
            this.$emit('output', this.value);
        },
    }
});

  • 2、demo.html

<script th:src="@{~/js/components/jt/child.js}"></script>
<child :give="foo" @output="output"></child>
<child :give.sync="foo"></child>
<child v-model="foo"></child>
<script type="text/javascript">
    let vue = new Vue({
        el: '#app',
        data: {
            foo: null,
        },
        methods: {
            output(data){
                this.foo = data;
                console.log('通过方法获取子对象属性变化:', this.foo)
            },
        }
    })
</script>
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head th:replace="common/header :: header">
</head>
<head>
    <meta charset="UTF-8">
    <!-- import CSS -->
    <link rel="stylesheet" th:href="@{~/css/ui/reset.css}">
    <link rel="stylesheet" th:href="@{~/css/ui/index.css}">

    <script th:src="@{~/js/components/jt/child.js}"></script>
</head>
<body>
<div id="app">
    <p style="font-size: 13px">父组件2:{{foo}}</p>
    普通方法:<child :give="foo" @output="output"></child>
    sync:<child :give.sync="foo"></child>
    v-model:<child v-model="foo"></child>
</div>
</body>
<script type="text/javascript">
    let vue = new Vue({
        el: '#app',
        data: {
            foo: null,
        },
        methods: {
            output(data){
                this.foo = data;
                console.log('通过方法获取子对象属性变化:', this.foo);
            },
        }
    })
</script>
</html>
  • 3、效果图

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章