实例化依次调用
- getDefaultProps
- 这个方法只会被调用一次,如果没有被父组件指定props属性的新建实例来说,这个方法返回的对象可以用于为实例设置默认的props值
- getInitalState
- 这个方法也只会被调用一次,初始化实例的state
- componentWillMount
- 该方法是完成首次渲染之前被调用。这也是render方法调用前可以修改组件state的最后一次机会
- render
- 在这里你会创建一个虚拟DOM,用来表示组件的输出。对于一个组件来说render是一个唯一一个必须的方法。并且还有一些特定的规定
- 只能通过this.props和this.state访问数据
- 可以返回null,false或者任何React组件
- 只能出现一个顶级组件:<div>意思是最终外面必须有一个大的标签包裹住</div>
- 在这里你会创建一个虚拟DOM,用来表示组件的输出。对于一个组件来说render是一个唯一一个必须的方法。并且还有一些特定的规定
- componentDidMount
- 在render方法成功调用并且真是DOM已经渲染之后,调用此方法你可以访问原始DOM结构
- 这个方法在服务器端渲染的话就没有了
存在期(组件已经渲染好之后,通过事件交互等...就可能触发下面这些周期钩子)
- componentWillReceiveProps
- 再次更新state的钩子
- shouldComponentUpdate
- 如果你确定某个组件或者它的子组件都不要渲染新的props或者state,则该方法返回false,返回false则是告诉React要跳过调用render方法;
- 也尽量不要去使用这个钩子
- componentWillUpdaterender
- 组件在接受到新的props或者state进行渲染前,调用该方法
- 你不能在该钩子上更新state
- componentDidUpdate
- 该钩子给了我们更新已经渲染好的DOM的机会
销毁&清理期
- componentWillUnmount
- 这个方法里面,我们可以做一些清理工作,例如关闭定时器等..
实例化 -> 存在期 -> 销毁&清理期
如果是初学React可以先简单的看一下这些钩子函数,心里有个概念即可,这东西只有等你实战之后,才会有一些更加深入的了解
来写一个平非常简单的react小组件:
var DropDown = React.createClass({ getInitialState:function(){ return { show:false } }, handleClick:function(){ var show_pop = this.state.show; show_pop = !show_pop; this.setState({ show:show_pop }) }, render:function(){ return ( <div className="drop"> <button onClick={this.handleClick}>{!this.state.show?"点击出现":"点击消失"}</button> <div className={this.state.show?"pop slow_show":"pop"}>出现了</div> </div> ) } }); ReactDOM.render( <DropDown />, document.querySelector('#app') )
这其实就是一个按钮,点击出现一个弹窗,在点击让弹窗消失的小例子,但是通过这个小例子足以看出,所有的写法都改变了,必须得去适应这种不操作DOM的写法,只操作state,数据变化了,样式自动更新。
React事件系统
React处理的事件本质上和原生JS事件一样;
1、所有事件命名与原生规范一致,会在相同的情景下触发
2、React中事件采用驼峰命名法:onClick,onMouseover
3、底层实现没有使用HTML的实现方式
总结:
原生事件具备哪些特性,React也具备哪些特性;
注意点:
return false 将不会阻止事件冒泡 ,取而代之是适合的场景下使用e.stopPropagation() && e.preventDefault()
我们通过3个实例来加深下理解吧:
- 数据双向绑定展示
- tab选项卡
- 屏幕中拖拽一个块
一:数据双向绑定展示(github:demo15)
var App = React.createClass({ getInitialState:function(){ return { data:'hello' } }, handleChange:function(e){ this.setState({ data:e.target.value }) }, render:function(){ return ( <div> <input type="text" onChange={this.handleChange} value={this.state.data} /> <span>{this.state.data}</span> </div> ) } })
这里有一点onChang需要补充下,
二.Tab选项卡(demo16)
var App = React.createClass({ getInitialState:function(){ return { currentIndex:0, tabNav:[ { title:'武汉', key:1 }, { title:'北京', key:2 }, { title:'上海', key:3 } ], tabCon:[ { content:'黄鹤楼', key:1 }, { content:'天安门', key:2 }, { content:'东方明珠', key:3 } ] } }, handleClick:function(index){ var currentIndex = index.target.getAttribute('data-uid'); this.setState({ currentIndex:currentIndex }) }, render:function(){ var navs = this.state.tabNav; var content = this.state.tabCon; var currentIndex = parseInt(this.state.currentIndex)+1; return ( <div className="wrapper"> <ul className="wrapper_nav" onClick={this.handleClick}> { navs.map(function(item,index){ return ( <li data-uid={index} key={item.key} className={currentIndex==item.key?"activeBack":""}>{item.title}</li> ) }) } </ul> <ul className="wrapper_content"> { content.map(function(item,index){ return ( <li key={item.key} className={currentIndex==item.key?"activeShow":""}>{item.content}</li> ) }) } </ul> </div> ) } }); ReactDOM.render( <App />, document.getElementById('app') )