文章目录
- 1.命令式和声明式
- 2.性能
- 3.运行时和编译时
- 4.声明式地描述UI
- 5.将虚拟DOM渲染为真实DOM
1.命令式和声明式
视图层框架通常分为命令式和声明式。
(1)命令式
jQuery就是一种典型的命令式框架,该类框架的特点是关注过程。即代码描述的是做事的过程,这样的写法比较符合我们的直觉。
(2)声明式
声明式框架是目前比较流行的视图层框架,比如说Vue,该类框架更加关注结果。比如在Vue中通过v-if表示组件是否显示的条件,v-for表示循环加载改组件。声明式框架往往会提供一个清晰的结果,至于怎么达到这个结果,这就涉及Vue的底层实现了,换句话说,Vue帮我们封装了过程。
ps.声明式框架的内部实现一定是命令式的,而暴露给用户的是生命式的表现形式
2.性能
声明式代码的性能并不优于命名式代码。
声明式框架的性能理论上比不上命令式代码(在写出极致优化的命令式代码的情况下),因为声明式框架为了实现最优的更新性能,需要先找出前后差异,并只更新发生变化的地方。如下面的代码:
div.innerHTML = 'Hello World';
假设修改操作的性能消耗为A,找出差异的性能消耗为B
(1)命令式的消耗 = A
(2)声明式的消耗 = A+B
ps.因为声明式框架本身就是封装了命令式的代码而保证了项目的可维护性,所以框架需要做的事情就是:在保证可维护性的同时,保证性能损失最小。
3.运行时和编译时
Vue3是一个运行时+编译时框架
(1)运行时框架
提供数据和render函数,使用render函数将数据转换为DOM,由于没有编译过程,无法分析用户提供的内容,
(2)编译时框架
提供HTML标签模板和compiler函数,在编译时调用compiler函数将HTML标签直接转换为可以执行的命令式代码,性能性能更强。
(3)编译时加运行时狂框架
在编译时分析静态和动态内容,然后传入render函数,做进一步优化。
4.声明式地描述UI
编写前端页面所涉及的内容:
- DOM元素
- 属性
- 事件
- 元素的层级结构
如果使用模板语法来描述是这样:
<div><span @click="handler">click me!</span>
</div>
或者使用对象描述:
const title = {tag: "div",children: [{tag: "span",props: {onClick: handler},children: "click me!"}]
}
该对象最终也会被渲染成上述模板。既然两种方式生成的结果相同,那么使用模板语法和对象语法有什么区别呢?区别就是使用对象描述的形式更加灵活。而在vue.js中就是使用对象也就是虚拟DOM的形式来描述界面的。
5.将虚拟DOM渲染为真实DOM
function renderer(vnode, container) {// 使用 vnode.tag 作为标签名称创建 DOM 元素const el = document.createElement(vnode.tag)// 遍历 vnode.props,将属性、事件添加到 DOM 元素for (const key in vnode.props) {if (/^on/.test(key)) {// 如果 key 以 on 开头,说明它是事件el.addEventListener(key.substr(2).toLowerCase(), // 事件名称 onClick --->clickvnode.props[key] // 事件处理函数)}}// 处理 childrenif (typeof vnode.children === 'string') {// 如果 children 是字符串,说明它是元素的文本子节点el.appendChild(document.createTextNode(vnode.children))} else if (Array.isArray(vnode.children)) {// 递归地调用 renderer 函数渲染子节点,使用当前元素 el 作为挂载点vnode.children.forEach(child => renderer(child, el))}// 将元素添加到挂载点下container.appendChild(el)
}
renderer的具体执行过程:
- 创建元素
- 为元素添加属性和方法
- 处理children