vue 原理

74 阅读1分钟

vue虚拟dom

1.为什么要用虚拟dom 答:因为操作真实dom消耗比较大 为了避免不必要的DOM操作 2.什么是虚拟dom 答:就是将真实的dom转换成 对象key value的形式

hello world

===>

截屏2023-02-08 16.17.48.png

  1. vnode使用什么方式 避免了不必要的dom操作 答:双指针比对 暴力比对

3.1 双指针比对

  • 旧前 新前 dom 比对
  • 旧后 新后 dom 比对
  • 旧前 新后 dom 比对
  • 旧后 新前 dom 比对

截屏2023-02-08 16.34.32.png

3.2 暴力比对

  1. 根据oldVnode 生成 map表 map[oldVnode.key] = idx
  2. if newVnode 在 oldVnode 中不存在 那么 新创建newVnode 插入到当前oldChild前面
  3. if newVnode 在 oldVnode 中存在 将 oldVnode 插入到当前oldChild前面 并且清空 map 对照表中的key

3.3 双指针比对 + 暴力比对 后

if 旧前指针 > 旧后指针 说明新节点比旧节点多 依次append 新元素 if 新前指针 > 新后指针 说明新节点比旧节点少 依次remove 旧元素

vue 真实dom 转换为 虚拟dom

  1. 首先将真实dom 转换为 ast 语法树

<div id="app" style="red">hello{{msg}}</div>

=>

{"tag":"div", "attrs":[{"name":"id","value":"app"},{"name":"style","value":"color:red"}], "children":[{"type":3,"text":"hello{{msg}}"}],"type":1}

=>

let code = _c('div',{id:"app",style:{"color":"red"}},_v("hello"+_s(msg)))

  1. 通过 with方法 转换为虚拟dom
function _c(tag, data = {}, ...children) {
  return vnode(tag, data, data.key, children);
}

function _v(text) {
  return vnode(undefined, undefined, undefined, undefined, text);
}

function _s(text) {
  return val === null
      ? ""
      : typeof val === "object"
      ? JSON.stringify(val)
      : val;
}

function vnode(tag, data, key, children, text) {
  return {
    tag,
    data,
    key,
    children,
    text,
  };
}

new Function('with(this){return ${code}}')

附图

截屏2023-02-09 10.43.29.png