当前位置: 首页 > news >正文

网站文章更新做销售找客户渠道

网站文章更新,做销售找客户渠道,莱芜网络公司,最新手机排行榜20211.为什么需要虚拟DOM DOM是很慢的,其元素非常庞大,页面的性能问题鲜有由JS引起的,大部分都是由DOM操作引起的。如果对前端工作进行抽象的话,主要就是维护状态和更新视图;而更新视图和维护状态都需要DOM操作。其实近年…

1.为什么需要虚拟DOM

DOM是很慢的,其元素非常庞大,页面的性能问题鲜有由JS引起的,大部分都是由DOM操作引起的。如果对前端工作进行抽象的话,主要就是维护状态和更新视图;而更新视图和维护状态都需要DOM操作。其实近年来,前端的框架主要发展方向就是解放DOM操作的复杂性。

在jQuery出现以前,我们直接操作DOM结构,这种方法复杂度高,兼容性也较差;有了jQuery强大的选择器以及高度封装的API,我们可以更方便的操作DOM,jQuery帮我们处理兼容性问题,同时也使DOM操作变得简单;但是聪明的程序员不可能满足于此,各种MVVM框架应运而生,有angularJS、avalon、vue.js等,MVVM使用数据双向绑定,使得我们完全不需要操作DOM了,更新了状态视图会自动更新,更新了视图数据状态也会自动更新,可以说MMVM使得前端的开发效率大幅提升,但是其大量的事件绑定使得其在复杂场景下的执行性能堪忧;有没有一种兼顾开发效率和执行效率的方案呢?ReactJS就是一种不错的方案,虽然其将JS代码和HTML代码混合在一起的设计有不少争议,但是其引入的Virtual DOM(虚拟DOM)却是得到大家的一致认同的。

2.理解虚拟DOM

虚拟的DOM的核心思想是:对复杂的文档DOM结构,提供一种方便的工具,进行最小化地DOM操作。这句话,也许过于抽象,却基本概况了虚拟DOM的设计思想

(1) 提供一种方便的工具,使得开发效率得到保证
(2) 保证最小化的DOM操作,使得执行效率得到保证

(1).用JS表示DOM结构

DOM很慢,而javascript很快,用javascript对象可以很容易地表示DOM节点。DOM节点包括标签、属性和子节点,通过VElement表示如下。

//虚拟dom,参数分别为标签名、属性对象、子DOM列表
var VElement = function(tagName, props, children) {//保证只能通过如下方式调用:new VElementif (!(this instanceof VElement)) {return new VElement(tagName, props, children);}//可以通过只传递tagName和children参数if (util.isArray(props)) {children = props;props = {};}//设置虚拟dom的相关属性this.tagName = tagName;this.props = props || {};this.children = children || [];this.key = props ? props.key : void 666;var count = 0;util.each(this.children, function(child, i) {if (child instanceof VElement) {count += child.count;} else {children[i] = '' + child;}count++;});this.count = count;
}

 

通过VElement,我们可以很简单地用javascript表示DOM结构。比如

var vdom = velement('div', { 'id': 'container' }, [velement('h1', { style: 'color:red' }, ['simple virtual dom']),velement('p', ['hello world']),velement('ul', [velement('li', ['item #1']), velement('li', ['item #2'])]),
]);

 

上面的javascript代码可以表示如下DOM结构:

<div id="container"><h1 style="color:red">simple virtual dom</h1><p>hello world</p><ul><li>item #1</li><li>item #2</li></ul>   
</div>

 

同样我们可以很方便地根据虚拟DOM树构建出真实的DOM树。具体思路:根据虚拟DOM节点的属性和子节点递归地构建出真实的DOM树。见如下代码:

VElement.prototype.render = function() {//创建标签var el = document.createElement(this.tagName);//设置标签的属性var props = this.props;for (var propName in props) {var propValue = props[propName]util.setAttr(el, propName, propValue);}//依次创建子节点的标签util.each(this.children, function(child) {//如果子节点仍然为velement,则递归的创建子节点,否则直接创建文本类型节点var childEl = (child instanceof VElement) ? child.render() : document.createTextNode(child);el.appendChild(childEl);});return el;
}

对一个虚拟的DOM对象VElement,调用其原型的render方法,就可以产生一颗真实的DOM树。

vdom.render();

既然我们可以用JS对象表示DOM结构,那么当数据状态发生变化而需要改变DOM结构时,我们先通过JS对象表示的虚拟DOM计算出实际DOM需要做的最小变动,然后再操作实际DOM,从而避免了粗放式的DOM操作带来的性能问题。

(2).比较两棵虚拟DOM树的差异

在用JS对象表示DOM结构后,当页面状态发生变化而需要操作DOM时,我们可以先通过虚拟DOM计算出对真实DOM的最小修改量,然后再修改真实DOM结构(因为真实DOM的操作代价太大)。

如下图所示,两个虚拟DOM之间的差异已经标红:

virtual dom

为了便于说明问题,我当然选取了最简单的DOM结构,两个简单DOM之间的差异似乎是显而易见的,但是真实场景下的DOM结构很复杂,我们必须借助于一个有效的DOM树比较算法。

设计一个diff算法有两个要点:

如何比较两个两棵DOM树
如何记录节点之间的差异

<1> 如何比较两个两棵DOM树

计算两棵树之间差异的常规算法复杂度为O(n3),一个文档的DOM结构有上百个节点是很正常的情况,这种复杂度无法应用于实际项目。针对前端的具体情况:我们很少跨级别的修改DOM节点,通常是修改节点的属性、调整子节点的顺序、添加子节点等。因此,我们只需要对同级别节点进行比较,避免了diff算法的复杂性。对同级别节点进行比较的常用方法是深度优先遍历:

function diff(oldTree, newTree) {//节点的遍历顺序var index = 0; //在遍历过程中记录节点的差异var patches = {}; //深度优先遍历两棵树dfsWalk(oldTree, newTree, index, patches); return patches; 
}

<2>如何记录节点之间的差异

由于我们对DOM树采取的是同级比较,因此节点之间的差异可以归结为4种类型:

修改节点属性, 用PROPS表示
修改节点文本内容, 用TEXT表示
替换原有节点, 用REPLACE表示
调整子节点,包括移动、删除等,用REORDER表示

对于节点之间的差异,我们可以很方便地使用上述四种方式进行记录,比如当旧节点被替换时:

{type:REPLACE,node:newNode}

而当旧节点的属性被修改时:

{type:PROPS,props: newProps}

在深度优先遍历的过程中,每个节点都有一个编号,如果对应的节点有变化,只需要把相应变化的类别记录下来即可。下面是具体实现:

function dfsWalk(oldNode, newNode, index, patches) {var currentPatch = [];if (newNode === null) {//依赖listdiff算法进行标记为删除} else if (util.isString(oldNode) && util.isString(newNode)) {if (oldNode !== newNode) {//如果是文本节点则直接替换文本currentPatch.push({type: patch.TEXT,content: newNode});}} else if (oldNode.tagName === newNode.tagName && oldNode.key === newNode.key) {//节点类型相同//比较节点的属性是否相同var propsPatches = diffProps(oldNode, newNode);if (propsPatches) {currentPatch.push({type: patch.PROPS,props: propsPatches});}//比较子节点是否相同diffChildren(oldNode.children, newNode.children, index, patches, currentPatch);} else {//节点的类型不同,直接替换currentPatch.push({ type: patch.REPLACE, node: newNode });}if (currentPatch.length) {patches[index] = currentPatch;}
}

 

比如对上文图中的两颗虚拟DOM树,可以用如下数据结构记录它们之间的变化:

var patches = {1:{type:REPLACE,node:newNode}, //h1节点变成h55:{type:REORDER,moves:changObj} //ul新增了子节点li}

 

(3).对真实DOM进行最小化修改

通过虚拟DOM计算出两颗真实DOM树之间的差异后,我们就可以修改真实的DOM结构了。上文深度优先遍历过程产生了用于记录两棵树之间差异的数据结构patches, 通过使用patches我们可以方便对真实DOM做最小化的修改。

//将差异应用到真实DOM
function applyPatches(node, currentPatches) {util.each(currentPatches, function(currentPatch) {switch (currentPatch.type) {//当修改类型为REPLACE时case REPLACE:var newNode = (typeof currentPatch.node === 'String')? document.createTextNode(currentPatch.node) : currentPatch.node.render();node.parentNode.replaceChild(newNode, node);break;//当修改类型为REORDER时case REORDER:reoderChildren(node, currentPatch.moves);break;//当修改类型为PROPS时case PROPS:setProps(node, currentPatch.props);break;//当修改类型为TEXT时case TEXT:if (node.textContent) {node.textContent = currentPatch.content;} else {node.nodeValue = currentPatch.content;}break;default:throw new Error('Unknow patch type ' + currentPatch.type);}});
}
http://www.lbrq.cn/news/2554615.html

相关文章:

  • 昆明网站开发哪家好网站定制
  • 上海松江区做网站的公司成都百度seo优化公司
  • 对省政府网站建设的发展有期待seo快速推广
  • 平顶山公司做网站seo关键词优化系统
  • 网站开发团队介绍谷歌商店下载官网
  • 品划做网站广告公司广告牌制作
  • 常德市人民政府网站今日最新闻
  • 律师网站深圳网站设计关键词热度分析工具
  • 河南映天建设网站关键词优化技巧
  • 网站建设综合推荐指数网站
  • 做网站咋不用买虚拟机网址和网站的区别
  • 海南专业网站建设seo的排名机制
  • 做网站服务器需要系统关键词生成器 在线
  • 网站建设差打不开疫情防控最新通告
  • 重庆百度网站快速排名怎么样推广自己的产品
  • 高端企业门户网站建设服务公司外贸营销推广
  • 做视频网站视频存放问题企业培训计划方案
  • 榆林公司做网站外链发布
  • 有没有发布需求的网站网络营销公司招聘
  • 河南省建设监理协会网站重庆做网络优化公司电话
  • 想做棋牌网站怎么做google下载安卓版下载
  • wordpress归档侧边栏按分类长沙做优化的公司
  • linux做网站西安官网seo技术
  • 江苏网站建设空间徐州百度推广公司
  • 做百度推广首先要做网站吗上海网站建设服务
  • 做网站学不需要做后台管理系统能打开各种网站的浏览器下载
  • wordpress的css文件在百度上如何做优化网站
  • 美术生最吃香的专业seo推广公司有哪些
  • 企业网站优化方案模板什么是网络营销的核心
  • 做网站后台数据库建设指数基金定投技巧
  • 十、SpringBootWeb快速入门-入门案例
  • Rockchip RK3568J +FPGA边缘智能系统及储能网关
  • 物联网与AI深度融合,赋能企业多样化物联需求
  • 学习Markdown
  • Python 使用pandas库实现Excel字典码表对照自动化处理
  • 高效管理Hosts文件的终极工具