实现一个简单的虚拟DOM

栏目: JavaScript · 发布时间: 5年前

内容简介:学习过框架尤其是VUE、React的肯定都知道Virtual DOM这个概念。因为我也很想知道并且了解它是一个什么东西,所以我打算把自己学习的分享个大家。如有错误,请大家指明。首先,说一下什么是虚拟DOM。其实就是一个JS的对象。我们先来简单的实现一个虚拟DOM。我们使用过React的都知道createElement这一个函数、Vue都知道render或者是“h”,这样一个函数。我们先来创建一个createElement函数。

学习过框架尤其是VUE、React的肯定都知道Virtual DOM这个概念。因为我也很想知道并且了解它是一个什么东西,所以我打算把自己学习的分享个大家。如有错误,请大家指明。

首先,说一下什么是虚拟DOM。

  • 虚拟DOM就是用JS对象来表示或者是模拟一个真实DOM的结构。

其实就是一个JS的对象。我们先来简单的实现一个虚拟DOM。我们使用过React的都知道createElement这一个函数、Vue都知道render或者是“h”,这样一个函数。我们先来创建一个createElement函数。

/**
 * [createElement 用来创建DOM节点]
 * @param  {[type]} type     [元素类型(名称)]
 * @param  {[type]} props    [描述信息]
 * @param  {[type]} children [子节点]
 * @return {[type]}          [description]
 */
function createElement(type, props, children) {
    // 返回一个Element对象。
    return new Element(type, props, children);
}
复制代码
<div class="vdom">561651</div>
    type: div
    props: class="vdom"
    children: 561651
复制代码

元素对象(Element),用来表示一个元素。

class Element {
    constructor(type, props, children) {
    	this.type = type;
    	this.props = props;
    	this.children = children;
    }
}
复制代码
let vDom = createElement("ul", {class: "dawd"}, [
    	createElement("li", {class: "dawd"}, ["1"]),
    	createElement("li", {class: "dawd"}, ["2"]),
    	createElement("li", {class: "dawd"}, ["3"])
    ]);
复制代码
实现一个简单的虚拟DOM

已经基本描述出了DOM的树形结构。下面我们来根据虚拟DOM创建真实的DOM。在这之前我们先创建元素节点(单个元素)。

/**
 * [createNode 创建单个元素]
 * @param  {[type]} node [元素节点]
 * @return {[type]}      [真实的DOM元素]
 */
function createNode(node){
    // 根据类型创建元素
    let el = document.createElement(node.type);
    for (key in node.props) {
        // 遍历属性 
    	if(key === "value"){
    	    // 只有input还有textarea需要value属性
    		if(node.type.toUpperCase() === "INPUT" || node.type.toUpperCase() === "TEXTAREA"){
    	 		el.value = node.props[key];
    		}
    	}else {
    	    // 设置属性
    		el.setAttribute(key, node.props[key]);
    	}
    }
    return el;
}
复制代码

根据单个元素组成DOM树

function createDom(node) {
    let root = createNode(node);
    if(node.children && node.children.length > 0){
        // 遍历子元素
    	node.children.forEach( function(element) {
    		if(element instanceof Element){
    		    // 节点
    			root.appendChild( createDom(element) );
    		}else {
    		    // 文本
    			root.appendChild( document.createTextNode(element) );
    		}
    	});
    }
    return root;
}
复制代码

根据虚拟DOM生成的真实DOM

实现一个简单的虚拟DOM

现在只是生成了真实的DOM但是还没有真正的挂载到DOM树上,没有显示。

let dom = createDom(vDom);
document.getElementsByTagName("body")[0].appendChild(dom);
复制代码
实现一个简单的虚拟DOM

再试一下input元素

let vDom = createElement("ul", {class: "dawd"}, [
			createElement("li", {class: "dawd"}, [
				createElement("input", {type: "radio",value: "1651"},[]),
				createElement("input", {type: "text",value: "1651"},[])
			])
		]);
复制代码

真实DOM

实现一个简单的虚拟DOM

显示效果

实现一个简单的虚拟DOM

我们再来一个复杂一点的来验证是否正确。

createElement("div", {class: "div"}, [
	createElement("ul", {class: "ul"}, [
		createElement("li", {class: "li"},[createElement("input", {type: "radio",value: "1651"},["单选"])]),
		createElement("li", {class: "li"},[createElement("input", {type: "text",value: "1651"},[])]),]),
		createElement("div", {class: "div"}, [
			createElement("p", {class: "p"},[
		            createElement("span", {class: "span"},["我是span"])]),
			    createElement("a", {class: "a",href: "https://juejin.im/editor/drafts/5cf3c75de51d45572c05fff3"},[
				    createElement("span", {class: "span"},["我是超链接里面的span"])]),
				    createElement("img", {class: "img",src: "http://g.hiphotos.baidu.com/image/h%3D300/sign=b5e4c905865494ee982209191df4e0e1/c2cec3fdfc03924590b2a9b58d94a4c27d1e2500.jpg",alt: "虚拟DOM图片",title: "虚拟的DOM"},[])
	]),
]);
复制代码
实现一个简单的虚拟DOM
  • 总结
    • 虚拟DOM对我们的项目性能很有帮助,我们重点的是要了解他的思想和实现,不是一味的使用或者是照抄。
    • 说到虚拟DOM就离不开DOM diff算法,我打算把他们分了两篇文章来写,首先一篇文章会太长。其次,我觉得这两个概念虽然戚戚相关但是我觉得还是两个东西。diff算法我觉得是对DOM更新等操作的优化,减少无用的更新,这样会带来更少的消耗更多的性能。

我会尽快写一篇有关DOM diff算法的文章,希望你们能耐心等候。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

史蒂夫·乔布斯传

史蒂夫·乔布斯传

[美] 沃尔特·艾萨克森 / 管延圻、魏群、余倩、赵萌萌、汤崧 / 中信出版社 / 2011-10-24 / 68.00元

这本乔布斯唯一授权的官方传记,在2011年上半年由美国出版商西蒙舒斯特对外发布出版消息以来,备受全球媒体和业界瞩目,这本书的全球出版日期最终确定为2011年11月21日,简体中文版也将同步上市。 两年多的时间,与乔布斯40多次的面对面倾谈,以及与乔布斯一百多个家庭成员、 朋友、竞争对手、同事的不受限的采访,造就了这本独家传记。 尽管乔布斯给予本书的采访和创作全面的配合,但他对内容从不干......一起来看看 《史蒂夫·乔布斯传》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试