上文已经说到了vue最后选择了的是声明式的写法,vue中使用了模板来编写声明式的代码,如果你已经开始解读源码的话对vue的虚拟dom应该是有很深的了解了
<div @click="handler">
<span></span>
</div>
上述代码就是模板式的声明代码,它最后会被解析为所谓的虚拟dom(如下)
const title = {
//标签名称
tag: 'div',
//标签属性
props: {
onClick: handler
},
//子节点
children: [
{tag: 'span'}
]
}
当然你也可以省略模板这个步骤直接去用js去写这个dom; 那么问题就来了,使用模板和javascript对象去描述这个UI有何不同呢? 答案就是灵活: 假如我们要采用不同级别的标题,用javascript就可以这样写
let level = 3;
const title = {
tag: `h${level}`,
}
可以看到,我们可以随时控制level的值让标签变化,然而用模板的话我们不得不一直穷举
<h1 v-if="level === 1"></h1>
<h2 v-else-if="level === 2"></h2>
<h3 v-else-if === 3"></h3>
<h4 v-else-if === 4"></h4>
等等
远远没有javascript那样的灵活 其实在vue.js组件中手写的渲染函数就是使用虚拟dom来渲染UI的,
import { h } from 'vue';
export default {
render() {
return h('h1', { onClick: handler})
}
}
有人会说这不就是h函数的调用么,其实h函数调用返回过来的就是javascript的对象,也就是虚拟dom
export default {
render() {
tag: 'h1',
props: { onClick: handler }
}
}
如果还有子节点的话编写内容话就需要编写更多的代码了,然而h函数仅仅是一个创建虚拟dom的辅助工具罢了。 最后怕有人不知道组件的渲染函数是什么,我们来解释一下: 一个组件要去渲染内部的内容的话就是通过渲染函数来描述的,也就是上述的render,想必写过React的兄弟应该不陌生,vue.js会根据组件的render函数的返回值去拿到想要的虚拟dom