vue数据双向绑定原理

vue数据双向绑定原理,第1张

vue.js 采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty() 来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。

首先我们为每个vue属性用Object.defineProperty()实现数据劫持,在监听数据的过程中,为每个属性分配一个订阅者集合的管理数组dep;然后在编译的时候在该属性的数组dep中添加订阅者 watcher,v-model会添加一个订阅者,{{}}也会,v-bind也会,只要用到该属性的指令理论上都会,接着为input会添加监听事件,修改值就会为该属性赋值,触发该属性的set方法,在set方法内通知订阅者数组dep,订阅者数组循环调用各订阅者的update方法更新视图。

实现步骤:修改输入框内容 =>在事件回调函数中修改属性值 =>触发属性的 set 方法=>发出通知 dep.notify() =>触发订阅者的 update 方法 =>更新视图。

流程图

在实例化一个Vue对象的时候,会传进去一个data对象,之后分成两个进程,一个进程是对挂载目标元素模板里的v-model和{{ }};两个指令进行编译。另一个进程是对传进去的data对象里面的数据进行监听。

上图中,observe是利用Object.defineProperty()对传入的data对象进行数据监听,在数据改变的时候触发该属性的set方法,更新该属性的值,并发布消息,我(该属性)的值变了。

compile是编译器,找到vue的指令v-model所在的元素,将data中该属性的值赋给元素的value,并给这个元素添加二级监听器,在元素的值改变的时候,将新值赋给data里面同名属性,这个时候就完成了单向数据绑定,视图 >>模型。

那么最终的由模型到视图的更新,依赖于dep和watcher,dep会收集订阅者,就是绑定了data里面属性的元素,在数据更新的时候,会触发该属性的set方法,在set里触发该属性的消息发布通知函数。而Watcher根据收到的数据变化通知,更新相应的数据。

dep这个东东给大家解释一下,就是data里的每个属性都有一个dep对象,dep对象里可以有很多订阅者(watcher),但是只有一个添加订阅者的方法和一个发布变化通知的方法,就是模板上可以有多处元素绑定data里的同一个属性值,所以dep是依赖于data里面的属性的。

而Watcher是每个{{ }}有一个,初次编译的时候,会在new的时候自动更新一下模板的数据,等到下次数据改变的时候,由dep通知数据更新,直接调用watcher的update方法,更新模板的绑定数据。

observer 模块共分为这几个部分:

示意图如下:

Observer的构造函数

value是需要被观察的数据对象,在构造函数中,会给value增加 ob 属性,作为数据已经被Observer观察的标志。如果value是数组,就使用observeArray遍历value,对value中每一个元素调用observe分别进行观察。如果value是对象,则使用walk遍历value上每个key,对每个key调用defineReactive来获得该key的set/get控制权。

Dep是Observer与Watcher之间的纽带,也可以认为Dep是服务于Observer的订阅系统。Watcher订阅某个Observer的Dep,当Observer观察的数据发生变化时,通过Dep通知各个已经订阅的Watcher。

Watcher是用来订阅数据的变化的并执行相应 *** 作(例如更新视图)的。Watcher的构造器函数定义如下:

参数中,vm表示组件实例,expOrFn表示要订阅的数据字段(字符串表示,例如a.b.c)或是一个要执行的函数,cb表示watcher运行后的回调函数,options是选项对象,包含deep、user、lazy等配置。

Object.defineProperty(obj, prop, descriptor) ,这个语法内有三个参数,分别为 obj (要定义属性的对象) prop (要定义或修改的属性的名称或 Symbol ) descriptor (要定义或修改的属性描述符=>具体的改变方法)

简单地说,就是用这个方法来定义一个值。当调用时我们使用了它里面的get方法,当我们给这个属性赋值时,又用到了它里面的set方法;

主要解释第三个参数{

value: 设置属性的值

writable: 值是否可以重写。true | false

enumerable: 目标属性是否可以被枚举。true | false(就是能不能被遍历出来)

configurable: 目标属性是否可以被删除或是否可以再次修改特性 true | false

set: 目标属性设置值的方法

get:目标属性获取值的方法

}

set是一个函数,接收一个新值,会在值被重写或修改的时候触发这个函数

get是一个函数,返回一个值,会在属性被调用的时候触发。

Object.defineProperty()详解

Object.defineProperty()官方文档

已经了解到vue是通过数据劫持的方式来做数据绑定的,其中最核心的方法便是通过Object.defineProperty()来实现对属性的劫持,那么在设置或者获取的时候我们就可以在get或者set方法里假如其他的触发函数,达到监听数据变动的目的。

我们知道通过Object.defineProperty()可以实现数据劫持,它的属性在赋值的时候触发set方法,

当然要是这么粗暴,肯定不行,性能会出很多的问题。

observer用来实现对每个vue中的data中定义的属性循环用Object.defineProperty()实现数据劫持,以便利用其中的setter和getter,然后通知订阅者,订阅者会触发它的update方法,对视图进行更新。

为什么要订阅者 :在vue中v-model,v-name,{{}}等都可以对数据进行显示,也就是说假如一个属性都通过这三个指令了,那么每当这个属性改变的时候,相应的这个三个指令的html视图也必须改变,于是vue中就是每当有这样的可能用到双向绑定的指令,就在一个Dep中增加一个订阅者,其订阅者只是更新自己的指令对应的数据,也就是v-model='name'和{{name}}有两个对应的订阅者,各自管理自己的地方。每当属性的set方法触发,就循环更新Dep中的订阅者。

订阅发布模式(又称观察者模式)定义了一种一对多的关系,让多个观察者同时监听某一个主题对象,这个主题对象的状态发生改变时就会通知所有观察者对象。

发布者发出通知 =>主题对象收到通知并推送给订阅者 =>订阅者执行相应 *** 作

举个例子:

2.实现compile: compile的目的就是解析各种指令称真正的html。

这样一来就实现了vue的数据双向绑定。

参考链接:

理解VUE双向数据绑定原理和实现---赵佳乐

Vue的双向数据绑定原理

vue双向绑定原理分析

Vue原理解析之observer模块

深入响应式原理

既然清楚了原理,那么,接下来进入正题——我知道了vue怎么安装,那么我怎么使用呢?

在告诉你基础用法之前,我还是要先告诉你一个情况。

可能要令你有点失望。vue主要是侧重于数据端的。他的目的就是渲染数据和在前端调整一下数据逻辑。

他不是像jquery那样让你用来做特技的。就算你要做特技。你也应该通过css3/canvas而不是dom。

所谓的双向绑定,你可以理解就是把view。(你还不清楚mvc的话,请看第一章)

和model绑定到一起。说白了,就是你js中的绑定值变了。你dom中的内容就跟着一块变了。

vue是通过解析{{文字..}}来生成内容的。后面绑定方法,输出内容的时候都会讲到。

列表输出使用 v-for,这些v开头加横杠的叫做命令

这些命令是可以自定义的。但是那都属于高级 *** 作,我们不用它也完全足够支撑做一个大型项目了。

其实你回发现,这里无论是v-for或者是v-什么其他玩意

它都深刻的遵循了es6的语法。这里不就是一个典型的for in 循环吗。不过我们现在都用for of了。

你记住这个用法,它就长这样。

前后端分离开发的关键在于:后台只提供接口。

我们获得的数据多数情况下,仅仅是一个json,而mvvm的关键就再于解析数据在前端完成了。如果你了解jsp或者php你会了解,数据的解析在mvc中,

是由后端完成的,而html只负责显示。

所以,当你了解了数据绑定和渲染以后,你可以第一时间先把数据输出到页面了。

我们前端最厉害的地方不就是处理能看得见的东西吗?


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/9945269.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-03
下一篇 2023-05-03

发表评论

登录后才能评论

评论列表(0条)

保存