1、什么是虚拟DOM以及虚拟DOM的表达 虚拟DOM简而言之就是,用JS去按照DOM结构来实现的树形结构对象, 上图是比较简单的一个结构,比较理想的是使用如下对象来模拟: OK,对象结构已经解析完成,接下来我们就看怎么批量生成这样的结构,直接上代码 我们只需要调用createElement即可生成上述的dom对象结构,他接收三个参数,第一个表示dom元素的类型,第二个表示要设置的属性,第三个则表示子元素。生成上述结构调用代码如下: 我们可以在控制台很清楚的看到打印出来的结构正是我们想要的结构 2、虚拟DOM转换成真实的DOM 上面我们已经实现了一个虚拟DOM的表达,也就是我们可以轻而易举的通过一个对象来表达一个dom了,接下来我们看看怎么把虚拟dom转换成我们的真实dom,也就是吧我们的对象转换回我们的真实DOM,从而在页面显示。 直接上代码如下: 直接调用我们的render函数,并把对应的虚拟DOM传入即可,接着上一步,我们已经生成了了虚拟dom对象virtualDom,因此只需要调用如下: 到此,我们的转换也就告一段了。 3、整个过程的封装 virtualDom.js test.js(测试文件) 虚拟DOM大家都不陌生,研究了一下略带收获,在这里简单记录下,做个备忘
也就是一个JS对象而已。
那么什么样的对象才能比较匹配的上dom结构呢?来看一下如下图所示的dom结构
<div class="list" style="color: red;"> <div class="item"> <p class="leftP"> <span class="left" style="margin-right: 10px;">leftSpan</span> <span class="right">rightSpan</span></p> <p class="rightP"> <img class="imgs" src="https://pics2.baidu.com/feed/94cad1c8a786c9175fd11173392345ca3ac75749.jpeg?token=8d28956f2c93b2e7090e89980059a553&s=FAC2B144C3BCB469044C8C830000B081" style="width: 100px; height: 100px;"> <span class="imgs" style="width: 100px; height: 100px;">图片旁边的span</span> </p> </div> <p class="item">玉溪</p> <p class="item">黄鹤楼</p> </div>
{ //节点类型 "type": "div", //节点属性 "props": { "class": "list", "style": "color:red;" }, //子节点 "children": [ { "type": "div", "props": {"class": "item"}, "children": [ { "type": "p", "props": {"class": "leftP"}, "children": [ { "type": "span", "props": { "class": "left", "style": "margin-right:10px" }, "children": ["leftSpan"] }, { "type": "span", "props": {"class": "right"}, //没有子节点了,直接显示文本 "children": ["rightSpan"] } ] }, { "type": "p", "props": {"class": "rightP"}, "children": [ { "type": "img", "props": { "class": "imgs", "style": "width:100px;height:100px", "src": "https://pics2.baidu.com/feed/94cad1c8a786c9175fd11173392345ca3ac75749.jpeg?token=8d28956f2c93b2e7090e89980059a553&s=FAC2B144C3BCB469044C8C830000B081" }, "children": [] }, { "type": "span", "props": { "class": "imgs", "style": "width:100px;height:100px" }, "children": ["图片旁边的span"] } ] } ] }, { "type": "p", "props": {"class": "item"}, "children": ["玉溪"] }, { "type": "p", "props": {"class": "item"}, "children": ["黄鹤楼"] } ] }
// 定义一个构造函数来 class Element { constructor(type, props, children) { this.type = type; this.props = props; this.children = children; } }; //生成虚拟dom对象 (批量调用构造函数,) class createElement=(type,props,children)=>{ return new Element(type,props,children); };
let virtualDom = createElement( 'div', {class:'list',style:'color:red;'}, [ //div createElement( 'div', {class:'item'}, [ //p createElement( 'p', {class:'leftP'}, [ //span createElement('span',{class:'left',style:'margin-right:10px'},['leftSpan']), //span createElement('span',{class:'right'},['rightSpan']), ] ), //p createElement('p',{class:'rightP'},[ createElement( 'img', { class:'imgs', style:'width:100px;height:100px', src:'https://pics2.baidu.com/feed/94cad1c8a786c9175fd11173392345ca3ac75749.jpeg?token=8d28956f2c93b2e7090e89980059a553&s=FAC2B144C3BCB469044C8C830000B081' }, [], ), createElement( 'span', { class:'imgs', style:'width:100px;height:100px', }, ['图片旁边的span'], ), ]), ] ), createElement('p',{class:'item'},['玉溪']), createElement('p',{class:'item'},['黄鹤楼']), ] ); console.log(virtualDom);
// 设置属性 const setAttr = (node, key, value)=> { // 需要判断key是什么 switch (key) { case 'value': // 属性是value就要看标签类型了,input和textarea的value就需要做区别 if (node.tagName.toLowerCase() === 'input' || node.tagName.toLowerCase() == 'textarea') { node.value = value; } else { node.setAttribute(key, value); } break; case 'style': node.style.cssText = value; break; default: node.setAttribute(key, value); break; } }; const render=(domObj)=> { // 根据元素类型来创建dom let el = document.createElement(domObj.type); // 遍历props对象,然后给创建的元素el设置属性 for (let key in domObj.props) { // 设置属性的方法 setAttr(el, key, domObj.props[key]); } // 遍历子节点数组 domObj.children.forEach(child =>{ // 需要注意的是:如果child是虚拟dom,就继续递归渲染 if (child instanceof Element) { child = this.render(child); } else { // 只是普通的文本内容 child = document.createTextNode(child); } // 把子节点添加到父节点中 el.appendChild(child); }); return el; };
// 得到dom元素 let el = render(virtualDom); console.log(el); //插入页面 document.getElementById('app').appendChild(el)
// 定义一个构造函数来 class Element { constructor(type, props, children) { this.type = type; this.props = props; this.children = children; } }; export default function VirtualDom(extendsObj={}){ Object.assign(this,extendsObj); // 设置属性 const setAttr = (node, key, value)=> { // 需要判断key是什么 switch (key) { case 'value': // 属性是value就要看标签类型了,input和textarea的value就需要做区别 if (node.tagName.toLowerCase() === 'input' || node.tagName.toLowerCase() == 'textarea') { node.value = value; } else { node.setAttribute(key, value); } break; case 'style': node.style.cssText = value; break; default: node.setAttribute(key, value); break; } }; //生成虚拟dom (批量调用构造函数,) this.createElement=(type,props,children)=>{ return new Element(type,props,children); }; //生成真实dom this.render=(domObj)=> { // 根据元素类型来创建dom let el = document.createElement(domObj.type); // 遍历props对象,然后给创建的元素el设置属性 for (let key in domObj.props) { // 设置属性的方法 setAttr(el, key, domObj.props[key]); } // 遍历子节点数组 domObj.children.forEach(child =>{ // 需要注意的是:如果child是虚拟dom,就继续递归渲染 if (child instanceof Element) { child = this.render(child); } else { // 只是普通的文本内容 child = document.createTextNode(child); } // 把子节点添加到父节点中 el.appendChild(child); }); return el; }; // 将元素插入页面 this.renderDom = (el, target)=> { target.appendChild(el); }; }
import VirtualDom from './virtualDom.js'; const testDom = ()=>{ let virtualDom = new VirtualDom(); console.log(virtualDom); let domObj = virtualDom.createElement( 'div', {class:'list',style:'color:red;'}, [ //div virtualDom.createElement( 'div', {class:'item'}, [ //p virtualDom.createElement( 'p', {class:'leftP'}, [ //span virtualDom.createElement('span',{class:'left',style:'margin-right:10px'},['leftSpan']), //span virtualDom.createElement('span',{class:'right'},['rightSpan']), ] ), //p virtualDom.createElement('p',{class:'rightP'},[ virtualDom.createElement( 'img', { class:'imgs', style:'width:100px;height:100px', src:'https://pics2.baidu.com/feed/94cad1c8a786c9175fd11173392345ca3ac75749.jpeg?token=8d28956f2c93b2e7090e89980059a553&s=FAC2B144C3BCB469044C8C830000B081' }, [], ), virtualDom.createElement( 'span', { class:'imgs', style:'width:100px;height:100px', }, ['图片旁边的span'], ), ]), ] ), virtualDom.createElement('p',{class:'item'},['玉溪']), virtualDom.createElement('p',{class:'item'},['黄鹤楼']), ] ); console.log(domObj ); // 渲染dom let el = virtualDom.render(domObj); // 得到dom元素 console.log(el); virtualDom.renderDom(el,document.getElementById('app')); }; export { testDom }
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算