为什么出现 vue
- 想想之前的发展史,我们使用 jQuery 去操作 dom,实现各自方式,后面使用 vue,我们可以用更少的代码实现相同功能,通过模板可以绑定数据交互和事件触发,vue 是通过什么方式让我们更加方便的呢?
实现如下功能
- 获取 id 为 app 的 div 标签
- 它的文本内容为 hello world
- 为其绑定点击事件
- 当点击时弹出提示:ok
使用原生方式(命令式)
js
const div = document.querySelector('#app') // 获取 div
div.innerText = 'hello world' // 设置文本内容
div.addEventListener('click', () => { alert('ok') }) // 绑定点击事件
使用 vue(声明式)
html
<div @click="() => alert('ok')">hello world</div>
优点: vue 可以让我们只关注目的,而忽略具体实现步骤。事件清晰,可以清楚明白是干什么而不是需要一行行代码去理解
性能可能性分析
首先说明下:声明式代码的性能不优于命令式代码的性能。 因为声明最后都是变为命令式代码执行的
命令式代码的更新性能消耗 = A
声明式代码的更新性能消耗 = B + A
vue选择声明式的原因是因为 可维护 强,在保持可维护性的同时让性能损失最小化。 vue 为了减少 B 的值,选择使用虚拟 dom 来找到差异,然后减小差异
使用虚拟 dom 实现的基础是:dom 操作的速度和JavaScript 的数据操作不在一个数量级
- 对比其他方式
- 所以在考虑增加工作量的情况,使用虚拟 dom 可以调节对细节实现的控制,方便开发人员更好的控制代码
运行时和编译时
- 方式 : 纯运行时的、运行时 + 编译时的或纯编译
编译时: 提供compile函数将 <template>
模版语法的html字符串转化为虚拟dom 运行时:提供render函数将虚拟dom对象转化为真实dom
运行时 demo
js
function Render(obj, root) {
const el = document.createElement(obj.tag)
if (typeof obj.children === 'string') {
const text = document.createTextNode(obj.children)
el.appendChild(text)
} else if (obj.children) {
// 数组,递归调用 Render,使用 el 作为 root 参数
obj.children.forEach((child) => Render(child, el))
}
// 将元素添加到 root
root.appendChild(el)
}
js
const obj = {
tag: 'div',
children: [
{ tag: 'span', children: 'hello world' }
]
}
// 渲染到 body 下
Render(obj, document.body)
compile编译 Render渲染