Vue 源码解析上Word格式文档下载.docx

上传人:b****4 文档编号:8161846 上传时间:2023-05-10 格式:DOCX 页数:9 大小:52.25KB
下载 相关 举报
Vue 源码解析上Word格式文档下载.docx_第1页
第1页 / 共9页
Vue 源码解析上Word格式文档下载.docx_第2页
第2页 / 共9页
Vue 源码解析上Word格式文档下载.docx_第3页
第3页 / 共9页
Vue 源码解析上Word格式文档下载.docx_第4页
第4页 / 共9页
Vue 源码解析上Word格式文档下载.docx_第5页
第5页 / 共9页
Vue 源码解析上Word格式文档下载.docx_第6页
第6页 / 共9页
Vue 源码解析上Word格式文档下载.docx_第7页
第7页 / 共9页
Vue 源码解析上Word格式文档下载.docx_第8页
第8页 / 共9页
Vue 源码解析上Word格式文档下载.docx_第9页
第9页 / 共9页
亲,该文档总共9页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

Vue 源码解析上Word格式文档下载.docx

《Vue 源码解析上Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《Vue 源码解析上Word格式文档下载.docx(9页珍藏版)》请在冰点文库上搜索。

Vue 源码解析上Word格式文档下载.docx

data:

function(){

return{

times:

1

};

},

created:

varme=this;

setInterval(function(){

me.times++;

},1000);

}

});

运行后,我们可以从页面中看到,count后面的times每隔1s递增1,视图一直在更新。

在代码中仅仅是通过setInterval方法每隔1s来修改vm.times的值,并没有任何DOM操作。

那么Vue.js是如何实现这个过程的呢?

我们可以通过一张图来看一下,如下图所示:

图中的模型(Model)就是data方法返回的{times:

1},视图(View)是最终在浏览器中显示的DOM。

模型通过Observer、Dep、Watcher、Directive等一系列对象的关联,最终和视图建立起关系。

归纳起来,Vue.js在这里主要做了三件事:

∙通过Observer对data做监听,并且提供了订阅某个数据项变化的能力。

∙把template编译成一段documentfragment,然后解析其中的Directive,得到每一个Directive所依赖的数据项和update方法。

∙通过Watcher把上述两部分结合起来,即把Directive中的数据依赖通过Watcher订阅在对应数据的Observer的Dep上。

当数据变化时,就会触发Observer的Dep上的notify方法通知对应的Watcher的update,进而触发Directive的update方法来更新DOM视图,最后达到模型和视图关联起来。

接下来我们就结合Vue.js的源码来详细介绍这三个过程。

Observer

首先来看一下Vue.js是如何给data对象添加Observer的。

我们知道,Vue实例创建的过程会有一个生命周期,其中有一个过程就是调用vm.initData方法处理data选项。

initData方法的源码定义如下:

!

-源码目录:

src/instance/internal/state.js-->

Vue.prototype._initData=function(){

vardataFn=this.$options.data

vardata=this._data=dataFn?

dataFn():

{}

if(!

isPlainObject(data)){

data={}

process.env.NODE_ENV!

=='

production'

&

&

warn(

'

datafunctionsshouldreturnanobject.'

this

}

varprops=this._props

//proxydataoninstance

varkeys=Object.keys(data)

vari,key

i=keys.length

while(i--){

key=keys[i]

//therearetwoscenarioswherewecanproxyadatakey:

//1.it'

snotalreadydefinedasaprop

//2.it'

sprovidedviaainstantiationoptionANDthereareno

//templateproppresent

props||!

hasOwn(props,key)){

this._proxy(key)

}elseif(process.env.NODE_ENV!

){

Datafield"

+key+'

"

isalreadydefined'

+

asaprop.Toprovidedefaultvalueforaprop,usethe"

default"

propoption;

ifyouwanttopasspropvaluestoaninstantiation'

call,usethe"

propsData"

option.'

this

//observedata

observe(data,this)

在initData中我们要特别注意proxy方法,它的功能就是遍历data的key,把data上的属性代理到vm实例上。

_proxy方法的源码定义如下:

Vue.prototype._proxy=function(key){

isReserved(key)){

//needtostorereftoselfhere

//becausethesegetter/settersmight

//becalledbychildscopesvia

//prototypeinheritance.

varself=this

Object.defineProperty(self,key,{

configurable:

true,

enumerable:

get:

functionproxyGetter(){

returnself._data[key]

},

set:

functionproxySetter(val){

self._data[key]=val

})

proxy方法主要通过Object.defineProperty的getter和setter方法实现了代理。

在前面的例子中,我们调用vm.times就相当于访问了vm.data.times。

在_initData方法的最后,我们调用了observe(data,this)方法来对data做监听。

observe方法的源码定义如下:

src/observer/index.js-->

exportfunctionobserve(value,vm){

value||typeofvalue!

object'

return

varob

if(

hasOwn(value,'

__ob__'

)&

value.__ob__instanceofObserver

){

ob=value.__ob__

}elseif(

shouldConvert&

(isArray(value)||isPlainObject(value))&

Object.isExtensible(value)&

!

value._isVue

ob=newObserver(value)

if(ob&

vm){

ob.addVm(vm)

returnob

observe方法首先判断value是否已经添加了ob属性,它是一个Observer对象的实例。

如果是就直接用,否则在value满足一些条件(数组或对象、可扩展、非vue组件等)的情况下创建一个Observer对象。

接下来我们看一下Observer这个类,它的源码定义如下:

exportfunctionObserver(value){

this.value=value

this.dep=newDep()

def(value,'

this)

if(isArray(value)){

varaugment=hasProto

?

protoAugment

:

copyAugment

augment(value,arrayMethods,arrayKeys)

this.observeArray(value)

}else{

this.walk(value)

Observer类的构造函数主要做了这么几件事:

首先创建了一个Dep对象实例(关于Dep对象我们稍后作介绍);

然后把自身this添加到value的ob属性上;

最后对value的类型进行判断,如果是数组则观察数组,否则观察单个元素。

其实observeArray方法就是对数组进行遍历,递归调用observe方法,最终都会调用walk方法观察单个元素。

接下来我们看一下walk方法,它的源码定义如下:

Observer.prototype.walk=function(obj){

varkeys=Object.keys(obj)

for(vari=0,l=keys.length;

i<

l;

i++){

this.convert(keys[i],obj[keys[i]])

walk方法是对obj的key进行遍历,依次调用convert方法,对obj的每一个属性进行转换,让它们拥有getter、setter方法。

只有当obj是一个对象时,这个方法才能被调用。

接下来我们看一下convert方法,它的源码定义如下:

Observer.prototype.convert=function(key,val){

defineReactive(this.value,key,val)

convert方法很简单,它调用了defineReactive方法。

这里this.value就是要观察的data对象,key是data对象的某个属性,val则是这个属性的值。

defineReactive的功能是把要观察的data对象的每个属性都赋予getter和setter方法。

这样一旦属性被访问或者更新,我们就可以追踪到这些变化。

接下来我们看一下defineReactive方法,它的源码定义如下:

exportfunctiondefineReactive(obj,key,val){

vardep=newDep()

varproperty=Object.getOwnPropertyDescriptor(obj,key)

if(property&

property.configurable===false){

//caterforpre-definedgetter/setters

vargetter=property&

property.get

varsetter=property&

property.set

varchildOb=observe(val)

Object.defineProperty(obj,key,{

functionreactiveGetter(){

varvalue=getter?

getter.call(obj):

val

if(Dep.target){

dep.depend()

if(childOb){

childOb.dep.depend()

for(vare,i=0,l=value.length;

e=value[i]

e&

e.__ob__&

e.__ob__.dep.depend()

returnvalue

functionreactiveSetter(newVal){

if(newVal===value){

if(setter){

setter.call(obj,newVal)

val=newVal

childOb=observe(newVal)

dep.notify()

defineReactive方法最核心的部分就是通过调用Object.defineProperty给data的每个属性添加getter和setter方法。

当data的某个属性被访问时,则会调用getter方法,判断当Dep.target不为空时调用dep.depend和childObj.dep.depend方法做依赖收集。

如果访问的属性是一个数组,则会遍历这个数组收集数组元素的依赖。

当改变data的属性时,则会调用setter方法,这时调用dep.notify方法进行通知。

这里我们提到了dep,它是Dep对象的实例。

接下来我们看一下Dep这个类,它的源码定义如下:

src/observer/dep.js-->

exportdefaultfunctionDep(){

this.id=uid++

this.subs=[]

//thecurrenttargetwatcherbeingevaluated.

//thisisgloballyuniquebecausetherecouldbeonlyone

//watcherbeingevaluatedatanytime.

Dep.target=null

Dep类是一个简单的观察者模式的实现。

它的构造函数非常简单,初始化了id和subs。

其中subs用来存储所有订阅它的Watcher,Watcher的实现稍后我们会介绍。

Dep.target表示当前正在计算的Watcher,它是全局唯一的,因为在同一时间只能有一个Watcher被计算。

前面提到了在getter和setter方法调用时会分别调用dep.depend方法和dep.notify方法,接下来依次介绍这两个方法。

depend方法的源码定义如下:

Dep.prototype.depend=function(){

Dep.target.addDep(this)

depend方法很简单,它通过Dep.target.addDep(this)方法把当前Dep的实例添加到当前正在计算的Watcher的依赖中。

接下来我们看一下notify方法,它的源码定义如下:

Dep.prototype.notify=function(){

//stablizethesubscriberlistfirst

varsubs=toArray(this.subs)

for(vari=0,l=subs.length;

subs[i].update()

notify方法也很简单,它遍历了所有的订阅Watcher,调用它们的update方法。

至此,vm实例中给data对象添加Observer的过程就结束了

下一节:

Vue.js是如何进行指令解析的。

请在文库中搜索Vue源码解析:

深入响应式原理(中)

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 工程科技

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2