Vue学习之双向数据绑定

介绍

实现原理

vue.js 2.0 是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
在这里插入图片描述

实现步骤(v-model)

在这里插入图片描述

第一步:
需要observe的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter和getter
这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化

第二步:compile解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图

第三步:Watcher订阅者是Observer和Compile之间通信的桥梁,主要做的事情是:
1、在自身实例化时往属性订阅器(dep)里面添加自己
2、自身必须有一个update()方法
3、待属性变动dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调,则功成身退。

第四步:MVVM作为数据绑定的入口,整合Observer、Compile和Watcher三者,通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据model变更的双向绑定效果。

实例

代码

/v-model/index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Title</title>
</head>
<body>
    订阅视图-1:<span class="box-1"></span>
    <br/>
    订阅视图-2:<span class="box-2"></span>
</body>
<script src="index.js"></script>
<script>
    let dataObj = {};
    dataHijack({
        data: dataObj,
        tag: 'view-1',
        datakey: 'one',
        selector: '.box-1'
    });
    dataHijack({
        data: dataObj,
        tag: 'view-2',
        datakey: 'two',
        selector: '.box-2'
    });

    // 初始化赋值
    dataObj.one = "init-1";
    dataObj.two = "init-2";
</script>
</html>

/v-model/index.js

// 订阅者模型
let Dep = {
    // 容器
    clientList: {}, // 浅拷贝
    // 添加订阅者
    listen: function (key ,fn) {
        // 短路运算符
        (this.clientList[key] || (this.clientList[key] = [])).push(fn)
    },
    // 发布消息
    trigger: function () {
        // 类数组转数组
        let key = Array.prototype.shift.call(arguments);
            fns = this.clientList[key];
        if(!fns || fns.length === 0) {
            return false
        }
        for (let i = 0, fn; fn = fns[i++];){
            fn.apply(this, arguments)
        }
    }
};

// 劫持方法
let dataHijack = function ({data, tag, datakey, selector}) {
    let value = '',
        el = document.querySelector(selector);
    // 数据劫持
    Object.defineProperty(data, datakey, {
        get: function () {
            return value
        },
        set: function (newValue) {
            value = newValue;
            Dep.trigger(tag, newValue)
        }
    });
    // 绑定观察者
    Dep.listen(tag, function (text) {
        el.innerHTML = text
    })
};

效果

初始化
在这里插入图片描述
修改值
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值