首页 > 语言 > JavaScript > 正文

深入理解Vue2.x的虚拟DOM diff原理

2024-05-06 15:26:09
字体:
来源:转载
供稿:网友

前言

经常看到讲解Vue2的虚拟Dom diff原理的,但很多都是在原代码的基础上添加些注释等等,这里从0行代码开始实现一个Vue2的虚拟DOM

实现VNode

src/core/vdom/Vnode.js

export class VNode{ constructor (  tag, //标签名  children,//孩子[VNode,VNode],  text, //文本节点  elm //对应的真实dom对象 ){  this.tag = tag;  this.children = children  this.text = text;  this.elm = elm; }}export function createTextNode(val){ //为什么这里默认把elm置为undefined,不直接根据tag 用document.createElement(tagName)把elm赋值?而要等后面createElm时候再赋值呢? return new VNode(undefined,undefined,String(val),undefined)}export function createCommentNode(tag,children){ if(children){  for(var i=0;i<children.length;i++){   var child = children[i];   if(typeof child == 'string'){    children[i] = createTextNode(child)   }  } } return new VNode(tag,children,undefined,null)}

定义一个Vnode类, 创建节点分为两类,一类为text节点,一类非text节点

src/main.js

import {VNode,createCommentNode} from './core/vdom/vnode'var newVonde = createCommentNode('ul',[createCommentNode('li',['item 1']),createCommentNode('li',['item 2']),createCommentNode('li',['item 3'])])

在main.js就可以根据Vnode 生成对应的Vnode对象,上述代码对应的dom表示

<ul><li>item1</li><li>item2</li><li>item3</li></ul>

先实现不用diff把Vnode渲染到页面中来

为什么先来实现不用diff渲染Vnode的部分,这里也是为了统计渲染的时间,来表明一个道理。并不是diff就比非diff要开,虚拟DOM并不是任何时候性能都比非虚拟DOM 要快

先来实现一个工具函数,不熟悉的人可以手工敲下代码 熟悉下

// 真实的dom操作// src/core/vdom/node-ops.jsexport function createElement (tagName) { return document.createElement(tagName)}export function createTextNode (text) { return document.createTextNode(text)}export function createComment (text) { return document.createComment(text)}export function insertBefore (parentNode, newNode, referenceNode) { parentNode.insertBefore(newNode, referenceNode)}export function removeChild (node, child) { node.removeChild(child)}export function appendChild (node, child) { node.appendChild(child)}export function parentNode (node) { return node.parentNode}export function nextSibling (node) { return node.nextSibling}export function tagName (node) { return node.tagName}export function setTextContent (node, text) { node.textContent = text}export function setAttribute (node, key, val) { node.setAttribute(key, val)}

src/main.js

import {VNode,createCommentNode} from './core/vdom/vnode'import patch from './core/vdom/patch'var container = document.getElementById("app");var oldVnode = new VNode(container.tagName,[],undefined,container);var newVonde = createCommentNode('ul',[createCommentNode('li',['item 1']),createCommentNode('li',['item 2']),createCommentNode('li',['item 3'])])console.time('start');patch(oldVnode,newVonde); //渲染页面console.timeEnd('start');            
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选