实现一个简单的虚拟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。在这之前我们先创建元素节点(单个元素)。
/** * [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树上,没有显示。
let dom = createDom(vDom); document.getElementsByTagName("body")[0].appendChild(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
显示效果
我们再来一个复杂一点的来验证是否正确。
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 diff算法,我打算把他们分了两篇文章来写,首先一篇文章会太长。其次,我觉得这两个概念虽然戚戚相关但是我觉得还是两个东西。diff算法我觉得是对DOM更新等操作的优化,减少无用的更新,这样会带来更少的消耗更多的性能。
我会尽快写一篇有关DOM diff算法的文章,希望你们能耐心等候。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 虚拟化生态系统及实现从虚拟化走向云端
- 利用虚拟机实现端口转发
- vue:虚拟dom的实现
- 以太坊虚拟机的Python实现
- HotSpot 虚拟机垃圾回收算法实现
- 使用 React + Rxjs 实现一个虚拟滚动组件
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
图片转BASE64编码
在线图片转Base64编码工具
Base64 编码/解码
Base64 编码/解码