React 起源于 Facebook 内部项目,是一个用来构建用户界面的 Javascript 库,至关于MVC架构中的V层框架,与市面上其余框架不一样的是,React 把每个组件当成了一个状态机,组件内部经过 state 来维护组件状态的变化,当组件的状态发生变化时,React 经过虚拟DOM技术来增量而且高效的更新真实DOM。本文将对React 的这些特色进行简单的介绍。html
考虑到有的同窗还未曾了解过 React,咱们先来写一个简单的 React 组件,让你们一睹为快!前端
// 建立一个HelloReact组件 var HelloReact = React.createClass({ render:function(){ return ( <div> Hello React! </div> ) } }); // 使用HelloReact组件 ReactDOM.render( <HelloReact />, document.querySelector('body') )
这样就定义了一个React组件,固然要运行这段代码是有条件的,须要引入React库,还须要引入JSX语法转换库,这里很少说了,这些基础的东西还须要各位亲自实践才好!ajax
在前端开发的过程当中,咱们常常会作的一件事就是将变化的数据实时更新到UI上,这时就须要对DOM进行更新和从新渲染,而频繁的DOM操做一般是性能瓶颈产生的缘由之一,有时候咱们会遇到这样一种尴尬的状况:好比有一个列表数据,当用户执行刷新操做时,Ajax会从新从后台请求数据,即便新请求的数据和上次彻底相同,DOM也会被所有更新一遍并进行从新渲染,这样就产生了没必要要的性能开销。服务器
React为此引入了虚拟DOM(Virtual DOM)机制:对于每个组件,React会在内存中构建一个相对应的DOM树,基于React开发时全部的DOM构造都是经过虚拟DOM进行,每当组件的状态发生变化时,React都会从新构建整个DOM数据,而后将当前的整个DOM树和上一次的DOM树进行对比,得出DOM结构变化的部分(Patchs),而后将这些Patchs 再更新到真实DOM中。整个过程都是在内存中进行,所以是很是高效的。借用一张图能够清晰的表示虚拟DOM的工做机制:架构
React 把每一个组件都看成一个状态机来维护和管理,所以每一个组件都拥有一套完整的生命周期,大体能够分为三个过程:初始化、更新和销毁。生命周期的每个过程都明确的反映了组件的状态变化。对于开发来讲就能很容易的把握组件的每一个状态,不一样的状态时期作对应的事情,互不干扰。如下是和组件生命周期相关的几个方法:框架
getDefaultProps异步
getInitialState性能
componentWillMountthis
componentDidMounturl
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate
componentDidUpdate
componentWillUnmount
对于外部系统来讲,组件是一个独立存在的封闭系统,内部的逻辑被隐藏,只对外暴露传递数据的接口,而React为咱们提供了两种方式来向组件传递数据,即 props 和 state。
props 是在调用 ReactDOM.render() 时经过标签属性xxx传递,而后经过 this.props.xxx 来获取,getDefaultProps 容许你为组件设置一个默认的props值,在没有传递props的状况下显示默认值。
// 建立HelloReact组件 var HelloReact = React.createClass({ /** * 当设置props的默认值 当没有传递时显示默认值 * @return {} */ getDefaultProps:function(){ return { data:"暂无数据" } }, render:function(){ return ( <div> //显示data,当props发生变化时会自动更新 {this.props.data} </div> ) } });//传递props属性data ReactDOM.render( <HelloReact data={"Hello React!"} />, document.querySelector('body') )
和 props 不一样的是,state不能经过外部传递,所以在使用state以前,须要在 getInitialState 中为state设置一个默认值,而后才能经过 this.state.xxx 来访问,当组件被挂载完成时,触发 componentDidMount 方法,咱们能够在这里经过Ajax请求服务器数据,而后再经过 setState() 把state的值设置为真实数据。
// 建立HelloReact组件 var HelloReact = React.createClass({ /** * 设置组件的初始值 * @returns {{data: Array, msg: string}} */ getInitialState:function(){ return { data:"数据加载中..." //初始值为[] } }, /** * 挂载后首次加载数据 */ componentDidMount:function(){ this.requestData();//请求数据 }, /** * 请求后台数据 */ requestData:function(){ $.ajax({ url:'xxxx.ashx', data:{}, success:function(data){ this.setState({ data:data //经过setState()更新服务器数据 }) } }.bind(this)) }, render:function(){ return ( <div> {this.state.data} </div> ) } }); ReactDOM.render( <HelloReact />, document.querySelector('body') )
props属性是只读的,若是想要改变props的值,只能经过从新调用render()来传递新的props,但要注意的是,从新执行render()组件不会被从新挂载,而是经过虚拟DOM技术进行增量更新和渲染,这时还会触发 componentWillReceiveProps 方法,并将新的props做为参数传递,你能够在这里对新的props进行处理。
相比props,state天生就是用来反映组件状态的,所以它的值是能够被改变的,当state的值被改变时,经过setState就能够改变state的值,React一样也是采用虚拟DOM技术来计算须要被更新的部分,而不是牵一发动全身的更新和渲染。
当 props 和 state 的状态发生变化后,组件在即将更新以前还会触发一个叫 shouldConponentUpdate 的方法,若是 shouldConponentUpdate 返回的是 true,无论props和state 的值和上一次相比有没有变化,React 都会老老实实的进行对比。此时,若是你肯定以及确定两次数据没有变化,那就让 shouldConponentUpdate 返回 false,React就不会进行diff了,更不会从新渲染了。瞬间省去了 diff 的时间。
当组件从DOM中被移除时,React会销毁之。在销毁以前,细心的React还触发 componentWillUnmount 来通知你,看你最后有没有什么话想对这个即将销毁的组件说,固然你没什么事就不用了。
咱们已经知道能够经过 props 和 state 两种方式向组件传递数据,props 是只读的不能被改变,而 state 是用来反映一个组件的状态,是能够改变的。所以,当组件所须要的数据在调用时是已经肯定的,不频繁发生变化的,就可使用props来传递,相反,当组件所须要的数据在调用时不能肯定,须要等待异步回调时才能肯定,好比ajax请求数据,input 的 onchange事件,这时就须要使用state 来记录和改变这些值得变化。
原创发布 @一像素 2016