本文章信息点
- 双向数据绑定原理(vue)
- 如何设计搭建自己的框架
- 代码暂略,详见,github [地址]https://github.com/yyccmmkk/Bi-directionalDataBindingDemo
什么是单向什么是双向?
单向指是数据从model流向view
双向是在单向的基础上数据再从view 流向model。
双向数据绑定原理
相信很多人看过很多双向数据绑定原理相关文章,多半看的一头雾水,看完仍然写不出一个简单的demo 框架,根本不知道为什么要这样做?主要原因是因为没有整理清楚双向数据绑定的需求,因为所有的代码逻辑实现都是围绕需求展开,所以下面会围绕需求展开,再细解如何实现这些需求,从整体逻辑上打通每一环最终实现双向数据绑定框架。所谓万剑归宗、殊途同归,需求是一样的,所以最终的实现也都将大同小异,原理自然而然显现。
简单的说是这样的,
初次模板与数据渲染时,监听数据每个属性的每次调用(通过getter实现),并给其属性添加观察者。监听数据的每个属性变更(通过setter实现),并通知与其相关的观察者,观察者调用自身的更新方法更新view。扫描模板时,找到双向绑定指令,并绑上指定事件,事件触发后更新数据,数据更新触发单向绑定逻辑 view 更新。
说的太简单很多人对细节不清楚,说的细了就是后面的长篇大论了。
相信很多人的疑问有像下面这些的:
观察者只是抽象概念,
- 它具体实现是什么?
- 为什么同一个属性不只一个观察者?
- 又在什么时候添加的?
- 观察者添加到哪了?
- 每个观察者的更新方法又是怎么确定的?
如何设计实现
单向、双向数据绑定是如何实现的呢?假如现在要写一个双向绑定框架要如何设计呢?
单向数据绑定需求可以简单的抽象为:将数据和模板进行某种绑定,数据中的某个属性值发生变化时,属性对应的模板和新值进行处理更新UI(移除旧的UI插入新的UI)。
双向数据绑定需求可以简单的抽象为:在单向的基础上,给特定元素(input 、textarea等)绑定指定事件,并将新值更新到数据,数据更改触发单向数据绑定逻辑,更新UI中相关属性绑定。
通过上面的简单分析,就可以发现"模板"相关需求需要用节点操作来实现,因为需要给特定元素绑定事件,要处理元素中的指令,必定要对模板中每一个节点进行遍历,并对每个节点的属性进行遍历。
下面会逐步分析需求,再将每个需求再细化就可以得到完整的需求,最后实现这些需求。
需求点分析
- 将数据的每一个属性与相对应的模板建立联系,数据属性值变更时view进行更新
- 监听数据所有属性的修改包括值的属性的修改
- 如何找到属性对应的模板
- 如何将数据属性与其对应模板建立链接
- 将数据新值更新到view
- 将特定元素的指定事件回馈到数据,数据被修改,同时与些数据相关view更新
- 监听指定元素的指定事件,并将新值赋值给数据,数据被修改触发view更新逻辑
【1.1解决思路】
数据属性的读写可以通过设置getter setter实现,通过Object.defineProperty()方法设置。 写一个方法递归的处理数据的每个属性不是什么难事。代码暂略,详见,github [地址]https://github.com/yyccmmkk/Bi-directionalDataBindingDemo
【1.2解决思路】
我们需要一个compiler 对模板的每一个节点进行扫描分析,分板当前节点是否有指令(插值表达式、单向数据绑定、双向数据绑定,事件绑定等)。如果有指令,找到当前指令相关的数据属性,当前节点即为'模板'(ps:数据更新时更样的节点)。
【1.3解决思路】
当compiler 对节点分析时如果找到指令,则给该指令相关的属性的更新列表,添加一个watcher实例,该实例包含渲染相关‘模板’(ps:当前扫描到的节点)
【1.4解决思路】
在1.1中对所有数据属性进行监听时,为每一个属性挂载一个对象(实际上是闭包),该对象拥有一个notify方法,还拥有一个值为数组的list 属性,list 中存放的是当前属性相关的 watcher实例,该实例在1.3(模板解析) 时生成并添加进来,该实例拥有一个update 方法,用来更新view; 当属性值变化时,调用相关必包中的notify 方法,该方法遍历list 中的每一个watcher 实例,并调用该实例的update 方法,upadate方法会在1.3(模板解析)时根据指令生成相关update 方法。本demo 中闭包对象是watcher 类来构造,也可以分开。
以上只是粗枝大叶的整个逻辑分析,细节还有很多,比如:指令解析,管道符解析,指令表达式解析,插槽(用以标记更新时插入点),需要销毁节点等,后续整理出来,计划搞一个系列文章,比如模板指令解析如何进行等,本demo 也有点粗造有时间吧整理一下,以后像虚拟dom的可以搞一搞,像生命周期钩子有了大框架要加也不是很困难,等以后细化再更新。
因精力有限。。。今日到此(未完待续)