react入门资源
一 学习方式学一门新技术,我习惯的学习方式是:
二 学习资源
利用react + react-router + react-redux + antd + yarn 完成了一个 todo-demo,地址:https://github.com/ranyingxia... 三 学习笔记react 生命周期
装载过程(Mount),组件第一次在DOM树渲染的过程。 装载过程,依次会调用以下函数: constructor():ES6类的构造函数(为了初始化state或绑定this) 更新过程, 当组件的props或者state改变时就会触发组件的更新过程,依次会调用如下函数: componentWillReceiveProps(nextProps):当父组件的render()方法执行后就会触发该方法。初始化时不调用。 卸载过程: componentWillUnmount():将组件从DOM树移出,防止内存溢出 React中的受控组件和非受控组件1.受控组件:受控组件 非受控组件的输入框类似于传统的表单输入,可以使用一个ref来获取它的值。例如,一个按钮的onClick操作: class Form extends Component { handleSubmitClick = () => { const name = this._name.value; } render() { return ( <div> <input type="text" ref={input => this._name = input} /> <button onClick={this.handleSubmitClick}>Sign up</button> </div> ); } } 2.非受控组件:非受控组件 class From extends Component { constructor(){ super(); this.state = { name: '' } } handleNameChange = (event) => { this.setState({name: event.target.value }) } render(){ return ( <div> <input type="text" value={this.state.name} onChange={this.handleNameChange} /> </div> ); } } 每次键入了一个新的字符,就会调用handleNameChange。它会获取input最新的值并在state中设置 开始设置值为空字符串—'' 这种“推入式”的流程改变了表单控件,因此表单控件总是能够一直获取输入框当前的值,而不用明确知道对象是谁。这意味着你的数据state以及UIinput总是异步的。状态将值赋給输入框,输入框通知表单改变当前的值 React创建组件的三种方式以及区别目前创建组件的方式大概有3中: 函数式定义的无状态组件 这三种创建方式如何选择?结论是: function HelloComponent(props,/* context */) { return <div>Hello {props.name}</div> } ReactDOM.render(<HelloComponent name="Sebastian" />,mountNode) 无状态函数式组件形式上表现为一个只带有一个render方法的组件类,通过函数形式或者ES6 arrow function的形式在创建,它是为了创建纯展示组件,这种组件只负责根据传入的props来展示,不涉及到要state状态的操作。 无状态的组件优点有:
因为组件被精简成一个render方法的函数来实现的,由于是无状态组件,所以无状态组件就不会在有组件实例化的过程,无实例化过程也就不需要分配多余的内存,从而性能得到一定的提升。
无状态组件由于没有实例化过程,所以无法访问组件this中的对象,例如:this.ref、this.state等均不能访问。若想访问就不能使用这种形式来创建组件
因为无状态组件是不需要组件生命周期管理和状态管理,所以底层实现这种形式的组件时是不会实现组件的生命周期方法。所以无状态组件是不能参与组件的各个生命周期管理的。
var InputControlES5 = React.createClass({ propTypes: {//定义传入props中的属性各种类型 initialValue: React.PropTypes.string },defaultProps: { //组件默认的props对象 initialValue: '' },// 设置 initial state getInitialState: function() {//组件相关的状态对象 return { text: this.props.initialValue || 'placeholder' }; },handleChange: function(event) { this.setState({ //this represents react component instance text: event.target.value }); },render: function() { return ( <div> Type something: <input onChange={this.handleChange} value={this.state.text} /> </div> ); } }); InputControlES6.propTypes = { initialValue: React.PropTypes.string }; InputControlES6.defaultProps = { initialValue: '' };
React.createClass会自绑定函数方法(不像React.Component只绑定需要关心的函数)导致不必要的性能开销,增加代码过时的可能性。 class InputControlES6 extends React.Component { constructor(props) { super(props); // 设置 initial state this.state = { text: props.initialValue || 'placeholder' }; // ES6 类中函数必须手动绑定 this.handleChange = this.handleChange.bind(this); } handleChange(event) { this.setState({ text: event.target.value }); } render() { return ( <div> Type something: <input onChange={this.handleChange} value={this.state.text} /> </div> ); } } InputControlES6.propTypes = { initialValue: React.PropTypes.string }; InputControlES6.defaultProps = { initialValue: '' }; React.Component是以ES6的形式来创建react的组件的,是React目前极为推荐的创建有状态组件的方式,最终会取代React.createClass形式;相对于 React.createClass可以更好实现代码复用 React.createClass创建的组件,其每一个成员函数的this都有React自动绑定,任何时候使用,直接使用this.method即可,函数中的this会被正确设置。React.Component创建的组件,其成员函数不会自动绑定this,需要开发者手动绑定,否则this不能获取当前组件实例对象。 const Contacts = React.createClass({ handleClick() { console.log(this); // React Component instance },render() { return ( <div onClick={this.handleClick}></div> ); } }); class Contacts extends React.Component { constructor(props) { super(props); } handleClick() { console.log(this); // null } render() { return ( <div onClick={this.handleClick}></div> ); } //或者是: this.handleClick = this.handleClick.bind(this); //构造函数中绑定 <div onClick={this.handleClick.bind(this)}></div> //使用bind来绑定 <div onClick={()=>this.handleClick()}></div> //使用arrow function来绑定 组件属性类型propTypes及其默认props属性defaultProps配置不同。 React.createClass在创建组件时,有关组件props的属性类型及组件默认的属性会作为组件实例的属性来配置,其中defaultProps是使用getDefaultProps的方法来获取默认组件属性的。React.Component在创建组件时配置这两个对应信息时,他们是作为组件类的属性,不是组件实例的属性,也就是所谓的类的静态属性来配置的。 const TodoItem = React.createClass({ propTypes: { // as an object name: React.PropTypes.string },getDefaultProps(){ // return a object return { name: '' } } render(){ return <div></div> } }) class TodoItem extends React.Component { static propTypes = {//类的静态属性 name: React.PropTypes.string }; static defaultProps = {//类的静态属性 name: '' }; ... } 组件初始状态state的配置不同。 React.createClass创建的组件,其状态state是通过getInitialState方法来配置组件相关的状态。 const TodoItem = React.createClass({ // return an object getInitialState(){ return { isEditing: false } } render(){ return <div></div> } }) class TodoItem extends React.Component{ constructor(props){ super(props); this.state = { // define this.state in constructor isEditing: false } } render(){ return <div></div> } } this的理解与使用React可以使用React.createClass、ES6 classes、纯函数3种方式构建组件。使用React.createClass会自动绑定每个方法的this到当前组件,但使用ES6 classes或纯函数时,就要靠手动绑定this,因此绑定方法如下: 使用React.createClass会自动绑定每个方法的this到当前组件 // 使用React.createClass会自动绑定每个方法的this到当前组件 const Contacts = React.createClass({ handleClick() { console.log(this); // React Component instance },render() { return ( <div onClick={this.handleClick}></div> ); } }); 使用箭头函数 箭头函数则会捕获其所在上下文的this值,作为自己的this值,使用箭头函数就不用担心函数内的this不是指向组件内部了---推荐 class LoggingButton extends React.Component { handleClick() { console.log('this is:',this); } render() { // 这个语法确保 `this` 被绑定在 handleClick 中 return ( <button onClick={(e) => this.handleClick(e)}> Click me </button> ); } } 使用bind()绑定(不推荐使用,参照下方展开代码) Function.prototype.bind(thisArg [,arg1 [,arg2,…]]) 是ES5新增的函数扩展方法,bind()返回一个新的函数对象,该函数的this被绑定到thisArg上,并向事件处理器中传入参数 class LoggingButton extends React.Component { handleClick(param) { console.log('this is:',this); } render() { return ( <button onClick={ this.handleClick.bind(this,'params') } Click me </button> ); } } // 考虑下面的代码: class MyCom extends React.Component{ submit(){ // do something } render(){ return <div> <Form onSubmit={this.submit.bind(this)} values={{name: '',id: ''}}></Form> <Input onChange={v => {this.setState({value: v})}} /> </div> } } input 组件每次onChange 都会触发父组件render,而每次render的时候都会造成子组件Form重新渲染,当子组件渲染比较复杂时,带来的卡顿将会非常明显!因为bind每次都会产生一个新函数。 构造函数内绑定 在构造函数 constructor 内绑定this,好处是仅需要绑定一次,避免每次渲染时都要重新绑定,函数在别处复用时也无需再次绑定 import React,{Component} from 'react' class Test extends React.Component { constructor (props) { super(props) this.state = {message: 'Allo!'} this.handleClick = this.handleClick.bind(this) } handleClick (e) { console.log(this.state.message) } render () { return ( <div> <button onClick={ this.handleClick }>Say Hello</button> </div> ) } } react-router的实现原理首先需要了解 history.pushState 与 popstate 事件,不清楚的点击这里: https://developer.mozilla.org... react-router 的实现原理参见 :http://zhenhua-lee.github.io/... 从点击 Link 到 render 对应 component ,路由中发生了什么react的diff算法react怎么优化react高阶组件从时间旅行的乌托邦,看状态管理的设计误区文章:https://juejin.im/post/5a3707... 聊一聊我对 React Context 的理解以及应用文章:https://juejin.im/post/5a90e0... 相关参靠资源:http://blog.csdn.net/heyuan98... (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |