根据render函数生成vnode
标签:function,return,render,vm,源码,vue2,data,节点 From: https://www.cnblogs.com/dgqp/p/17323823.html
上文介绍
上面已经将模板编译成了
render
函数,下面就要使用render
函数,从而完成渲染的操作:首先,根据
render
函数生成虚拟节点;然后根据虚拟节点+真实数据生成真实节点。实现
mountComponent
方法,完成渲染虚拟节点生成
封装
vm._render
方法。Vue.prototype._render = function () { // 让with指中的this指向vm // 当渲染的时候会去实例取值,就可以将属性和视图绑定在一起 return this.$options.render.call(this); // 通过ast语法转义后生成的render方法 };
当
_render
被调用时,内部会调用_c
、_v
、_s
三个方法所以,在
vm._render
方法中,需要完成以下几件事:
- 调用
render
函数- 提供
_c
、_v
、s
三个方法Vue.prototype._c = function () { return createElementVNode(this, ...arguments); }; Vue.prototype._v = function () { return createTextVNode(this, ...arguments); }; Vue.prototype._s = function (value) { // 不是对象 if (typeof value !== "object") return value; // 是对象,返回字符串 return JSON.stringify(value); };
_s
方法如上面所示。
实现
_c
和_v
方法观察
_c
和_v
调用了两个方法,因此实现两个方法:export function createElement() { // 返回元素虚拟节点 } export function createText() { // 返回文本虚拟节点 }
这两个方返回虚拟节点。
实现:
// h() _c() export function createElementVNode(vm, tag, data = {}, ...children) { if (data == null) { data = {} } let key = data.key if (key) { delete data.key } return vnode(vm, tag, key, data, children) } // _v() export function createTextVNode(vm, text) { return vnode(vm, undefined, undefined, undefined, undefined, text) } // ast一样吗?ast做的是语法层面的转化,他描述的是语法本身 // 我们的虚拟dom是描述的dom元素,可以增加自定义属性 function vnode(vm, tag, key, data, children, text) { return { vm, // 是谁的虚拟节点 tag, // 标签 key, // 键 data, // 数据 children, // 孩子 text, // 文本 } }
总结生成虚拟节点
根据
render
函数,生成vnode
- 封装
vm._render
返回虚拟节点_s
,_c
,_v
的实现