React基础(Diff算法,属性和状态)
1.React的背景原理
(1)React Diff算法流程
(2)React虚拟DOM机制
React引入了虚拟DOM(Virtual DOM)的机制:在浏览器端用Javascript实现了一套DOM API。
基于React进行开发时所有的DOM构造都是通过虚拟DOM进行,每当数据变化时,React都会重新构建整个DOM树,然后React将当前整个DOM树和上一次的DOM树进行对比,得到DOM结构的区别,然后仅仅将需要变化的部分进行实际的浏览器DOM更新。
而且React能够批处理虚拟DOM的刷新,在一个事件循环(Event Loop)内的两次数据变化会被合并,例如你连续的先将节点内容从A变成B,然后又从B变成A,React会认为UI不发生任何变化,而如果通过手动控制,这种逻辑通常是极其复杂的。
尽管每一次都需要构造完整的虚拟DOM树,但是因为虚拟DOM是内存数据,性能是极高的,而对实际DOM进行操作的仅仅是Diff部分,因而能达到提高性能的目的。这样,在保证性能的同时,开发者将不再需要关注某个数据的变化如何更新到一个或多个具体的DOM元素,而只需要关心在任意一个数据状态下,整个界面是如何Render的。
总之一句话:根据 React 的设计,所有的 DOM 变动,都先在虚拟 DOM 上发生,然后再将实际发生变动的部分,反映在真实 DOM上
2.属性和状态
React 的一大创新,就是将组件看成是一个状态机,一开始有一个初始状态,然后用户互动,导致状态变化,从而触发重新渲染 UI
React里面的React.render方法:
React.render 是 React 的最基本方法,用于将模板转为 HTML 语言,并插入指定的 DOM 节点。
下面的例子就是把<h1>标题插入到container节点中
这里需要注意的是,react并不依赖jQuery,当然我们可以使用jQuery,但是render里面第二个参数必须使用JavaScript原生的getElementByID方法,不能使用jQuery来选取DOM节点。
(1)状态:
(2)状态的用法:
》getInitialState(函数):初始化每个实例特有的状态。它只是在实例创建的时候被调用,创建完毕之后不会再被调用。
》setState(函数):更新组件的状态。
$(document).ready(function(){ var InputState=React.createClass({ getInitialState:function(){ return {enable:false}; }, handleClick:function(){ this.setState({enable:!this.state.enable}); }, render:function(){ return ( <p> <input type="text" disabled={this.state.enable}/> <button onClick={this.handleClick}>Change State</button> </p> ); } }); ReactDOM.render(<InputState/>,document.getElementById('container')); });
这里,我们又使用到了一个方法getInitialState,这个函数在组件初始化的时候执行,必须返回NULL或者一个对象。这里我们可以通过this.state.属性名来访问属性值,这里我们将enable这个值跟input的disabled绑定,当要修改这个属性值时,要使用setState方法。我们声明handleClick方法,来绑定到button上面,实现改变state.enable的值。
原理分析:
上面代码是一个InputState 组件,它的 getInitialState
方法用于定义初始状态,也就是一个对象,这个对象可以通过 this.state
属性读取。当用户点击组件,导致状态变化,this.setState
方法就修改状态值,每次修改以后,自动调用 this.render
方法,再次渲染组件。
这里值得注意的几点如下:
1)getInitialState函数必须有返回值,可以是NULL或者一个对象。
2)访问state的方法是this.state.属性名。
3)变量用{}包裹,不需要再加双引号。如:{this.props.name}
(3)属性:
组件的属性可以接受任意值,字符串、对象、函数等等都可以
React 允许将代码封装成组件(component),然后像插入普通 HTML 标签一样,在网页中插入这个组件。React.createClass 方法就用于生成一个组件类。
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8"> <title>属性</title> <script src="./build/react.js"></script> <script src="./build/react-dom.js"></script> <script src="./build/browser.min.js"></script> <script src="./build/jquery.min.js"></script> </head> <body> <div id="container"></div> </body> <script type="text/babel" > $(document).ready(function(){ var Greet=React. createClass({ render:function(){ return <h1>Hello {this.props.name}</h1>; } }); ReactDOM.render(<Greet name="Jack"/>, document.getElementById('container') ); });
注意:
首先,最后一个 <script>
标签的 type
属性为 text/babel
。这是因为 React 独有的 JSX 语法,跟 JavaScript 不兼容。凡是使用 JSX 的地方,都要加上 type="text/babel"
。
其次,上面代码一共用了三个库: react.js
、react-dom.js
和 Browser.js
,它们必须首先加载。其中,react.js
是 React 的核心库,react-dom.js
是提供与 DOM 相关的功能,Browser.js
的作用是将 JSX 语法转为 JavaScript 语法,这一步很消耗时间,实际上线的时候,应该将它放到服务器完成。
关于属性几个注意的地方:
1)获取属性的值用的是this.props.属性名
2)创建的组件名称首字母必须大写。如:var Greet=React. createClass({});
3)为元素添加css的class时,要用className。
4)组件的style属性的设置方式也值得注意,要写成style={{width: this.state.witdh}}。第一重大括号表示这是 JavaScript 语法,第二重大括号表示样式对象。
3.属性和状态的区别
由于 this.props
和 this.state
都用于描述组件的特性,可能会产生混淆。
一个简单的区分方法是,this.props
表示那些一旦定义,就不再改变的特性,而 this.state
是会随着用户互动而产生变化的特性。
参考文档:
http://www.cocoachina.com/webapp/20150721/12692.html
http://www.ruanyifeng.com/blog/2015/03/react.html