状态、属性、组件API、组件的生命周期
当react的状态改变时,自动执行this.render()方法更新组件
ES6写React的时候,事件里不会自动绑定this,需要自己绑定,或者直接在constructor里写方法
constructor(props) { super(props); this.state = { liked: false }; this.handleClick = (e) => { this.setState({liked: !this.state.liked}); }; }
状态
import React from 'react'; class LikeButton extends React.Component { // es6用constructor代替getInitialState constructor(props) { super(props); this.state = { liked: false } } handleClick (e) { this.setState({liked: !this.state.liked}) } render () { let text = this.state.liked ? '喜欢': '不喜欢'; return ( <div> <p onClick={this.handleClick.bind(this)}> 你喜欢红茶吗?{text} </p> </div> ) } } export default LikeButton;
props
HelloMessage.jsx
import React from 'react'; class HelloMessage extends React.Component { render () { return ( <div> Hello,{this.props.name} </div> ) } } export default HelloMessage;
main.js
import React from 'react'; import ReactDOM from 'react-dom'; import HelloMessage from './component/HelloMessage'; const app = document.getElementById('app'); ReactDOM.render(<HelloMessage name="Runoob"/>,app);
props验证
可以保证应用组件被正确使用
React.PropTypes提供很多验证器(validator)来验证传入数据是否有效。当props传入无效数据时,JavaScript控制台会抛出错误。
import React from 'react'; class HelloMessage extends React.Component { render () { return ( <div> Hello,{this.props.name} </div> ) } } // getDefaultProps要写在外部 HelloMessage.defaultProps = { name: 'this is default name' }; HelloMessage.propTypes = { name: React.PropTypes.string.isrequired }; export default HelloMessage;
更多验证器
React.createClass({ propTypes: { // 可以声明 prop 为指定的 JS 基本数据类型,默认情况,这些数据是可选的 optionalArray: React.PropTypes.array,optionalBool: React.PropTypes.bool,optionalFunc: React.PropTypes.func,optionalNumber: React.PropTypes.number,optionalObject: React.PropTypes.object,optionalString: React.PropTypes.string,// 可以被渲染的对象 numbers,strings,elements 或 array optionalNode: React.PropTypes.node,// React 元素 optionalElement: React.PropTypes.element,// 用 JS 的 instanceof 操作符声明 prop 为类的实例。 optionalMessage: React.PropTypes.instanceOf(Message),// 用 enum 来限制 prop 只接受指定的值。 optionalEnum: React.PropTypes.oneOf(['News','Photos']),// 可以是多个对象类型中的一个 optionalUnion: React.PropTypes.oneOfType([ React.PropTypes.string,React.PropTypes.number,React.PropTypes.instanceOf(Message) ]),// 指定类型组成的数组 optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number),// 指定类型的属性构成的对象 optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number),// 特定 shape 参数的对象 optionalObjectWithShape: React.PropTypes.shape({ color: React.PropTypes.string,fontSize: React.PropTypes.number }),// 任意类型加上 `isrequired` 来使 prop 不可空。 requiredFunc: React.PropTypes.func.isrequired,// 不可空的任意类型 requiredAny: React.PropTypes.any.isrequired,// 自定义验证器。如果验证失败需要返回一个 Error 对象。不要直接使用 `console.warn` 或抛异常,因为这样 `oneOfType` 会失效。 customProp: function(props,propName,componentName) { if (!/matchme/.test(props[propName])) { return new Error('Validation Failed!'); } } },/* ... */ });
React组件API
setState 设置状态
replaceState 替换状态
setProps 设置属性
replaceProps 替换属性
forceUpdate 强制更新
findDOMNode 获取DOM节点,查找真实DOM
React.findDOMNode()只在mounted组件中调用,如果在组件的render()方法中调用React.findDOMNode()就会抛出异常。
React组件的生命周期
组件生命周期的三个状态
Mounting: 已插入真实DOM
Updating: 正在被重新渲染
Unmounting: 已移除真实DOM
生命周期方法
componentWillMount 在渲染前调用,在客户端也在服务端
componentDidMount 在第一次渲染后调用,只在客户端。
之后组件已经生成了对应的DOM结构,可以通过this.getDOMNode()来进行访问。
如果你想和其他JavaScript框架一起使用,可以在这个方法中调用setTimeout,setInterval或者发送AJAX请求等操作(防止异部操作阻塞UI)。
componentWillReceiveProps 在初始化render时不会被调用,当组件接收到一个新的prop时被调用
shouldComponentUpdate 返回一个布尔值。当确认不需要更新组件时使用。在组件接收到新的state或新的props时被调用。在初始化时或使用forceUpdate时不被调用
componentWillUpdate 初始化不会调用。组件接收到新的state或者props但还没有render时被调用
componentDidUpdate 初始化不会调用。组件完成更新后立即调用。
componentWillUnmount 组件从DOM中移除的时候立刻被调用。
用state判断是否已经插入真实DOM
componentWillMount() { this.mounted = false; } componentDidMount() { this.mounted = true; }
需求:写一个实例,在组件加载以后,通过componentDidMount设置一个定时器,改变组件的透明度并重新渲染
HelloMessage.jsx
import React from 'react'; class HelloMessage extends React.Component { constructor (props) { super(props); this.state = { opacity: 1.0 }; } componentDidMount () { this.timer = setInterval(() => { let opacity = this.state.opacity; opacity -= 0.05; if(opacity <= 0.1) { opacity = 1.0; } this.setState({ opacity: opacity }); },100); } render () { let myStyle = { fontFamily: 'microsoft yahei',width: '100%',height: '100px',background: 'red',opacity: this.state.opacity }; return ( <div style={myStyle}> Hello,{this.props.name} <p>{this.state.opacity}</p> </div> ) } } // getDefaultProps要写在外部 HelloMessage.defaultProps = { name: 'this is default name' }; HelloMessage.propTypes = { name: React.PropTypes.string.isrequired }; export default HelloMessage;
另一个实例,体现react的生命周期
import React from 'react'; class Content extends React.Component { componentWillMount () { console.log('组件将被插入到真实DOM'); } componentDidMount () { console.log('已经插入真实DOM'); } componentWillReceiveProps (newProps) { console.log('组件将要接收属性,新属性是:'); console.log(newProps); } shouldComponentUpdate (newProps,newState) { return true; } componentWillUpdate (nextProps,nextState) { console.log('组件将要更新,下一个属性:' + nextProps + ',下一个状态:' + nextState); console.log(nextProps); } componentDidUpdate (prevProps,prevState) { console.log('组件已更新,上一个属性:' + prevProps + ',上一个状态:' + prevState); console.log(prevProps); } componentWillUnmount () { console.log('已经移除真实DOM'); } render () { return ( <div> 次数:{this.props.myNum} </div> ) } } class Increment extends React.Component { constructor (props) { super(props); this.state = { data: 0 }; } setNewNumber () { this.setState({ data: this.state.data + 1 }); } render () { return ( <div> <button onClick={this.setNewNumber.bind(this)}>Increment</button> <Content myNum={this.state.data}/> </div> ) } } export default Increment;
未完待续 ... ...