在教程开端先说些题外话,我喜欢在学习一门新技术或读过一本书后,写一篇教程或总结,既能帮助消化,也能加深印象和发现自己未注意的细节,写的过程其实仍然是一个学习的过程。有个记录的话,在未来需要用到相关知识时,也方便自己查阅。
二、组件
组件的构建方式有3种:React.createClass()、ES6的类和函数。当用ES6的类来构建时,所有的组件都继承自抽象基础类
1)props
如果一个组件要做到可复用,那么它应该是可配置的。为此,React提供了props属性,它的使用如下所示。
class Search extends Component { render() { return ( <div> <button className="btn" data-url={this.props.url}>{"<搜索>"}</button> </div> ); } } <Search url="http://www.pwstrick.com" />
先给Search组件定义一个名为url的属性,然后在组件内部,可以通过引用props属性来获取url的值。有一点要注意,props是只读属性,因此在组件内部无法修改它。
React为组件提供了默认的配置,可以调用它的静态属性defaultProps。总共有两种写法实现默认配置,如下代码所示,其中写法一用到了ES6中的static关键字。
//写法一class Search extends Component { static defaultProps = { url: "http://jane.com" }; } //写法二Search.defaultProps = { url: "http://jane.com" }; <Search />
此时,即使组件不定义url属性,在组件内部还是会有值。
props还有一个特殊的属性:children,它的值是组件内的子元素,如下代码所示,children属性的值为“<h1>React扫盲教程</h1>”。
class Search extends Component { render() { return ( <div> {this.props.children} </div> ); } } <Search> <h1>React扫盲教程</h1></Search>
2)state
组件的呈现会随着内部状态和外部配置而改变,通常会在组件的构造函数中初始化需要的内部状态,如下代码所示,为文本框添加默认提示。
class Search extends Component { constructor (props) { super(props); this.state = { txt: "请输入关键字" }; } }
React还提供了setState()方法,用于更新组件的状态。注意,不要通过直接为state赋值的方式来更新状态,因为setState()方法在更新状态后,还会调用render()方法,重新渲染组件。此外,React为了提升性能,会把多次setState()调用合并成一次,像下面这样写打印出的txt属性的值仍然是前一次的值,因此状态更新是异步的。
this.setState({ txt: "React" }); console.log(this.state.txt); //"请输入关键字"
3)生命周期
组件的生命周期(life cycle)可简单的分为4个阶段:初始化(Initialization)、挂载(Mounting)、更新(Updation)和卸载(Unmounting),具体如下图所示。每个阶段都会对应几个方法,其中包含will的方法会在某个方法之前被调用,而包含did的方法会在某个方法之后被调用。

1、在初始化阶段,会设置props、state等属性。
2、在挂载阶段,两个挂载方法将以组件的render()为分界点。
3、更新阶段发生在传递props或执行setState()的时候。
4、当一个组件被移除时,就会调用componentWillUnmount()方法。
当组件在页面中输出时,在控制台将依次输出“will mount”、“render”和“did mount”。
class Search extends Component { componentWillMount() { console.log("will mount"); } componentDidMount() { console.log("did mount"); } render() { console.log("render"); } }
三、React和DOM
1)ReactDOM
当一个组件设置了Context后,它的子组件就能直接访问Context中的内容,Context相当于一个全局变量,但作用域仅限于它的子组件中。总共有两种Context的实现方式,都基于生产者消费者模式。首先来看第一种,具体代码如下所示。
import PropTypes from 'prop-types'; class Grandpa extends Component { getChildContext() { return { name: "strick" }; } render() { return (<Son />); } } Grandpa.childContextTypes = { name: PropTypes.string }; class Son extends Component { render() { return (<Grandson />); } } class Grandson extends Component { render() { let { name } = this.context; return (<div>爷爷叫{name}</div>); } } Grandson.contextTypes = { name: PropTypes.string };
