博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Vue结构
阅读量:5020 次
发布时间:2019-06-12

本文共 2821 字,大约阅读时间需要 9 分钟。

转自:https://www.jianshu.com/p/90b762f1f649

架构图

先看下Vue源码的基本架构图:

 
vue源码结构.png
Vue的设计可以概括成两部分:
响应式数据
节点挂载。简单来讲,前者是设计数据的getter和setter方法,保证get和set时触发视图的更新;后者是解析视图的结构,生成相应的directive(指令),视图的更新是由directive完成的。

 

响应式数据

Vue进行实例化时,会执行_init函数,_init包括了以下几个执行步骤:

Vue.prototype._initState = function () {    this._initProps() this._initMeta() this._initMethods() this._initData() this._initComputed() }
  • _initProps 处理props属性,在Component中会使用到props属性
  • _initMeta 处理诸如$index, $key & $value等meta信息
  • _initMethods 把methods属性中包含的方法绑定到Vue实例上,并且指定其作用域为该Vue的实例
  • _initData 给数据的每个字段添加响应逻辑,数据获取(getter)时会更新依赖,数据设置(setter)时会通知依赖进行更新
  • _initComputed computed属性中方法的执行和计算,同时生成Watcher实例,Watcher负责关联数据和directive
_initData

_initData 的主要功能是给data中所有字段都加上响应式设计。当字段进行get操作时,更新订阅当前字段的Watcher对象,也就是更新依赖;当字段set时,通知Watcher对象,Watcher对象会通知directive对象进行进行View的改变。 Watcher在数据(data)和指令(directive)之间充当数据桥梁的作用。它的主要逻辑集中在defineReactive函数:

function defineReactive (obj, key, val) { var dep = new Dep() // dep对象负责维护订阅列表(对数据而言,就是Watcher对象) ... var childOb = observe(val) // 迭代遍历执行 Object.defineProperty(obj, key, { enumerable: true, configurable: true, get: function reactiveGetter () { var value = getter ? getter.call(obj) : val if (Dep.target) { // Dep.target是个Watcher对象实例 dep.depend() // 把Dep.target这个Watcher对象加入到dep的subs列表中 if (childOb) { // 迭代更新字段的子字段 childOb.dep.depend() } ... } return value }, set: function reactiveSetter (newVal) { var value = getter ? getter.call(obj) : val if (newVal === value) { return } if (setter) { setter.call(obj, newVal) } else { val = newVal } childOb = observe(newVal) // 此处会调用依赖列表的watcher进行数据视图的同步! // watcher会调用directive的更新方法 dep.notify() } }) }

挂载节点

普通节点

节点的挂载主要逻辑在在_compile中,它对挂载的root节点和子节点分开处理。 对root节点,执行的流程:

_compile -> compileRoot -> compileDirectives -> vm._bindDir -> directive._bind

vm._bindDir 会依据节点的指令生成directive对象实例,然后调用directive的_bind方法实现directive和Watcher的关联:

Directive.prototype._bind = function () {  var name = this.name var descriptor = this.descriptor // initial bind // 调用directive 如 on click的bind方法 if (this.bind) { this.bind() } ... // 生成watcher对象,watcher对象实例化时 会执行get方法 进行一次数据的依赖收集 var watcher = this._watcher = new Watcher( this.vm, this.expression, this._update, // callback { filters: this.filters, twoWay: this.twoWay, deep: this.deep, preProcess: preProcess, postProcess: postProcess, scope: this._scope } ) // v-model with inital inline value need to sync back to // model instead of update to DOM on init. They would // set the afterBind hook to indicate that. if (this.afterBind) { this.afterBind() } else if (this.update) { this.update(watcher.value) } } this._bound = true }

对于非root节点,有一个迭代遍历解析的过程,基本的执行过程相同。

Component节点

对了组件(Component)中的逻辑,其执行流程和普通的节点相似;不同的地方是它有一个独立的作用域。

作者:狐尼克朱迪
链接:https://www.jianshu.com/p/90b762f1f649
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

 

转载于:https://www.cnblogs.com/chinet/p/9285701.html

你可能感兴趣的文章
使用SpringSocial开发QQ登录
查看>>
好玩的游戏
查看>>
2.6. Statistical Models, Supervised Learning and Function Approximation
查看>>
代码说明call和apply方法的区别 (咱们这方面讲解的少,这样的题有变式,需要举例讲解一下)...
查看>>
T-SQL 类型转换
查看>>
在eclipse中设计BPMN 2.0工作流定义的根本步骤
查看>>
Json对象与Json字符串互转(4种转换方式)
查看>>
PAT甲级1002 链表实现方法
查看>>
查看Linux信息
查看>>
Python中sys模块sys.argv取值并判断
查看>>
【详记MySql问题大全集】四、设置MySql大小写敏感(踩坑血泪史)
查看>>
并查集
查看>>
ubuntu 11.04下android开发环境的搭建!
查看>>
Bzoj 3343: 教主的魔法
查看>>
括号序列(栈)
查看>>
一件趣事
查看>>
DevExpress控件TExtLookupComboBox实现多列模糊匹配输入的方法
查看>>
atom 调用g++编译cpp文件
查看>>
H3C HDLC协议特点
查看>>
iptables 网址转译 (Network address translation,NAT)
查看>>