- React是一个专注提供清晰、简洁、灵活的View层解决方案的库
- 特点:轻
- 组件化的开发思路
React组件
- React组件的构建方式
- 用
React.createClass
构建组件是 React 最传统、也是兼容性最好的方法。
const Button = React.createClass({
getDefaultProps() {
return {
color: 'blue',
text: 'OK',
};
},
render() {
const { color, text } = this.props;
return (
<button className={`btn btn-${color}`}>
<em>{text}</em>
</button>
);
}
});
- 用ES6 标准的类语法的方式来构建。官方推荐。
class Greeting extends React.Component {
static defaultProps = {
name: 'World',
};
static propTypes = {
name: React.PropTypes.string.isRequired,
};
render() {
return (
<h1>Hello, {this.props.name}</h1>
);
}
}
- 使用无状态函数构建
function Button({ color = 'blue', text = 'OK' }) {
return (
<button className={`btn btn-${color}`}>
<em>{text}</em>
</button>
);
}
组件本身即上面两种 React 组件构建方法中的 render 方法。
- 组件内的属性和状态
props
我们可以通过this.props.xx的形式获取组件对象的属性,对象的属性可以任意定义,但要避免与JavaScript关键字冲突。
组件可以定义初始值,自己不可更改props属性值,只允许从父组件中传递过来:
// 父组件
class ParentComponent extends React.Component{
render(){
return(<Child name="name">);
}
}
// 子组件
class Child extends React.Component{
render(){
return(<Text>{this.props.name}</Text>);
}
}
父组件向子组件传递name="name"的props属性,在子组件中使用this.props.name引用此属性。
属性类型prop type和默认属性 default prop可以通过类中的 static来声明:
class Demo extends React.Component {
// 默认props
static defaultProps = {
autoPlay: false,
maxLoops: 10,
}
// propTypes用于验证转入的props
static propTypes = {
autoPlay: React.PropTypes.bool.isRequired,
maxLoops: React.PropTypes.number.isRequired,
posterFrameSrc: React.PropTypes.string.isRequired,
}
state = {
loopsRemaining: this.props.maxLoops,
}
}
- 遍历对象的属性
this.props.children会返回组件对象的所有属性。
React 提供一个工具方法 React.Children 来处理 this.props.children 。我们可以用 React.Children.map或React.Children.forEach 来遍历子节点。
var NotesList = React.createClass({
render: function() {
return (
<ol>
{
React.Children.map(this.props.children, function (child) {
return <li>{child}</li>;
})
}
</ol>
);
}
});
ReactDOM.render(
<NotesList>
<span>hello</span>
<span>world</span>
</NotesList>,
document.body
);
state
组件用来改变自己状态的属性,通常使用setState({key:value})来改变属性值触发界面刷新,不能使用this.state.xxx来直接改变。 典型的场景是在接收到服务器返回的新数据,或者在用户输入数据之后。
对于经常改变的数据且需要刷新界面显示,可以使用state。
对于不需要改变的属性值可以使用props。
React数据流
在 React 中,数据是自顶向下单向流动的,即从父组件到子组件。
- props是由父组件传递给子组件的。
- state是子组件内部的维护的数据。
Virtual Dom
React 最大的特色是当View层在渲染的时候,它不会直接从模板里面去构建一个DOM节点. 首先, 它创建一些暂时的, 虚拟的 DOM, 然后和真实的DOM还有创建的Diffs一起做对比, 然后才决定需不需要渲染。
- JSX
- diff算法
React生命周期
生命周期:广义上 => 各种客观事物的阶段性变化及其规律。生命体的周期是单一,不可逆,而软件开发的生命周期会根据方法的不同在完成前重新开始。
React 组件的生命周期可以分为挂载(Mounting)、渲染(Updating)和卸载(Unmounting)这几个阶段。
当渲染后的组件需要更新时,重新去渲染组件,直至卸载。
- Mounting:初始化阶段(已插入真实 DOM)
初始化阶段可以使用的函数:
getDefaultProps
: 只调用一次,实例之间共享引用
getInitialState
: 初始化每个实例特有的状态
componentWillMount
: render之前最后一次修改状态的机会。如果在这个方法内调用setState,render()将会感知到更新后的state,将会执行仅一次,尽管state改变了。
render
: 只能访问this.props和this.state,只有一个顶层组件,不允许修改状态和DOM输出
componentDidMount
: 成功render并渲染完成真实DOM之后触发,可以修改DOM
调用顺序
当组件在客户端被实例化,第一次被创建时,以下方法依次被调用:
getInitialState
componentWillMount
render
componentDidMount
- Updating :更新
componentWillReceiveProps(object nextProps)
在组件接收到新的 props 的时候调用。在初始化渲染的时候,该方法不会调用。
用此函数可以作为 react 在 prop 传入之后, render() 渲染之前更新 state 的机会。老的 props 可以通过 this.props 获取到。在该函数中调用 this.setState() 将不会引起第二次渲染。
shouldComponentUpdate(object nextProps, object nextState)
: 在接收到新的 props 或者 state,将要渲染之前调用。
该方法在初始化渲染的时候不会调用,在使用 forceUpdate 方法的时候也不会。如果确定新的 props 和 state 不会导致组件更新,则此处应该 返回 false。
心得:重写此方法你可以根据实际情况,来灵活的控制组件当 props 和 state 发生变化时是否要重新渲染组件,也是优化性能的一项手段。
componentWillUpdate(object nextProps, object nextState)
:在接收到新的 props 或者 state 之前立刻调用。
在初始化渲染的时候该方法不会被调用。使用该方法做一些更新之前的准备工作。
注意:你不能在该方法中使用 this.setState()。如果需要更新 state 来响应某个 prop 的改变,请使用 componentWillReceiveProps。
componentDidUpdate(object prevProps, object prevState)
: 在组件的更新已经同步到 DOM 中之后立刻被调用。
该方法不会在初始化渲染的时候调用。使用该方法可以在组件更新之后操作 DOM 元素。 - Unmounting:移除
componentWillUnmount
:在组件从 DOM 中移除的时候立刻被调用。
在该方法中执行任何必要的清理,比如无效的定时器,或者清除在componentDidMount 中创建的 DOM 元素。
Redux
react-redux
库提供了一个组件和一个 API 帮助 Redux
和 React
进行绑定,
一个是 React 组件 <Provider/> ,一个是 connect()。
<Provider/> 接受一个 store 作为props,它是整个 Redux 应用的顶层组件,
connect() 提供了在整个 React 应用的任意组件中获取 store 中数据的功能。
它们一个将组件与redux关联起来,一个将store传给组件。组件通过dispatch发出action,store根据action的type属性调用对应的reducer并传入state和这个action,reducer对state进行处理并返回一个新的state放入store,connect监听到store发生变化,调用setState更新组件。
流程:
一、Provider组件接受redux的store作为props,然后通过context往下传。
二、connect函数收到Provider传出的store,然后接受三个参数mapStateToProps,mapDispatchToProps和组件,并将state和actionCreator以props传入组件,这时组件就可以调用actionCreator函数来触发reducer函数返回新的state,connect监听到state变化调用setState更新组件并将新的state传入组件。
connect(state => state, action)(Component);