摘要:模版如下我是选项模板为我是选项模板对应我是选项模板为对应的为下把等方法挂载到原型上这样就是执行就是执行就是执行在下标签关于这个节点的值,包括等子节点实例对象创建对象关于这个节点的值,包括等子节点文本内容真实的节点创建这个的上下文下面分别
模版如下
我是选项模板3
{{number}}
{{message}}
111122345
options.render为
function anonymous( ) {
with(this){
return _c(
"div",
[_c("h1",{staticStyle:{"color":"red"}},[_v("我是选项模板3")])
,_v(" "),_c("p",[_v(_s(number))]),
_v(" "),
_c("p",[_v(_s(message))]),
_v(" "),
_m(0)]
)
}
}
对应
我是选项模板3
{{number}}
{{message}}
options.staticRenderFns为 [0]
function anonymous() {
with(this){
return _c("div",[
_c("div",[_v("
1
"),
_c("div",[_v("11")]),_v(" "),
_c("div",[_v("12")])
]),_v(" "),
_c("div",[_v("2")]),_v(" "),
_c("div",[_v("3")]),_v(" "),
_c("div",[_v("4")]),_v(" "),
_c("div",[_v("5")])
])
}
}
对应的template为
111122345
render-helpers 下 index.js
export function installRenderHelpers (target) {
target._o = markOnce
target._n = toNumber
target._s = toString
target._l = renderList
target._t = renderSlot
target._q = looseEqual
target._i = looseIndexOf
target._m = renderStatic
target._f = resolveFilter
target._k = checkKeyCodes
target._b = bindObjectProps
target._v = createTextVNode
target._e = createEmptyVNode
target._u = resolveScopedSlots
target._g = bindObjectListeners
}
render.js
function renderMixin (Vue) {
//把_v,_m等方法挂载到vue原型上
installRenderHelpers(Vue.prototype)
}
function initRender (vm) {
vm._c = (a, b, c, d) => createElement(vm, a, b, c, d, false)
}
这样this._c就是执行createElement
this._m就是执行renderStatic
_v就是执行createTextVNode
在vdom下create-element.js
tag // 标签
data // 关于这个节点的data值,包括attrs,style,hook等
children // 子vdom节点
context // vue实例对象
function _createElement(context,tag,data,children,normalizationType) {
vnode = new VNode(
tag, data, children,
undefined, undefined, context
)
return vnode
}
创建vdom对象
vnode
class VNode {
constructor (
tag,
data, // 关于这个节点的data值,包括attrs,style,hook等
children, // 子vdom节点
text, // 文本内容
elm, // 真实的dom节点
context, // 创建这个vdom的上下文
componentOptions,
asyncFactory
) {
this.tag = tag
this.data = data
this.children = children
this.text = text
this.elm = elm
this.ns = undefined
this.context = context
this.fnContext = undefined
this.fnOptions = undefined
this.fnScopeId = undefined
this.key = data && data.key
this.componentOptions = componentOptions
this.componentInstance = undefined
this.parent = undefined
this.raw = false
this.isStatic = false
this.isRootInsert = true
this.isComment = false
this.isCloned = false
this.isOnce = false
this.asyncFactory = asyncFactory
this.asyncMeta = undefined
this.isAsyncPlaceholder = false
}
}
下面dom分别依次执行,先渲染里面然后再渲染外层
1. [_c("h1",{staticStyle:{"color":"red"}},[_v("我是选项模板3")])
我是选项模板3
2._c("p",[_v(_s(number))]
{{number}}
3._c("p",[_v(_s(message))])
{{message}}
4._m(0)是缓存渲染数
function anonymous() {
with(this){
return _c("div",[
_c("div",[_v("
1
"),
_c("div",[_v("11")]),_v(" "),
_c("div",[_v("12")])
]),_v(" "),
_c("div",[_v("2")]),_v(" "),
_c("div",[_v("3")]),_v(" "),
_c("div",[_v("4")]),_v(" "),
_c("div",[_v("5")])
])
}
}
vdom顺序依次为
(1)11
(2)12
(3)
1
11
12
(4)2
(5)3
(6)4
(7)5
(8)
1
11
12
2
3
4
5
(9)
我是选项模板3
{{number}}
{{message}}
1
11
12
2
3
4
5
最后一次执行最外面的
render-static.js给m[0]静态树做了缓存处理
renderStatic (
index,
isInFor
) {
//缓存处理
const cached = this._staticTrees || (this._staticTrees = [])
// staticRenderFns被执行
tree = cached[index] = this.$options.staticRenderFns[index].call(
this._renderProxy, // 代理可以理解为vue实例对象,多了一些提示处理
null,
this // for render fns generated for functional component templates
)
markStatic(tree, `__static__${index}`, false)
return tree
}
function markStatic (
tree,
key,
isOnce
) {
function markStaticNode (node, key, isOnce) {
node.isStatic = true //静态树为true
node.key = key // `__static__${index}` 标志
node.isOnce = isOnce // 是否是v-once
}
markStaticNode(node, key, isOnce)
}
然后又重新执行
function anonymous(
) {
with(this){return _c("div",[_c("div",[_v("
1
"),_c("div",[_v("11")]),_v(" "),_c("div",[_v("12")])]),_v(" "),_c("div",[_v("2")]),_v(" "),_c("div",[_v("3")]),_v(" "),_c("div",[_v("4")]),_v(" "),_c("div",[_v("5")])])}
}
打印render()结果
静态树有了isStatic和key值
补充个小问题 render函数里number 还是变量是什么时候变成数字的
因为function有个with(this){}改变了作用域,当this.render()执行时候,那么this就是指得vue, $options.data 已经通过defineProperty代理到了vue下,访问this.data就是访问$options.data 所以number就是数字啦
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/97393.html
摘要:今年的月日,的版本正式发布了,其中核心代码都进行了重写,于是就专门花时间,对的源码进行了学习。本篇文章就是源码学习的总结。实现了并且将静态子树进行了提取,减少界面重绘时的对比。的最新源码可以去获得。 Vue2.0介绍 从去年9月份了解到Vue后,就被他简洁的API所吸引。1.0版本正式发布后,就在业务中开始使用,将原先jQuery的功能逐步的进行迁移。 今年的10月1日,Vue的2...
摘要:图在中应用三数据渲染过程数据绑定实现逻辑本节正式分析从到数据渲染到页面的过程,在中定义了一个的构造函数。一、概述 vue已是目前国内前端web端三分天下之一,也是工作中主要技术栈之一。在日常使用中知其然也好奇着所以然,因此尝试阅读vue源码并进行总结。本文旨在梳理初始化页面时data中的数据是如何渲染到页面上的。本文将带着这个疑问一点点追究vue的思路。总体来说vue模版渲染大致流程如图1所...
摘要:首先在里调用函数把获取相应传递过去里在原型上定义方法对浏览器的怪癖做兼容布尔值。对浏览器的怪癖做兼容布尔值。 首先在init.js里调用$mount函数把el #app获取相应dom传递过去 Vue.prototype._init = function (options) { ... if (vm.$options.el) { vm.$mount(vm.$opt...
摘要:接下来我们分析下是如何调用的,这就涉及到了经典的机制此处先简单介绍,下一篇会有较详细的分析。 Vue demo 先给出vue简单的使用demo,通过创建一个Vue的实例,将被替换成template模版中的内容,a,b的值也会被换成data属性的值 var vm = new Vue({ el: #app, template: ` {{a}} {{b}} ...
摘要:下面用具体代码进行分析。匹配不到那么就是开始标签,调用函数解析。如这里的转化为加上是为了的下一步转为函数,本文中暂时不会用到。再把转化后的内容进。 什么是AST 在Vue的mount过程中,template会被编译成AST语法树,AST是指抽象语法树(abstract syntax tree或者缩写为AST),或者语法树(syntax tree),是源代码的抽象语法结构的树状表现形式。...
阅读 3824·2021-11-18 10:02
阅读 3305·2019-08-29 18:34
阅读 3606·2019-08-29 17:00
阅读 641·2019-08-29 12:35
阅读 939·2019-08-28 18:22
阅读 2343·2019-08-26 13:58
阅读 1863·2019-08-26 10:39
阅读 2889·2019-08-26 10:11