1. 程式人生 > >React中的核心概念

React中的核心概念

                                                         React中的核心概念                                                          

* 1 虛擬DOM(Virtual DOM) * 2 Diff演算法(虛擬DOM的加速器,提升React效能的法寶)   虛擬DOM(Vitural DOM) React將DOM抽象為虛擬DOM,虛擬DOM其實就是用一個物件來描述DOM,通過對比前後兩個物件的差異,最終只把變化的部分重新渲染,提高渲染的效率 為什麼用虛擬dom,當dom反生更改時需要遍歷 而原生dom可遍歷屬性多大231個 且大部分與渲染無關 更新頁面代價太大 VituralDOM的處理方式
* 1 用 JavaScript 物件結構表示 DOM 樹的結構,然後用這個樹構建一個真正的 DOM 樹,插到文件當中
* 2 當狀態變更的時候,重新構造一棵新的物件樹。然後用新的樹和舊的樹進行比較,記錄兩棵樹差異 * 3 把2所記錄的差異應用到步驟1所構建的真正的DOM樹上,檢視就更新了
Diff演算法 當你使用React的時候,在某個時間點 render() 函式建立了一棵React元素樹, 在下一個state或者props更新的時候,render() 函式將建立一棵新的React元素樹, React將對比這兩棵樹的不同之處,計算出如何高效的更新UI(只更新變化的地方)   Diff演算法的說明 - 1
* 如果兩棵樹的根元素型別不同,React會銷燬舊樹,建立新樹
// 舊樹 <div>   <Counter /></div> // 新樹 <span>   <Counter /></span> 執行過程:destory Counter -> insert Counter
Diff演算法的說明 - 2 * 對於型別相同的React DOM 元素,React會對比兩者的屬性是否相同,只更新不同的屬性 * 當處理完這個DOM節點,React就會遞迴處理子節點。  
// 舊 <div className="before" title="stuff" /> // 新 <div className="after" title="stuff" /> 只更新:className 屬性   // 舊 <div style={{color: 'red', fontWeight: 'bold'}} /> // 新 <div style={{color: 'green', fontWeight: 'bold'}} /> 只更新:color屬性
Diff演算法的說明 - 3 * 1 當在子節點的後面新增一個節點,這時候兩棵樹的轉化工作執行的很好
// 舊 <ul>   <li>first</li>   <li>second</li> </ul> // 新 <ul>   <li>first</li>   <li>second</li>   <li>third</li> </ul> 執行過程: React會匹配新舊兩個<li>first</li>,匹配兩個<li>second</li>,然後新增 <li>third</li> tree
* 2 但是如果你在開始位置插入一個元素,那麼問題就來了:
// 舊 <ul>   <li>Duke</li>   <li>Villanova</li> </ul> // 新 <ul>   <li>Connecticut</li>   <li>Duke</li>   <li>Villanova</li> </ul> 在沒有key屬性時執行過程: React將改變每一個子刪除重新建立,而非保持 <li>Duke</li> 和 <li>Villanova</li> 不變
key 屬性 為了解決以上問題,React提供了一個 key 屬性。當子節點帶有key屬性,React會通過key來匹配原始樹和後來的樹。
// 舊 <ul>   <li key="2015">Duke</li>   <li key="2016">Villanova</li> </ul> // 新 <ul>   <li key="2014">Connecticut</li>   <li key="2015">Duke</li>   <li key="2016">Villanova</li> </ul> 執行過程: 現在 React 知道帶有key '2014' 的元素是新的,對於 '2015' 和 '2016' 僅僅移動位置即可
* 說明:key屬性在React內部使用,但不會傳遞給你的元件 * 推薦:在遍歷資料時,推薦在元件中使用 key 屬性:<li key={item.id}>{item.name}</li> * 注意:key只需要保持與他的兄弟節點唯一即可,不需要全域性唯一 * 注意:儘可能的減少陣列index作為key,陣列中插入元素的等操作時,會使得效率底下

                                                                        React的基本使用 * 安裝:npm i -S react react-dom * react:react 是React庫的入口點 * react-dom:提供了針對DOM的方法,比如:把建立的虛擬DOM,渲染到頁面上
// 1. 匯入 react import React from 'react' import ReactDOM from 'react-dom'   // 2. 建立 虛擬DOM // 引數1:元素名稱  引數2:元素屬性物件(null表示無)  引數3:當前元素的子元素string||createElement() 的返回值 const divVD = React.createElement('div', {   title: 'hello react' }, 'Hello React!!!')   // 3. 渲染 // 引數1:虛擬dom物件  引數2:dom物件表示渲染到哪個元素內 引數3:回撥函式 ReactDOM.render(divVD, document.getElementById('app'))
createElement()的問題 * 說明:createElement()方式,程式碼編寫不友好,太複雜
var dv = React.createElement(   "div",   { className: "shopping-list" },   React.createElement(     "h1",     null,     "Shopping List for "   ),   React.createElement(     "ul",     null,     React.createElement(       "li",       null,       "Instagram"     ),     React.createElement(       "li",       null,       "WhatsApp"     )   ) ) // 渲染 ReactDOM.render(dv, document.getElementById('app'))
JSX 的基本使用 * 注意:JSX語法,最終會被編譯為 createElement() 方法 * 推薦:使用 JSX 的方式建立元件 * JSX - JavaScript XML * 安裝:npm i -D babel-preset-react (依賴與:babel-core/babel-loader) 注意:JSX的語法需要通過 babel-preset-react 編譯後,才能被解析執行
/* 1 在 .babelrc 開啟babel對 JSX 的轉換 */ {   "presets": [     "env", "react"   ] }   /* 2 webpack.config.js */ module: [   rules: [     { test: /\.js$/, use: 'babel-loader', exclude: /node_modules/ },   ] ]   /* 3 在 js 檔案中 使用 JSX */ const dv = (   <div title="標題" className="cls container">Hello JSX!</div> )   /* 4 渲染 JSX 到頁面中 */ ReactDOM.render(dv, document.getElementById('app'))
JSX的注意點 * 注意 1: 如果在 JSX 中給元素新增類, 需要使用 className 代替 class * 類似:label 的 for屬性,使用htmlFor代替 * 注意 2:在 JSX 中可以直接使用 JS程式碼,直接在 JSX 中通過 {} 中間寫 JS程式碼即可 * 注意 3:在 JSX 中只能使用表示式,但是不能出現 語句!!! * 注意 4:在 JSX 中註釋語法:{/* 中間是註釋的內容 */} React元件 React 元件可以讓你把UI分割為獨立、可複用的片段,並將每一片段視為相互獨立的部分。 * 元件是由一個個的HTML元素組成的 * 概念上來講, 元件就像JS中的函式。它們接受使用者輸入(props),並且返回一個React物件,用來描述展示在頁面中的內容 React建立元件的兩種方式 * 1 通過 JS函式 建立(無狀態元件) * 2 通過 class 建立(有狀態元件) 函式式元件 和 class 元件的使用場景說明: 1 如果一個元件僅僅是為了展示資料,那麼此時就可以使用 函式元件 2 如果一個元件中有一定業務邏輯,需要操作資料,那麼就需要使用 class 建立元件,因為,此時需要使用 state JavaScript函式建立 * 注意:1 函式名稱必須為大寫字母開頭,React通過這個特點來判斷是不是一個元件 * 注意:2 函式必須有返回值,返回值可以是:JSX物件或null * 注意:3 返回的JSX,必須有一個根元素 * 注意:4 元件的返回值使用()包裹,避免換行問題
function Welcome(props) {   return (     // 此處註釋的寫法     <div className="shopping-list">       {/* 此處 註釋的寫法 必須要{}包裹 */}       <h1>Shopping List for {props.name}</h1>       <ul>         <li>Instagram</li>         <li>WhatsApp</li>       </ul>     </div>   ) }   ReactDOM.render(   <Welcome name="jack" />,   document.getElementById('app') )
class建立 在es6中class僅僅是一個語法糖,不是真正的類,本質上還是建構函式+原型 實現繼承
// ES6中class關鍵字的簡單使用   // - **ES6中的所有的程式碼都是執行在嚴格模式中的** // - 1 它是用來定義類的,是ES6中實現面向物件程式設計的新方式 // - 2 使用`static`關鍵字定義靜態屬性 // - 3 使用`constructor`建構函式,建立例項屬性 // - [參考](http://es6.ruanyifeng.com/#docs/class)   // 語法: class Person {   // 例項的建構函式 constructor   constructor(age){     // 例項屬性     this.age = age   }   // 在class中定義方法 此處為例項方法 通過例項打點呼叫   sayHello () {     console.log('大家好,我今年' + this.age + '了');   }     // 靜態方法 通過建構函式打點呼叫 Person.doudou()   static doudou () {     console.log('我是小明,我新get了一個技能,會暖床');   } } // 新增靜態屬性 Person.staticName = '靜態屬性' // 例項化物件 const p = new Person(19) // 實現繼承的方式 class American extends Person {   constructor() {     // 必須呼叫super(), super表示父類的建構函式     super()     this.skin = 'white'     this.eyeColor = 'white'   } }   // 建立react物件 // 注意:基於 `ES6` 中的class,需要配合 `babel` 將程式碼轉化為瀏覽器識別的ES5語法 // 安裝:`npm i -D babel-preset-env` //  react物件繼承字React.Component class ShoppingList extends React.Component {   constructor(props) {     super(props)   }   // class建立的元件中 必須有rander方法 且顯示return一個react物件或者null   render() {     return (       <div className="shopping-list">         <h1>Shopping List for {this.props.name}</h1>         <ul>           <li>Instagram</li>           <li>WhatsApp</li>         </ul>       </div>     )   } }