博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
数据绑定:模型到视图
阅读量:5030 次
发布时间:2019-06-12

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

Object.defineProperty

听说vuejs和avalon都是使用这种方式实现的。

Object.defineProperty最早是由IE8实现的,但是IE8的实现有许多问题而且不能hack。。。所以vuejs才支持IE9+,avalon才使用VBScript这个鬼。

我们可以在Object.defineProperty里用getter和setter方法来定义对象的属性,这个属性叫存储器属性(JavaScript权威指南的翻译,JavaScript高级程序设计翻译为访问器属性,英文:accessor property)。当读取属性的时候,会调用getter方法,设置属性时,就会调用setter方法。

所以,setter方法就给了我们无限可能,自然就可以将数据的变化反映到视图上去。我们看一个例子(改自JavaScript高级程序设计的代码):

html,就一行:

js:

var bookName = document.getElementById('bookName')var book = {    _year: 2004,    edition: 1};Object.defineProperty(book, "year", {    get: function(){        return this._year;    },    set: function(newValue){     if (newValue > 2004) {          this._year = newValue;          bookName.textContent = newValue;          this.edition += newValue - 2004;        }    }});book.year = 2005;

我们定义了一个book对象,并给了他一个year的属性,读取year的返回_year的值,设置year的时候,_year也随之变化,并且给div的textContent也赋上了新值。就这样完成了简单的模型到视图的绑定。

Object.observe

接下来我们要祭出ES7的神器了——Object.observe。

Object.observe(),作为未来ECMAScript标准的一部分,是一个用于异步监听JavaScript对象变化的方法,并且无需使用额外的JavaScript库。它允许监听器接受一个按时间顺序排列的变更记录序列,这些变更记录描述了被监听对象所发生变化的内容的集合。

不过它的支持情况就没那么让人兴奋了(来自Can I Use):

它的使用更加简单。

还是上面的那一条html代码,js现在是这样:

var book = {    year: 2004,    edition: 1};var bookName = document.getElementById('bookName')function observer(changes) {    bookName.textContent = changes[0].object[changes[0].name];}Object.observe(book, observer)book.year = 2005;

 

当book的值发生变化的时候,就会触发observer函数,设置div的值。同样完成了数据到模型的绑定。

脏检查

Angular和Regular都使用了脏检查。

脏检查中,都有一个watch方法来监视着数据的变化,检测到数据变化时就会触发监听的回调,在回调里处理相应的逻辑。但是我们如何知道数据变化了呢。

这里会有一个digest方法,在这个方法里,检查新值和旧值是否相等,如果不相等,就会触发监听回调。一直循环这个过程,直到两者相等。

框架大多数情况下都会自动进入digest,同时也会暴露接口给用户,自主触发。

这里有一个简化的实现:

var Scope = function() {    this.$$watchers = [];}Scope.prototype.$watch = function(watchExp, listener) {    this.$$watchers.push({        watchExp: watchExp,        listener: listener || function() {}    });}Scope.prototype.$digest = function() {    var dirty;    do {        dirty = false;        for(var i = 0; i < this.$$watchers.length; i++) {            var newValue = this.$$watchers[i].watchExp(),                oldValue = this.$$watchers[i].last;            if(oldValue !== newValue) {                this.$$watchers[i].listener(newValue, oldValue);                dirty = true;                this.$$watchers[i].last = newValue;            }        }    } while(dirty);}

(来自)

我们可以这样使用,html代码: <input type="text"> 

js:

var $scope = new Scope();$scope.name = 'zjzhome';$scope.$watch(function() {    return $scope.name;}, function(newValue, oldValue) {    console.log('Input value updated - it is now ' + newValue);    element.value = $scope.name;});var element = document.querySelector('input');function updateScopeValue() {    $scope.name = 'Bob';    $scope.$digest();};updateScopeValue();

你会发现input显示为Bob了。

这里同时也能够进行视图到模型的绑定,只要监听input的keyup事件即可:

element.onkeyup = function() {    $scope.name = element.value;    $scope.$digest();}

MVVM框架中实现远比这些复杂。了解下基本的原理对于迅速的掌握框架的使用也是好的。

转载于:https://www.cnblogs.com/jiangxiaobo/p/5954027.html

你可能感兴趣的文章
php pathinfo()的用法
查看>>
firefox的console log功能
查看>>
Eclipse中的TreeViewer类和ListViewer类
查看>>
[改善Java代码]用枚举实现工厂方法模式更简洁
查看>>
iOS开发网络篇—数据安全
查看>>
dede判断当前文章
查看>>
初见《构建之法》orz……
查看>>
mysql中把一个表的数据批量导入另一个表中
查看>>
Spring MVC的多视图解析器配置及与Freemarker的集成
查看>>
20160930
查看>>
mpvue学习笔记
查看>>
[App Store Connect帮助]六、测试 Beta 版本(4.3) 管理 Beta 版构建版本:为 Beta 版构建版本提供出口合规证明...
查看>>
[Swift-2019力扣杯春季初赛]2. 校园自行车分配
查看>>
SQL SERVER将远程服务器的数据库备份到本地文件夹
查看>>
[LeetCode] 628. Maximum Product of Three Numbers_Easy
查看>>
[Java in NetBeans] Lesson 06. Custom classes
查看>>
[AngularFire2 & Firestore] Example for collection and doc
查看>>
[Javascript] The "this" keyword
查看>>
ElasticSearch-5.3.1集群环境搭建,安装ElasticSearch-head插件,安装错误解决
查看>>
sharepoint Report使用共享数据源部署报错
查看>>