为什么选择我--ReactJS
在页面中如何大面积操作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的更多相关文章
- 一看就懂的ReactJs入门教程-精华版
现在最热门的前端框架有AngularJS.React.Bootstrap等.自从接触了ReactJS,ReactJs的虚拟DOM(Virtual DOM)和组件化的开发深深的吸引了我,下面来跟我一起领 ...
- 前端构建大法 Gulp 系列 (二):为什么选择gulp
系列目录 前端构建大法 Gulp 系列 (一):为什么需要前端构建 前端构建大法 Gulp 系列 (二):为什么选择gulp 前端构建大法 Gulp 系列 (三):gulp的4个API 让你成为gul ...
- ReactJS webpack实现JS模块化使用的坑
从一个原生HTML/CSS/JS模式的网页改造到ReactJS模块化的结构,需要以下步骤: (1)引用ReactJS框架 ->(2)使用webpack 工具 -> (3)配置webpack ...
- reactjs 接入数据模型以及markdown语法的支持
页面如下: reactjs 数据接入,直接定义数据(json),如下: reactjs 数据接入,从服务器抓取数据(json),如下:
- 初探ReactJS.NET 开发
ReactJS通常也被称为"React",是一个刚刚在这场游戏中登场的新手.它由Facebook创建,并在2013年首次发布.Facebook认为React在处理SPA问题上可以成 ...
- ReactJs笔记
中文教程:http://reactjs.cn/ 实例: http://www.ruanyifeng.com/blog/2015/03/react.html
- redux的中间层 --reactjs学习
React只负责UI层,也就是我们通常在MVC框架中 所说的View层,所以在使用React开发中 我们得引入Redux 负责Model 一开始学习Redux的中间层 有点 摸不到头, 其实只要你注意 ...
- 初识ReactJs(一)
React的开发背景 ReactJS官网地址:http://facebook.github.io/react/ Github地址:https://github.com/facebook/react J ...
- D2.Reactjs 操作事件、状态改变、路由
下面内容代码使用ES6语法 一.组件的操作事件: 1.先要在组件类定义内定义操作事件的方法,如同event handler.若我需要监听在组件内的Button的点击事件onClick,首先定义监听方法 ...
随机推荐
- “未能加载文件或程序集file:///E:/MoneySet.dll或它的某一个依赖项,试图加载格式不正确的程序,行203,位置5. 文件:MReportSet.resx”,
http://bbs.csdn.net/topics/390334265 1.右键卸载项目2.右键选择编辑工程文件,在打开的文件的最后一行</project>之前加以下内容: <Pr ...
- hbase 架构
由图可以client并不直接和master交互,而是与zookeeper交互,所以master挂掉,依然会对外提供读写服务, 但master挂掉后无法提供数据迁移服务. 所以说 hbase无单点故障, ...
- 000webhost找不到文件自定义错误
1.新建一个名为.htaccess的文本文件:2.在文件中输入如下代码:ErrorDocument 404 /404.php3.保存文件,将.htaccess上传到域名的根目录,再验证,呵呵,成功了! ...
- [BZOJ 1086] [SCOI2005] 王室联邦 【树分块】
题目链接:BZOJ - 1086 题目分析 这道题要求给树分块,使得每一块的大小在 [B, 3B] 之间,并且可以通过一个块外的节点(块根)使得整个块联通. 那么我们使用一种 DFS,维护一个栈,DF ...
- HTML和CSS特殊属性
禁止用户选中html元素: <body onselectstart="return false"> 禁止事件传递: favorite.find("span&q ...
- Java语言基础(一) 标识符
Java标识符的问题: ①不可以以数字开头 int 123number = 0; //错误 ②可以使用任意的货币符号(¥和$等等)中文也可以 int $i = 0; //正确 int ¥i = 1; ...
- xcode5 ios7升级后的一系列问题解决
framework not found IOKit解决办法,打开终端:cd /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS. ...
- 网络流(最大流)CodeForces 512C:Fox And Dinner
Fox Ciel is participating in a party in Prime Kingdom. There are n foxes there (include Fox Ciel). T ...
- jQuery 数据 DOM 元素 核心 属性
jQuery 参考手册 - 数据 .clearQueue() 从序列中删除仍未运行的所有项目 .clearQueue(queueName) $("div").clearQueue( ...
- 利用Trie树对字符串集合进行排序并计算特征值
该算法用于将一组乱序的字符串反序列化到一个Trie树中,这个过程即可视为对字符串进行了一次排序. 还可以通过调用 GetFeatureString 将该 Trie 树重新序列化. #include & ...