在页面中如何大面积操作DOM的话,性能肯定是一个很大的问题,然而聪明的ReactJS实现了Virtual DOM技术,这是他的亮点之一。将组件的DOM结构映射到这个Virtual DOM对象上,并且ReactJS还实现了一套Diff算法,这也是他亮点之一。当需要更新组件的时候,会通过Diff算法找到要变更的内容,最后,在把这个修改更新到实际的DOM节点上,所以,组件更新实际上不是真的渲染整个DOM树,而是指更新需要修改的DOM节点,这样在性能上会比原生DOM快很多。

那么这个Virtual DOM到底是什么?假设我们要创建一个组件,其结构如下:

 <ul>
<li>
A
</li>
<li>
<ul>
<li>
B
</li>
</ul>
</li>
</ul>

然后我们开始创建原生组件:

 //用JSX实现的
var root = <ul>
<li>A</li>
<li>
<ul>
<li>
B
</li>
</ul>
</li>
</ul>;
//用javascript实现的
var A = React.createElement('li',null,'A');
var B = React.createElement('ul',null,React.createElement('li',null,'B'));
var root = React.createElement('ul',null,A,B);
//输出虚拟的DOM结构
console.log(root);

打开控制台我们就能看到输出的一个javascript的对象,没错这就是我们所说的Virtual DOM对象;

接下来我们看看Diff算法在ReactJS中的体现,首先我们借助浏览器中的MutationObderver功能,对页面元素进行监听

 'use strict';
const mutation = window.MutationObserver
||window.WebKitMutationObserver
||window.MozMutationObserver;
if(!!mutation){
const mutationObserver = new mutation((item) => {
item.forEach((item) => {
console.log(item);
});
});
const options = {
"childList" : true,
"attributes" : true,
"characterData" : true,
"subtree" : true,
"attributeOldValue" : true,
"characterDataOldValue" : true
};
mutationObserver.observe(document.body,options);
}

然后再把ReactJS组件的生命周期进行封装,便于组件来调用

 'use strict';
const LifeCycle = name => {
let obj = {
name : name
};
return Object.assign(obj,Cycle);
};
const Cycle = {
getDefaultProps:function(){
console.log(this.name,'getDefaultProps');
return {};
},
getInitialState:function(){
console.log(this.name,'getInitailState');
return {};
},
componentWillMount:function(){
console.log(this.name,'componentWillMount');
},
componentDidMount:function(){
console.log(this.name,'componentDidMount');
},
componentWillRecieveProps:function(){
console.log(this.name,'componentWillRecieveProps');
},
shouldComponentUpdate:function(){
console.log(this.name,'shouldComponentUpdate');
return true;
},
componentWillUpdate:function(){
console.log(this.name,'componentWillUpdate');
},
componentDidUpdate:function(){
console.log(this.name,'componentDidUpdate');
},
componentWillUnmount:function(){
console.log(this.name,'componentWillUnmount');
}
};

接着定义需要用到的组件

 'use strict';
//A组件
let A = React.createClass({
mixins:[LifeCycle('A')],
render:function(){
console.log('A','render');
return (
<ul>
<li>A</li>
<li>
<ul>
{this.props.children}
</ul>
</li>
</ul>
);
}
});
//B组件
let B = React.createClass({
mixins:[LifeCycle('B')],
render:function(){
console.log('B','render');
return (
<li>B</li>
);
}
});
//C组件
let C = React.createClass({
mixins:[LifeCycle('C')],
render:function(){
console.log('C','render');
return (
<li>C</li>
);
}
});
//D组件
let D = React.createClass({
mixins:[LifeCycle('D')],
render:function(){
console.log('D','render');
return (
<li>D</li>
);
}
});

最后,定义我们的主逻辑

 console.log('----------------first-----------------');
React.render(
<A><B></B><C></C></A>,
document.body
); setTimeout(() => {
console.log('-----------------second--------------');
React.render(
<A><B></B><D></D><C></C></A>,
document.body
);
},1000);

常规的做法就是将B和C组件先删除,然后依次创建和插入A,B,C组件。接下来我们打开浏览器的控制台看下ReactJS是怎么做的

          

从日志中可以看出,React的Diff算法的结果是,A组件不变,先将C组件进行删除,然后在创建D组件并插入D组件,最后创建并插入C组件,这比我们常规的做法省去了对B组件的删除操作。这样其实并没有将Diff算法的作用发挥到极限。下面我们调整下逻辑代码:

 console.log('----------------first-----------------');
React.render(
<A key="A"><B key="B"></B><C key="C"></C></A>,
document.body
); setTimeout(() => {
console.log('-----------------second--------------');
React.render(
<A key="A"><B key="B"></B><D key="D"></D><C key="C"></C></A>,
document.body
);
},1000);

主要的修改就是给每个组件加了一个key属性,此时再来运行下代码看下控制台的日志:

       

可以看出,这次Diff算法与之前的有很大的不同。B组件不变,C组件不变,只是在C组件之前创建并插入了D组件。

以上便是Virtual DOM和Diff算法的一些简单的使用和分析,学习来源:

http://calendar.perfplanet.com/2013/diff/ 《React Native入门与实践》

为什么选择我--ReactJS的更多相关文章

  1. 一看就懂的ReactJs入门教程-精华版

    现在最热门的前端框架有AngularJS.React.Bootstrap等.自从接触了ReactJS,ReactJs的虚拟DOM(Virtual DOM)和组件化的开发深深的吸引了我,下面来跟我一起领 ...

  2. 前端构建大法 Gulp 系列 (二):为什么选择gulp

    系列目录 前端构建大法 Gulp 系列 (一):为什么需要前端构建 前端构建大法 Gulp 系列 (二):为什么选择gulp 前端构建大法 Gulp 系列 (三):gulp的4个API 让你成为gul ...

  3. ReactJS webpack实现JS模块化使用的坑

    从一个原生HTML/CSS/JS模式的网页改造到ReactJS模块化的结构,需要以下步骤: (1)引用ReactJS框架 ->(2)使用webpack 工具 -> (3)配置webpack ...

  4. reactjs 接入数据模型以及markdown语法的支持

    页面如下: reactjs 数据接入,直接定义数据(json),如下: reactjs 数据接入,从服务器抓取数据(json),如下:  

  5. 初探ReactJS.NET 开发

    ReactJS通常也被称为"React",是一个刚刚在这场游戏中登场的新手.它由Facebook创建,并在2013年首次发布.Facebook认为React在处理SPA问题上可以成 ...

  6. ReactJs笔记

    中文教程:http://reactjs.cn/ 实例: http://www.ruanyifeng.com/blog/2015/03/react.html

  7. redux的中间层 --reactjs学习

    React只负责UI层,也就是我们通常在MVC框架中 所说的View层,所以在使用React开发中 我们得引入Redux 负责Model 一开始学习Redux的中间层 有点 摸不到头, 其实只要你注意 ...

  8. 初识ReactJs(一)

    React的开发背景 ReactJS官网地址:http://facebook.github.io/react/ Github地址:https://github.com/facebook/react J ...

  9. D2.Reactjs 操作事件、状态改变、路由

    下面内容代码使用ES6语法 一.组件的操作事件: 1.先要在组件类定义内定义操作事件的方法,如同event handler.若我需要监听在组件内的Button的点击事件onClick,首先定义监听方法 ...

随机推荐

  1. 如何搭建一个独立博客——简明Github Pages与Hexo教程

    摘要:这是一篇很详尽的独立博客搭建教程,里面介绍了域名注册.DNS设置.github和Hexo设置等过程,这是我写得最长的一篇教程.我想将我搭建独立博客的过程在一篇文章中尽可能详细地写出来,希望能给后 ...

  2. xmlns:android作用以及自定义布局属性

    要定制Android layout 中的 attributes关键是要明白android中命名空间定义如: xmlns:android="http://schemas.android.com ...

  3. Android 小闹钟程序

    最近写了个闹钟的程序,看到SharedPreferences在一个程序中可以共享数据,SharedPreferences是一个轻量级的键值存储机制,只可以存储基本数据类型.我就拿来用用,没想到Shar ...

  4. Android应用--新浪微博客户端新特性滚动视图和启动界面实现

    新浪微博客户端新特性滚动视图和启动界面实现 2013年8月20日新浪微博客户端开发之启动界面实现 前言: 使用过新浪微博客户端的童鞋都清楚,客户端每一次升级之后第一次启动界面就会有新特性的介绍,用户通 ...

  5. Invitation Cards(邻接表+逆向建图+SPFA)

    Time Limit: 8000MS   Memory Limit: 262144K Total Submissions: 17538   Accepted: 5721 Description In ...

  6. ☀【HTML5】Modernizr

    Modernizr 使用Modernizr探测HTML5/CSS3新特性

  7. iOS 多线程学习笔记 —— GCD

    本文复制.参考自文章:iOS多线程编程之Grand Central Dispatch(GCD)介绍和使用 ,主要为了加强个人对知识的理解和记忆,不做他用.原作者声明: 著作权声明:本文由http:// ...

  8. HDOJ/HDU 1250 Hat's Fibonacci(大数~斐波拉契)

    Problem Description A Fibonacci sequence is calculated by adding the previous two members the sequen ...

  9. OpenStack Havana 部署在Ubuntu 12.04 Server 【OVS+GRE】(二)——网络节点的安装

    序:OpenStack Havana 部署在Ubuntu 12.04 Server [OVS+GRE] 网络节点: 1.安装前更新系统 安装好ubuntu 12.04 Server 64bits后,进 ...

  10. Django中静态文件引用优化

    静态文件引用优化 在html文件中是用django的静态文件路径时,一般会这么写: <script type="text/javascript" src="/sta ...