博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
vue数据双向绑定原理-wather
阅读量:6159 次
发布时间:2019-06-21

本文共 2643 字,大约阅读时间需要 8 分钟。

1508320579801.jpg

​​

vue数据双向绑定原理, 和简单的实现,本文将实现mvvm的 Watcher

上面的步骤已经实现了监听器, 和订阅器, 当属性发生改变,发出通知, 那么这个通知 是通知谁呢,肯定是订阅者 watcher.

Watcher订阅者作为Observer和Compile之间通信的桥梁,主要做的事情是:

1、在自身实例化时往属性订阅器(dep)里面添加自己

2、自身必须有一个update()方法
3、待属性变动dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调,则释放自己。

// Watcherfunction Watcher(vm, exp, cb) {    this.cb = cb;    this.$vm = vm;    this.exp = exp;    // 此处为了触发属性的getter,从而在dep添加自己,结合Observer更易理解    this.value = this.get(); // 将自己添加到订阅器的操作}Watcher.prototype = {    update: function() {        this.run();    // 属性值变化收到通知    },    run: function() {        var value = this.get(); // 取到最新值        var oldVal = this.value;        if (value !== oldVal) {            this.value = value;            this.cb.call(this.$vm, value, oldVal); // 执行Compile中绑定的回调,更新视图        }    },    get: function() {        Dep.target = this;    // 将当前订阅者指向自己,缓存        var value = this.$vm[this.exp];    // 强制触发监听的getter,添加自己到属性订阅器中        Dep.target = null;    // 添加完毕,重置释放        return value;    }};

订阅者要缓存自己, 并且告诉监听器, 要把我加到订阅器里面去. 所以还要改造下 监听器

function defineReactive(data, key, val) {    var dep = new Dep()    observe(val); // 监听子属性    Object.defineProperty(data, key, {      .......        get: function () {            // 由于需要在闭包内添加watcher,所以可以在Dep定义一个全局target属性,暂存watcher, 添加完移除            Dep.target && dep.addDep(Dep.target);            return val;        },.......    });}

实例化Watcher的时候,调用get()方法,通过Dep.target = watcherInstance标记订阅者是当前watcher实例,强行触发属性定义的getter方法,getter方法执行的时候,就会在属性的订阅器dep添加当前watcher实例,从而在属性值有变化的时候,watcherInstance就能收到更新通知。

实现MVVM

到这儿先将监听器 Observer 和监听者Watcher 连起来, 先模拟一些数据,实现简单的数据绑定

这可以看到 div的和内容初始为 hello world , 每隔一秒之后变换为 chuchur 加时间戳,虽然是实现了, 但是与想象的还差很多. 是vue.name 不是 vue.data.name ,所以这里需要给Vue实例添加一个属性代理的方法,使访问vm的属性代理为访问vm.data的属性,改造后的代码如下:

function Vue(options) {   this.$options = options || {};   this.data = this.$options.data;   // 属性代理,实现 vm.xxx -> vm.data.xxx   var self = this;   Object.keys(this.data).forEach(function (key) {      self.proxy(key); // 绑定代理属性   });   observe(this.data, this);​   el.innerHTML = this.data[exp]; // 初始化模板数据的值   new Watcher(this, exp, function (value) {      el.innerHTML = value;   });   return this;}Vue.prototype = {    proxy: function (key) {        var self = this;        Object.defineProperty(this, key, {            enumerable: false,            configurable: true,            get: function proxyGetter() {                return self.data[key];            },            set: function proxySetter(newVal) {                 self.data[key] = newVal;            }        });    }}

然后就可以通过vue.name,直接改版模板的数据了, 下一步就要实现 解析器Complie

[完]

转载于:https://www.cnblogs.com/chuchur/p/9396995.html

你可能感兴趣的文章
Linux macos 常用终端操作
查看>>
企业网络的管理思路
查看>>
Linux磁盘分区与挂载
查看>>
J2se学习笔记一
查看>>
DNS视图及日志系统
查看>>
老李分享:Android性能优化之内存泄漏 3
查看>>
mysql命令
查看>>
来自极客标签10款最新设计素材-系列七
查看>>
极客技术专题【009期】:web技术开发小技巧
查看>>
PHP 简单计算器代码实现
查看>>
正则表达式的知识普及
查看>>
docker使用笔记
查看>>
华为eNSP模拟器上实现FTP服务
查看>>
【全球AI人才排行榜】美国第一,中国仅排名第7
查看>>
微信小程序输入框input
查看>>
MySql字符串函数使用技巧
查看>>
Doc2Vec,Word2Vec文本相似度 初体验。
查看>>
系统ghost后变成一个盘了别的分区的文件怎么找回
查看>>
Win7+Ubuntu11
查看>>
请问华为三层交换机里面的那个从IP是个什么意思? -
查看>>