@(StuRep)2016.06.10
React的PropTypes使用方法
React.PropTypes.array // 数组 React.PropTypes.bool.isrequired // Boolean 且必要。 React.PropTypes.func // 函式 React.PropTypes.number // 数字 React.PropTypes.object // 对象 React.PropTypes.string // 字符串 React.PropTypes.node // 任何类型的: numbers,strings,elements 或者任何这种类型的数组 React.PropTypes.element // React 元素 React.PropTypes.instanceOf(XXX) // 某种类型的实例 React.PropTypes.oneOf(['foo','bar']) // 其中一个字符串 React.PropTypes.oneOfType([React.PropTypes.string,React.PropTypes.array]) // 其中一种格式类型 React.PropTypes.arrayOf(React.PropTypes.string) // 某种类型的数组(字符串型) React.PropTypes.objectOf(React.PropTypes.string) // 具有某种属性类型的对象(字符串类型) React.PropTypes.shape({ // 是否符合指定格式的对象 color: React.PropTypes.string,fontSize: React.PropTypes.number }); React.PropTypes.any.isrequired // 可以是任何格式,且必要。
_
react-redux中的connect方法
//绑定状态到props上面 function mapStateToProps(state) { return { year: state.calendarReducer.year,month: state.calendarReducer.month,day: state.calendarReducer.day } } //把action所有方法绑定到props上面,同时action具有了dispatch能力 function mapDispatchToProps(dispatch) { return {actions: bindActionCreators(CalendarActions,dispatch)} } export default connect(mapStateToProps,mapDispatchToProps)(App)
mapStateToProps
监听store变化,添加这个才能让组件监听到store里面的状态;
Redux 有一个全局的state,通过将根组件包进Provider,将store分发给所有的子组件,而子组件通过connect方法,获取dispatch事件分发函数,以及需要的props(如果有需要也可以通过connect传入想分发给子组件的action)
_
如何用Redux去管理React的状态
在不使用
Redux
的时候,React
组件间的状态管理需要一层层地传递,使用Redux
可以在最顶层的store
中存储所有的状态,每个组件都可以获得这些状态值。
Redux
主要的三部分:
Store
Action
Reducer
简单的流程:dispatch(action)把action分发到reducer,reducer更新状态然后返回到store,总的容器组件(app)从store(this.props)中获取的值有变,传给子组件的属性变化,触发render重新渲染。
action
Redux中,action主要用来传递操作State的信息,以一个js对象的形式存在,除了其中的type字段为必须的,其他字段都可以定义。如果采用直接声明action的方式,在action越来越多的时候就会很难管理,所以有了action的构造工厂:
//action创建函数 export function getNextMonth() { return {type: GET_NEXT_MONTH} }
reducer
action用来传递信息,reducer就用来处理信息,传入一个旧的state来返回一个新的state。
reducer应该保持“纯函数”特性,入参相同,出参结果一定相同。这也是函数式编程的特点。
function calendarReducer(state = initialState,action) { switch (action.type) { case GET_NEXT_MONTH: return state.month >= 12 ? {...state,year: ++state.year,month: 1} : {...state,month: ++state.month}; case GET_PRE_MONTH: return state.month <= 1 ? {...state,year: --state.year,month: 12} : {...state,month: --state.month}; default: console.log("default calendarReducer state"); return state; } }
在reducer中,需要传入一个默认的state参数,在dispatch一个action区触发state修改的时候,如果reducer中并没有匹配到该action,那就一定要返回一个旧的state,不然会造成undefined。
另外,在修改状态的时候,不要通过直接修改当前state,而是通过创建一个副本去修改,可以用ES6中的Object.assign
方法:
return Object.assign({},state,{ XXX:XXX })
或者使用ES7提案中的对象展开运算符(...):
switch (action.type) { case GET_NEXT_MONTH: return state.month >= 12 ? {...state,month: --state.month}; default: console.log("default calendarReducer state"); return state; }
在使用ES7的展开运算符的时候需要添加一个插件来支持,因为目前该语法还处于stage2阶段:
query: { presets: ['react','es2015'],plugins: ['transform-object-rest-spread'] }
store
在 Redux 项目中,Store 是单一的。维护着一个全局的 State,并且根据 Action 来进行事件分发处理 State。可以看出 Store 是一个把 Action 和 Reducer 结合起来的对象。
Redux 提供了 createStore()
方法来 生产 Store,如:
let store = createStore(calendarApp);
react-redux 提供一个<Provider>
组件把整个app包在里面,以 React 组件的形式来为 Provider 注入 store,从而使得其子组件能够在上下文中得到 store 对象,共享同一个store,如:
let rootElement = document.getElementById('main'); render( <Provider store={store}> <App /> </Provider>,rootElement );
_
组件的生命周期
componentWillMount
componentWillMount()
服务器端和客户端都只调用一次,在初始化渲染执行之前立刻调用。如果在这个方法内调用 setState
,render()
将会感知到更新后的 state
,将会执行仅一次,尽管 state 改变了。
componentDidMount
componentDidMount()
在初始化渲染执行之后立刻调用一次,仅客户端有效(服务器端不会调用)。在生命周期中的这个时间点,组件拥有一个 DOM
展现,可以通过 this.getDOMNode()
来获取相应 DOM
节点。
如果想和其它JavaScript
框架集成,使用setTimeout
或者setInterval
来设置定时器,或者发送 AJAX
请求,可以在该方法中执行这些操作。
componentWillReceiveProps
componentWillReceiveProps(object nextProps)
在组件接收到新的 props
的时候调用。在初始化渲染的时候,该方法不会调用。
用此函数可以作为 react
在 prop
传入之后, render()
渲染之前更新 state
的机会。老的 props
可以通过 this.props
获取到。在该函数中调用 this.setState()
将不会引起第二次渲染。
shouldComponentUpdate
boolean shouldComponentUpdate(object nextProps,object nextState)
在接收到新的 props
或者 state
,将要渲染之前调用。该方法在初始化渲染的时候不会调用,在使用 forceUpdate
方法的时候也不会。
如果确定新的 props
和 state
不会导致组件更新,则此处应该 返回 false
。
shouldComponentUpdate: function(nextProps,nextState) { return nextProps.id !== this.props.id; }
如果 shouldComponentUpdate
返回 false,则 render()
将不会执行,直到下一次 state
改变。(另外,componentWillUpdate
和 componentDidUpdate
也不会被调用。)
默认情况下,shouldComponentUpdate
总会返回 true,在 state 改变的时候避免细微的 bug
,但是如果总是小心地把 state
当做不可变的,在 render()
中只从 props
和 state
读取值,此时可以覆盖 shouldComponentUpdate
方法,实现新老 props
和 state
的比对逻辑。
如果性能是个瓶颈,尤其是有几十个甚至上百个组件的时候,使用 shouldComponentUpdate
可以提升应用的性能。
componentWillUpdate
componentWillUpdate(object nextProps,object nextState)
在接收到新的 props
或者 state
之前立刻调用。在初始化渲染的时候该方法不会被调用。
使用该方法做一些更新之前的准备工作。
componentDidUpdate
componentDidUpdate(object prevProps,object prevState)
在组件的更新已经同步到 DOM
中之后立刻被调用。该方法不会在初始化渲染的时候调用。
使用该方法可以在组件更新之后操作 DOM
元素。
componentWillUnmount
componentWillUnmount()
在组件从 DOM
中移除的时候立刻被调用。
在该方法中执行任何必要的清理,比如无效的定时器,或者清除在 componentDidMount
中创建的 DOM
元素。