渲染函数render function
本文记录自尤小右的视频教学。
模板template
ast树
抽象语法树compiled into
Render Function 编译成渲染函数return
Virtual DOM 返回虚拟dom元素generates
Actual DOM 生成真实dom元素
vue的templates实际上是由渲染函数渲染出来的,当我们渲染一个vue应用,我们会将template放到渲染函数进行编译,这会发生在你使用完整的编译模式,也就是你直接使用dom模板,就像你直接在dom中编写模板一样。或者直接给vue实例传递一个模板字符串,但是如果你使用vue-cli来构建项目,用到webpack和vue-loader,它实际上是在构建时预编译模板,所以浏览器访问的代码是不包含原始模板的,相反它提供了编译的渲染函数代码,这是纯js。这样做会节省很多编译时间,而且我们可以在没有编译器的情况下运行。在vue中我们提供两种构建方式,一种是完整的构建,它包含一个编译器gzip后大概30kb,但是不包含编译器只包含运行时大小就只有20kb。
render函数实际上是返回虚拟dom,然后vue基于虚拟dom生成真实dom。我们产生虚拟dom的过程本质上是调用render函数,因为render函数和所有的data属性有依赖关系,同时这些data属性是具有响应性的,所有的这些data属性会帮助这个组件的渲染函数收集依赖,如果这些依赖属性中发生了任何变化,将会再次调用渲染函数,它会返回新的虚拟dom,此时新旧的虚拟dom将被比较和区分。
虚拟dom的优点(误区:让框架运行的更快)
- 以声明的方式构成你想要的dom结构
- 把渲染逻辑从真实的dom中分离出来,先计算差异再应用dom中
每个组件都有自己的自动循环渲染,组件只负责自己的依赖
插槽
你可以通过 this.$slots 访问静态插槽的内容,每个插槽都是一个 VNode 数组:
render: function (createElement) {
// `<div><slot></slot></div>`
return createElement('div', this.$slots.default)
//等同于
return createElement('div', this.$scopedSlots.default())
//作用域插槽
return createElement('div', this.$scopedSlots.default({a: 1}))
}
this.$scopedSlots.default() === this.$slots.default //true
抽象组件
export default {
name: 'debounce',
abstract: true, //标记为抽象组件
render() {
let vnode = this.$slots.default[0]; // 子组件的vnode
if (vnode) {
let event = get(vnode, `data.on.click`); // 子组件绑定的click事件
if (typeof event === 'function') {
set(vnode, `data.on.click`, debounce(event, 1000));
}
}
return vnode;
}
};