JavaScript实现简单的双向数据绑定

什么是双向数据绑定

双向数据绑定简单来说就是UI视图(View)与数据(Model)相互绑定在一起,当数据改变之后相应的UI视图也同步改变。反之,当UI视图改变之后相应的数据也同步改变。

双向数据绑定最常见的应用场景就是表单输入和提交。一般情况下,表单中各个字段都对应着某个对象的属性,这样当我们在表单输入数据的时候相应的就改变对应的对象属性值,反之对象属性值改变之后也反映到表单中。

目前流行的 MVVM 框架(Angular、Vue)都实现了双向数据绑定,这样也就实现了视图层和数据层的分离。相信使用过 jQuery 的人都知道,往往我们在获取到数据之后就直接操作 DOM ,这样数据操作和 DOM 操作就高度耦合在一起了。

JavaScript实现简单的双向数据绑定

实现方式 发布者-订阅者模式

这种实现方式就是使用自定义的 data 属性在 HTML 代码中指明绑定。所有绑定起来的 JavaScript 对象以及 DOM 元素都将 “订阅” 一个发布者对象。任何时候如果 JavaScript 对象或者一个 HTML 输入字段被侦测到发生了变化,我们将代理事件到发布者-订阅者模式,这会反过来将变化广播并传播到所有绑定的对象和元素。具体实现可看这篇文章:

脏值检查

Angularjs(这里特指AngularJS 1.x.x版本,不代表AngularJS 2.x.x版本)双向数据绑定的技术实现是脏值检查。原理就是:Angularjs内部会维护一个序列,将所有需要监控的属性放在这个序列中,当发生某些特定事件时(并不是定时的而是由某些特殊事件触发的,比如:DOM事件、XHR事件等等),Angularjs会调用 $digest 方法,这个方法内部做的逻辑就是遍历所有的 watcher,对被监控的属性做对比,对比其在方法调用前后属性值有没有发生变化,如果发生变化,则调用对应的 handler。

这种方式的缺点很明显,遍历轮训 watcher 是非常消耗性能的,特别是当单页的监控数量达到一个数量级的时候。

访问器监听

vue.js 实现数据双向绑定的原理就是访问器监听。它使用了 ECMAScript5.1(ECMA-262)中定义的标准属性 方法。通过 Object.defineProperty 设置各个属性的 setter,getter,在数据变动时更新UI视图。

实现

本文将采用 访问器监听 这种方式来实现一个简单的双向数据绑定,主要实现:

**_obverse**:对数据进行处理,重写相应的 set 和 get 函数

**_complie**:解析指令(e-bind、e-model、e-click)等,并在这个过程中对 view 与 model 进行绑定

Watcher:作为连接 _obverse 和 _complie 的桥梁,用来绑定更新函数,实现对视图的更新

首先看下我们的视图代码:

<!DOCTYPE html> <head> <meta charset=http://www.likecs.com/"UTF-8"> <meta name=http://www.likecs.com/"author" content=http://www.likecs.com/"赖祥燃, laixiangran@163.com, "/> <title>实现简单的双向数据绑定</title> <style> #app { text-align: center; } </style> <script src=http://www.likecs.com/"eBind.js"></script> <script> window.onload =http://www.likecs.com/ function () { new EBind({ el: '#app', data: { number: 0, person: { age: 0 } }, methods: { increment: function () { this.number++; }, addAge: function () { this.person.age++; } } }); }; </script> </head> <body> <div id=http://www.likecs.com/"app"> <form> <input type=http://www.likecs.com/"text" e-model=http://www.likecs.com/"number"> <button type=http://www.likecs.com/"button" e-click=http://www.likecs.com/"increment">增加</button> </form> <h3 e-bind=http://www.likecs.com/"number"></h3> <form> <input type="text" e-model="person.age"> <button type="button" e-click="addAge">增加</button> </form> <h3 e-bind="person.age"></h3> </div> </body>

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpgxxp.html