简介:react
1.组件内: 传递参数的时候要少传,且每次传递的尽可能是一份数据,不要每次这个数据都会被从新建立 2.组件间:shouldComponent、pureComponent、immutable
handleClick(event){ // 你的事件处理逻辑 } 1. onclick={::this.handlerClick} 不建议,es7中的写法,等同于3 onClick={this.handleClick.bind(this)} // 箭头函数中的上下文是所在全局的上下文,不决定于谁调用他 2. onclick={() => this.handlerClick()} onClick={this.handleClick} handleClick = () => { console.log(this); } // 因此咱们须要在class的construct中将函数的执行做用域设为当前组件 3. constructor(props, context) { super(props, context) this.handlerClick= this.handlerClick.bind(this) } onclick={this.handlerClick}
Q: 上面那种方式最好?redux
构造函数bind > 箭头函数 > 直接bind 由于构造函数只会在app建立,执行一次,箭头函数和bind每次都返回一个新的函数,引发渲染
Q: React事件机制,为何拿不到this数组
class Foo { constructor(name){ this.name = name } display(){ console.log(this.name); } } var foo = new Foo('Saurabh'); foo.display(); // Saurabh //下面的赋值操做模拟了上下文的丢失。 //与实际在 React Component 中将处理程序做为 callback 参数传递类似。 // 类声明和类表达式的主体以 严格模式 执行,主要包括构造函数、静态方法和原型方法。Getter 和 setter 函数也在严格模式下执行。 var display = foo.display; display(); // TypeError: this is undefined
Q:为何在使用bind能解决数据结构
// 解决:构造函数中bind,对应第三种方法 class Foo { constructor(name){ this.name = name this.display = this.display.bind(this); } display(){ console.log(this.name); } var foo = new Foo('Saurabh'); foo.display(); // Saurabh var display = foo.display; display(); // Saurabh // 咱们也能够在其余地方bind,对应第一种方法 // 但因为构造函数是全部初始化发生的地方,所以它是编写绑定事件语句最佳的位置 class Foo { constructor(name){ this.name = name; } display(){ console.log(this.name); } } var foo = new Foo('Saurabh'); foo.display = foo.display.bind(foo); foo.display(); // Saurabh var display = foo.display; display(); // Saurabh
Q:箭头函数为何能解决app
1.箭头函数机制less
箭头函数没有 this,因此须要经过查找做用域链来肯定 this 的值。 这就意味着若是箭头函数被非箭头函数包含,this 绑定的就是最近一层非箭头函数的 this this 是有词法约束力的。这意味它可使用封闭的函数上下文或者全局上下文做为 this 的值
2.分析为何能解决 - 箭头函数两种解决方式dom
公共类字段语法: 箭头函数被包含在 Foo 类中或者构造函数中,因此它的上下文就是组件实例
class Foo extends React.Component{ handleClick = () => { console.log(this); } render(){ return ( <button type="button" onClick={this.handleClick}> Click Me </button> ); } } ReactDOM.render( <Foo />, document.getElementById("app") );
回调中的箭头函数:箭头函数被包含在 render() 方法中,该方法由 React 在组件实例的上下文中调用
class Foo extends React.Component{ handleClick(event){ console.log(this); } render(){ return ( <button type="button" onClick={(e) => this.handleClick(e)}> Click Me </button> ); } } ReactDOM.render( <Foo />, document.getElementById("app") );
Q: bind为什么不能用 call和apply这种替代函数
由于call和apply会当即执行,这是bind与call,apply的区别
2.传递参数注意性能
若是直接写一个对象在item处,则每次会生成新的
so, 传递参数的时候要少传,且每次传递的尽可能是一份数据,不要每次这个数据都会被从新建立优化
const item = { firstName: 'Liu' } <Demo style={{ color: 'red' }} name={item}></Demo> <Demo {...this.state}></Demo>
1.shouldComponentUpdate
// 浅比较先后两次的props的变化 // 通常redux的state层次深,数据结构复杂,深层比较太消耗性能,得不偿失 class Demo extends React.component { shouldComponentUpdate(nextProps, nextState) { if (compareObj(nextProps, this.props)) { return false } return true } render() { return <h2>{this.props.title}</h2> } }
浅比较
function compareObj(obj1, obj2) { if (obj1 == obj2) { return true } if (Object.keys(obj1).length !== Object.keys(obj2).length) { return false } for(let k in obj1) { if (obj1[k] !== obj2[k]) { return false } } return true }
补充: 深比较的实现 - 浅比较的递归
function compareObj(obj1, obj2) { if (obj1 == obj2) { return true } if (Object.keys(obj1).length !== Object.keys(obj2).length) { return false } for (let k in obj1) { if (typeof obj1[k] == 'object') { return compareObj(obj1[k], obj2[k]) } else if (obj1[k] !== obj2[k]) { return false } } return true }
React16 简易的写法 - 把nextProps每一个都遍历比较了一遍
class Demo extends React.PureComponent { render() { return <h2>{ this.props.title }</h2> } }
2. immutablejs
解决什么问题:
immutablejs的出现就是为了解决可变数据结构深层比较的性能问题 让咱们更优更高效的比对数据,减小渲染
优点:
节省内存,下降可变的风险,能够用等号判断是否相等 比较是直接拿地址得hash作对比,因此比较相等的复杂度特别低
使用:
将react, redux的数据所有改成使用immutable的数据类型来操做
// 此时,定制shouldComponentUpdate就会特别简单高效 class Demo extends React.component { shouldComponentUpdate(nextProps, nextState) { return is(nextProps, this.props) } render() { return <h2>{this.props.title}</h2> } }
推荐immutable轻量级包:seamless-immutable
建议:循环时,不要使用index来做为key,最好拿数值或者数组与其余的组合来确保key的惟一性
<ul> {this.state.users.map((v,index) => <li key={index}>{v}</li>)} </ul>
问题:
若是我再数组前面插入数组,则整个数组的index都会发生变化,v-dom就没有存在的意义 key用来标识同级的dom元素,其做用和重要性,详情请见另外一篇blog - 深刻diff和虚拟dom key变化了,react比对时,就会所有删除插入,不会进行复用移动