react学习小结
本文是我学习react的阶段性小结,如果看官你是react资深玩家,那么还请就此打住移步他处,如果你想给一些建议和指导,那么还请轻拍~
目前团队内对react的使用非常普遍,之前对react使用不多,正好我目前在做的项目也在使用react+redux,借着这个机会系统的学习下react+redux。
react是什么
react是一个JavaScript类库,通过react,我们可以构建可组合的UI,也就是说,我们可以通过重用组件来组合出我们的UI。可以说react的核心便是组件,目的就是重用和组合。
react解决什么问题
官网有这样一句话.
We built React to solve one problem: building large applications with data that changes over time.
我们知道,随着应用规模的不断扩大,UI背后的数据模型越来越复杂,业务逻辑也不可避免的变得越来越复杂,以至于复杂到仅仅是修复一个简单的问题我们就需要投入大量的时间和精力。
现有的很多前端框架都在致力于解决这样的问题,基本思想都是基于MV*的模式,这里有一篇文章详细介绍了各种MV*模式的原理和优缺点。
那么,react是如何解决这个问题的呢?
react聚焦于组件。react理解的组件实际上就是一个状态机。当组件处于某个状态时,就输出这个状态对应的界面。在React中,我们只需要简单的去更新某个组件的状态,然后输出基于新状态的整个界面。React负责以最高效的方式去比较两个界面并更新DOM树。至于如何对组件之外的数据进行管理,react提出了flux方案。
react点点点
生命周期
前面我们知道,react组件是一个状态机器,以状态为输入,以界面为输出。在不同状态切换之间,react提供了一系列的生命周期方法,大致可以分为如下三类:
实例化时期
react组件在实例化时会依次调用如下组件方法:
- getDefaultProps
- getInitialState
- componentWillMount
- render
- componentDidMount
存在期
当react组件被实例化后,用户的一些操作会导致组件状态的更新,此时如下方法将依次被调用:
- componentWillReceiveProps
- shouldComponentUpdate
- componentWillUpdate
- render
- componentDidUpdate
销毁时期
在组件销毁的时候,会调用如下组件方法:
- componentWillUnmount
这里有一段简单的测试代码:
var ChildComponent = React.createClass({
render: function () {
console.log("call render"); return ( <div> {this.props.data} </div> ); }, componentWillReceiveProps: function () { console.log("call componentWillReceiveProps"); }, shouldComponentUpdate: function () { console.log("call shouldComponentUpdate"); return true; }, componentWillUpdate: function () { console.log("call componentWillUpdate"); }, componentDidUpdate: function () { console.log("call componentDidUpdate"); }, componentWillUnmount: function () { console.log("call componentWillUnmount"); } }); var MyComponent = React.createClass( { getDefaultProps: function () { // console.log("call getDefaultProps"); return { className: "test" }; }, getInitialState: function () { // console.log("call getInitialState"); // console.log("log prop: ", this.props); return { text: "something" }; }, componentWillMount: function () { console.log("call componentWillMount"); }, componentDidMount: function () { console.log("call componentDidMount"); }, render: function () { console.log("call render"); var child; if (this.state.text === "after click") { child = null; } else { child = <ChildComponent data={this.state.text} />; } return ( <div className={this.props.className} onClick={this.handleClick}> {child} </div> ); }, handleClick: function () { this.setState({ text: "after click" }); } }); ReactDOM.render( <MyComponent />, document.getElementById("content") );
常用API
关于API的部分,官网已经给了详尽的说明,此处略去。
JSX
JSX是react的核心组件之一。react坚信标签和生成它的代码是紧密相连的,如果展示逻辑非常复杂(事实上大多数情况下都是),那么通过模板语言来实现这些逻辑会产生大量代码,于是react做了一个非常简单、可选类似HTML语法 ,通过函数调用即可生成模板的编译器,称为JSX。
通过JSX,我们可以用HTML的语法创建JavaScript对象。比如,为了在React中生成一个链接,通过纯JavaScript可以这么写:
React.createElement('a', {href: 'http://facebook.github.io/react/'}, 'Hello React!')
通过JSX这就变成了:
<a href="http://facebook.github.io/react/">Hello React!</a>
我们发现通过JSX,代码会更加简洁和易读,使用起来也更加方便。
更过关于JSX的内容请参考官方文档.
组合可重用的组件
前面我们知道,react的核心就是组件,目的就是重用和组合。那么我们如何才能做到组件可重用和组合呢?
首先说说组合。
组合描述的是一种从属关系,在面向对象编程中被描述为HAS-A的关系。
在react中,我们通过如下的代码实现组合:
<Parent><Child data={this.props.childData} /></Parent>
在这个例子中,Parent中有一个Child的实例,Parent是拥有着。在组件中,组件不能改变自身的props,组件的props始终与组件的拥有着设置的保持一致。
这里就有一个非常有趣的事情。组件的props永远来自于组件的拥有者(默认的除外),组件的拥有者可以通过它的props 或state计算出一些值,并把这些值绑定到它们拥有的组件的props上,即在react中,数据就通过props的方式从组件的拥有者单向的流向了组件。
再说说可重用。
可重用,第一感觉就是有一层抽象含义在其中。我们从若干相似的组件中抽象出一层接口,实现公共的组件。换句话说,我们把一些页面上通用的设计元素(按钮、表单等)拆分成接口设计良好的可复用组件。每一个组件经过良好的测试和封装,那么在下次开发相似的页面的时候,可以写更少的代码,也意味着更高的开发效率和更高的质量。