簡介: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比對時,就會所有刪除插入,不會進行復用移動