Skip to content

为什么出现 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 的数据操作不在一个数量级

alt text

  • 对比其他方式

alt text

  • 所以在考虑增加工作量的情况,使用虚拟 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渲染