[vue]vue双向绑定$on $emit sync

双向绑定实现($on $emit)

关于父子之间数据更新同步, 如果单向绑定, 子修改了,父却没有修改, 这种一般不符合规范

正常更新数据的套路是:
1. 子通知父更新数据
2. 子自动刷新获取最新数据
- 为实现这个,就会有发布订阅模式
1.特点: 一对多, 一个动作产生,引发一连串行为. 对应到数据结构是:
    {失恋:[cry,eat,shopping]} 
2.如果失恋产生, 则会触发cry,eat shopping一系列动作执行. 这个思路就是发布订阅模式. 对应到vue,就是子去通知父亲刷新数据后子同步数据.

// 发布 emit 订阅 on {}
function Girl() {
    this._events = {}
}
Girl.prototype.on = function (eventName,callback) {

    if(this._events[eventName]){ // 不是第一次
        this._events[eventName].push(callback); // {失恋:[cry,eat,shopping]}
    }else{
        this._events[eventName] = [callback] //{失恋:[cry]}
    }
};
Girl.prototype.emit = function (eventName,...args) { //[我,你,他]
    // [].slice.call(arguments,1);
    // Array.from(arguments).slice(1);
    if(this._events[eventName]){
        this._events[eventName].forEach(cb=>cb(...args));
    }
};
let girl = new Girl();
let girl1 = new Girl();
let cry = (who) =>{console.log(who+'哭');};
let shopping = (who) =>{console.log(who+'购物');};
let eat = (who) =>{console.log(who+'吃');};
girl.on('失恋',cry); // {失恋:[cry]}
girl.on('失恋',eat); // {失恋:[cry,eat]}
girl.on('失恋',shopping); // {失恋:[cry,eat,shopping]}
girl1.emit('失恋');

本文思路:

- 先实现子获取父数据(单向绑定)
- 然后实现双向数据更新($on $emit)
    1.给父亲写改money的方法(但不要注册到父上) 
    2.将父改money方法传给子,$on
    3.子一旦想改数据,即会发射信息$emit给父,提示父该执行动作了.

- 双向更新简化: sync
    1.直接实现
    2.语法糖简化

<div id="app">
    money:{{money}} <br>
    <awsome :childmoney="money"></awsome>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
    let vm = new Vue({
        el: "#app",
        data: {
            money: 700,
        },
        components: {
            awsome: {
                data: function () {
                    return {count: 0}
                },
                props:['childmoney'],
                template: "<button @click='childmoney++'>childmoney: {{childmoney}}</button>"
            }
        }
    })
</script>
- 双向绑定3步走
// 1. 父亲定义更改自己money事件
            methods: {getMoney() {this.$emit('childthings', 1400);} 
// 2. 父将事件传给子, 
            childthings.$on('childthings',things)
// 3, 子在这里(相当于)触发父方法在父上执行
            awsome.$emit('childthings', 1400);
<div id="app">
    money:{{money}} <br>
    <!--2,父将事件传给子,
                      childthings.$on('childthings',things)-->
    <awsome :childmoney="money" @childthings="things"></awsome>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>

    //1. 单向数据更新不应该发生
    //2. 子想改变数据,应该通知父先改变, 父改变后,子自动刷新
    let vm = new Vue({
        el: "#app",
        data: {
            money: 700,
        },
        methods: {
            things(val) {                                           // 1.父亲定义更改自己money事件
                alert(val);
                this.money = val;
            }
        },
        components: {
            awsome: {
                data: function () {
                    return {count: 0}
                },
                props: ['childmoney'],
                methods: {
                    getMoney() {
                        this.$emit('childthings', 1400);            // 3, 子在这里(相当于)触发父方法在父上执行(函数名+参数)
                    }
                },
                template: "<button @click='getMoney'>childmoney: {{childmoney}}</button>"
            }
        }
    })
</script>
- 双向绑定的简写: sync

<div id="app">
    money:{{money}} <br>
    <h1>sync双向绑定1-1:</h1>
    <awsome :childmoney="money" @update:childmoeny="val=>this.money=val"></awsome>
    <h1>sync双向绑定1-2:</h1>
    <awsome :childmoney="money" @update:childmoeny="things"></awsome>
    <h1>sync双向绑定1-3: 简化写法</h1>
    <awsome :childmoney.sync="money"></awsome>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
    let vm = new Vue({
        el: "#app",
        data: {
            money: 700,
        },
        methods: {
            things(val) {
                alert(val);
                this.money = val;
            }
        },
        components: {
            awsome: {
                data: function () {
                    return {count: 0}
                },
                props: ['childmoney'],
                methods: {
                    getMoney() {
                        this.$emit('update:childmoney', 1400);  // 这里需要改成和上面父给子注册方法时相同的名字
                    }
                },
                template: "<button @click='getMoney'>childmoney: {{childmoney}}</button>"
            }
        }
    })
</script>

猜你喜欢

转载自www.cnblogs.com/iiiiiher/p/9030959.html