Vue.js有两个核心功能,一个是响应数据绑定系统,另一个是组件系统。本文只探讨如何实现hello world的双向绑定,几乎所有Vue的开篇介绍都提到了这一点。先讲涉及的知识点,再参考源代码,用尽可能少的代码实现hello world的开篇示例。
参考文章://www . JB 51 . net/article/100819 . htm
首先,访问器属性
访问器属性是对象中的一个特殊属性,不能直接在对象中设置,但必须由defineProperty()方法单独定义。
var obj={ };//为obj (obj、' hello '、{get:function () {returnsth}、set 3360 function(val){/* dosth */})obj定义名为hello的访问器属性。hello//可以像普通属性一样读取访问器属性。
存取器属性的“值”是特殊的。读取或设置访问器属性的值实际上是调用其内部特性:获取和设置函数。
Obj.hello //读取属性就是调用get函数并返回get函数的返回值
Obj.hello='abc' //给属性赋值就是调用set函数,赋值实际上就是参数传递
get和set方法内部指向obj,这意味着get和set函数可以操作对象内部的值。此外,访问器属性将“覆盖”同名的公共属性,因为访问器属性将被优先访问,同名的公共属性将被忽略(也就是说,它将被“劫持”)。
二是最小双向绑定的实现
这个例子的效果是:随着文本框中输入文本的变化,相同的文本内容会在跨度内同步显示;在js或控制台中显式修改obj.name的值,视图将相应更新。这样实现了model=view和view=model的双向绑定,具有响应性。
以上就是Vue实现双向绑定的基本原理。
第三,分解任务
以上例子只是为了说明原理。我们最终想要实现的是:
首先,任务被分成几个子任务:
1.输入框与文本节点和数据之间的数据绑定
2.当输入框的内容发生变化时,数据中的数据也会同步变化。也就是说,观点的改变=模式。
3.当数据中的数据发生变化时,文本节点的内容也会同步变化。也就是模型=视图的变化。
为了实现任务一,需要编译DOM。这里有一个知识点:DocumentFragment。
四.文档片段
一个DocumentFragment可以看作一个节点容器,它可以包含多个子节点。当我们把它插入到DOM中时,只有它的子节点才会被插入到目标节点中,所以我们把它看作是一组节点的容器。使用DocumentFragment处理节点比直接操作DOM要快得多,也更好。当Vue编译时,它将装载目标的所有子节点劫持(真正劫持)到DocumentFragment中。经过一些处理后,它将文档片段作为一个整体返回,以插入到装载目标中。
动词(verb的缩写)数据初始化绑定
上面的代码实现了任务一,我们可以看到hello world已经呈现在输入框和文本节点中。
第六,响应性数据绑定
让我们来看看任务2的实现思路:当我们在输入框中输入数据时,首先触发输入事件(或keyup、change事件)。在相应的事件处理程序中,我们获取输入框的值,并将其分配给vm实例的文本属性。我们将使用defineProperty将数据中的文本劫持为vm的访问器属性,因此为vm赋值。text将触发set方法。set方法主要做两件事,第一件是更新属性值,第二件是等到任务三。
任务2完成,文本属性值将与输入框内容同步变化:
七、订阅/发布模式(subscribepublish)
文本属性已更改,set方法已触发,但文本节点的内容未更改。同样绑定到文本的文本节点如何同步变化?这里还有一个知识点:订阅发布模式。
订阅发布模式(也称为观察者模式)定义了一对多关系,允许多个观察者同时监视一个主体对象,并在主体对象状态发生变化时通知所有观察者。
发布者发送通知=主题对象接收通知并将其推送给订阅者=订阅者执行相应的操作
如前所述,触发set方法后要做的第二件事就是以发布者的身份发布通知:“我是属性文本,我变了”。文本节点充当订阅者,并在收到消息后执行相应的更新操作。
八、实现双向绑定
回过头来看,每当new是一个Vue,它主要做两件事:第一件是听数据:观察(data),第二件是编译HTML: nodeofcreation (id)。
在监控数据的过程中,会为数据中的每个属性生成一个主题对象dep。
在编译HTML的过程中,会为每个与数据绑定相关的节点生成一个订阅者观察器,观察器会将自己添加到相应属性的dep中。
我们实现了修改输入框内容=在事件回调函数中修改属性值=触发属性的设置方法。
接下来我们要实现的是:发出通知dep.notify()=触发订阅者的更新方法=更新视图。
这里的关键逻辑是如何将观察器添加到关联属性的dep中。
在编译HTML的过程中,会为与数据关联的每个节点生成一个Watcher。Watcher函数中发生了什么?
首先,给自己分配一个全局变量Dep.target;
其次,执行更新方法,然后执行get方法。get方法读取vm的访问器属性,这会触发访问器属性的get方法。在get方法中,观察器被添加到相应访问器属性的dep中。
同样,获取属性值,然后更新视图。
最后,将Dep.target设置为空。因为它是一个全局变量,也是观察者和dep之间的唯一桥梁,所以Dep.target在任何时候都只能有一个值。
至此,hello world双向绑定基本实现。文本内容会随着输入框的内容同步变化,在控制器中修改vm.text的值也会同步体现在文本内容中(但输入框还没有绑定,读者可以自行尝试)。
完整代码:https://github.com/bison1994/two-way-data-binding
以上就是本文的全部内容。希望对大家的学习有帮助,支持我们。