React入门看这篇就够了
2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>
摘要: 很多值得了解的細(xì)節(jié)。
- 原文:React入門看這篇就夠了
- 作者:Random
Fundebug經(jīng)授權(quán)轉(zhuǎn)載,版權(quán)歸原作者所有。
React 背景介紹
- React 入門實(shí)例教程
React 起源于 Facebook 的內(nèi)部項(xiàng)目,因?yàn)樵摴緦?duì)市場(chǎng)上所有 JavaScript MVC 框架,都不滿意,就決定自己寫一套,用來(lái)架設(shè) Instagram 的網(wǎng)站。做出來(lái)以后,發(fā)現(xiàn)這套東西很好用,就在2013年5月開源了。
什么是React
- A JAVASCRIPT LIBRARY FOR BUILDING USER INTERFACES
- 用來(lái)構(gòu)建UI的 JavaScript庫(kù)
- React 不是一個(gè) MVC 框架,僅僅是視圖(V)層的庫(kù)
- React 官網(wǎng)
- React 中文文檔
特點(diǎn)
- 使用 JSX語(yǔ)法 創(chuàng)建組件,實(shí)現(xiàn)組件化開發(fā),為函數(shù)式的 UI 編程方式打開了大門
- 性能高的讓人稱贊:通過(guò) diff算法 和 虛擬DOM 實(shí)現(xiàn)視圖的高效更新
- HTML僅僅是個(gè)開始
為什么要用React
- 使用組件化開發(fā)方式,符合現(xiàn)代Web開發(fā)的趨勢(shì)
- 技術(shù)成熟,社區(qū)完善,配件齊全,適用于大型Web項(xiàng)目(生態(tài)系統(tǒng)健全)
- 由Facebook專門的團(tuán)隊(duì)維護(hù),技術(shù)支持可靠
- ReactNative - Learn once, write anywhere: Build mobile apps with React
- 使用方式簡(jiǎn)單,性能非常高,支持服務(wù)端渲染
- React非常火,從技術(shù)角度,可以滿足好奇心,提高技術(shù)水平;從職業(yè)角度,有利于求職和晉升,有利于參與潛力大的項(xiàng)目
React中的核心概念
- 虛擬DOM(Virtual DOM)
- Diff算法(虛擬DOM的加速器,提升React性能的法寶)
虛擬DOM(Vitural DOM)
React將DOM抽象為虛擬DOM,虛擬DOM其實(shí)就是用一個(gè)對(duì)象來(lái)描述DOM,通過(guò)對(duì)比前后兩個(gè)對(duì)象的差異,最終只把變化的部分重新渲染,提高渲染的效率
為什么用虛擬dom,當(dāng)dom反生更改時(shí)需要遍歷 而原生dom可遍歷屬性多大231個(gè) 且大部分與渲染無(wú)關(guān) 更新頁(yè)面代價(jià)太大
- 如何實(shí)現(xiàn)一個(gè) Virtual DOM 算法
- 理解 Virtual DOM
VituralDOM的處理方式
Diff算法
- Reconciliation diff
- diff算法 - 中文文檔
- 不可思議的 react diff
- React diff 算法
當(dāng)你使用React的時(shí)候,在某個(gè)時(shí)間點(diǎn) render() 函數(shù)創(chuàng)建了一棵React元素樹, 在下一個(gè)state或者props更新的時(shí)候,render() 函數(shù)將創(chuàng)建一棵新的React元素樹, React將對(duì)比這兩棵樹的不同之處,計(jì)算出如何高效的更新UI(只更新變化的地方)
有一些解決將一棵樹轉(zhuǎn)換為另一棵樹的最小操作數(shù)算法問(wèn)題的通用方案。然而,樹中元素個(gè)數(shù)為n,最先進(jìn)的算法 的時(shí)間復(fù)雜度為O(n3) 。
如果直接使用這個(gè)算法,在React中展示1000個(gè)元素則需要進(jìn)行10億次的比較。這操作太過(guò)昂貴,相反,React基于兩點(diǎn)假設(shè),實(shí)現(xiàn)了一個(gè)O(n)算法,提升性能:
React中有兩種假定:
- 兩個(gè)不同類型的元素會(huì)產(chǎn)生不同的樹(根元素不同結(jié)構(gòu)樹一定不同)
- 開發(fā)者可以通過(guò)key屬性指定不同樹中沒有發(fā)生改變的子元素
Diff算法的說(shuō)明 - 1
- 如果兩棵樹的根元素類型不同,React會(huì)銷毀舊樹,創(chuàng)建新樹
Diff算法的說(shuō)明 - 2
- 對(duì)于類型相同的React DOM 元素,React會(huì)對(duì)比兩者的屬性是否相同,只更新不同的屬性
- 當(dāng)處理完這個(gè)DOM節(jié)點(diǎn),React就會(huì)遞歸處理子節(jié)點(diǎn)。
Diff算法的說(shuō)明 - 3
- 1 當(dāng)在子節(jié)點(diǎn)的后面添加一個(gè)節(jié)點(diǎn),這時(shí)候兩棵樹的轉(zhuǎn)化工作執(zhí)行的很好
- 2 但是如果你在開始位置插入一個(gè)元素,那么問(wèn)題就來(lái)了:
key 屬性
為了解決以上問(wèn)題,React提供了一個(gè) key 屬性。當(dāng)子節(jié)點(diǎn)帶有key屬性,React會(huì)通過(guò)key來(lái)匹配原始樹和后來(lái)的樹。
// 舊 <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> 執(zhí)行過(guò)程: 現(xiàn)在 React 知道帶有key '2014' 的元素是新的,對(duì)于 '2015' 和 '2016' 僅僅移動(dòng)位置即可- 說(shuō)明:key屬性在React內(nèi)部使用,但不會(huì)傳遞給你的組件
- 推薦:在遍歷數(shù)據(jù)時(shí),推薦在組件中使用 key 屬性:<li key={item.id}>{item.name}</li>
- 注意:key只需要保持與他的兄弟節(jié)點(diǎn)唯一即可,不需要全局唯一
- 注意:盡可能的減少數(shù)組index作為key,數(shù)組中插入元素的等操作時(shí),會(huì)使得效率底下
React的基本使用
- 安裝:npm i -S react react-dom
- react:react 是React庫(kù)的入口點(diǎn)
- react-dom:提供了針對(duì)DOM的方法,比如:把創(chuàng)建的虛擬DOM,渲染到頁(yè)面上
createElement()的問(wèn)題
- 說(shuō)明:createElement()方式,代碼編寫不友好,太復(fù)雜
JSX 的基本使用
- 注意:JSX語(yǔ)法,最終會(huì)被編譯為 createElement() 方法
- 推薦:使用 JSX 的方式創(chuàng)建組件
- JSX - JavaScript XML
- 安裝:npm i -D babel-preset-react (依賴與:babel-core/babel-loader)
注意:JSX的語(yǔ)法需要通過(guò) babel-preset-react 編譯后,才能被解析執(zhí)行
/* 1 在 .babelrc 開啟babel對(duì) JSX 的轉(zhuǎn)換 */ {"presets": ["env", "react"] }/* 2 webpack.config.js */ module: [rules: [{ test: /\.js$/, use: 'babel-loader', exclude: /node_modules/ },] ]/* 3 在 js 文件中 使用 JSX */ const dv = (<div title="標(biāo)題" className="cls container">Hello JSX!</div> )/* 4 渲染 JSX 到頁(yè)面中 */ ReactDOM.render(dv, document.getElementById('app'))JSX的注意點(diǎn)
- 如果在 JSX 中給元素添加類, 需要使用 className 代替 class
- 類似:label 的 for屬性,使用htmlFor代替
- 在 JSX 中可以直接使用 JS代碼,直接在 JSX 中通過(guò) {} 中間寫 JS代碼即可
- 在 JSX 中只能使用表達(dá)式,但是不能出現(xiàn) 語(yǔ)句!!!
- 在 JSX 中注釋語(yǔ)法:{/* 中間是注釋的內(nèi)容 */}
React組件
React 組件可以讓你把UI分割為獨(dú)立、可復(fù)用的片段,并將每一片段視為相互獨(dú)立的部分。
- 組件是由一個(gè)個(gè)的HTML元素組成的
- 概念上來(lái)講, 組件就像JS中的函數(shù)。它們接受用戶輸入(props),并且返回一個(gè)React對(duì)象,用來(lái)描述展示在頁(yè)面中的內(nèi)容
React創(chuàng)建組件的兩種方式
- 通過(guò) JS函數(shù) 創(chuàng)建(無(wú)狀態(tài)組件)
- 通過(guò) class 創(chuàng)建(有狀態(tài)組件)
函數(shù)式組件 和 class 組件的使用場(chǎng)景說(shuō)明:
- 如果一個(gè)組件僅僅是為了展示數(shù)據(jù),那么此時(shí)就可以使用 函數(shù)組件
- 如果一個(gè)組件中有一定業(yè)務(wù)邏輯,需要操作數(shù)據(jù),那么就需要使用 class 創(chuàng)建組件,因?yàn)?#xff0c;此時(shí)需要使用 state
JavaScript函數(shù)創(chuàng)建組件
- 注意:1 函數(shù)名稱必須為大寫字母開頭,React通過(guò)這個(gè)特點(diǎn)來(lái)判斷是不是一個(gè)組件
- 注意:2 函數(shù)必須有返回值,返回值可以是:JSX對(duì)象或null
- 注意:3 返回的JSX,必須有一個(gè)根元素
- 注意:4 組件的返回值使用()包裹,避免換行問(wèn)題
class創(chuàng)建組件
在es6中class僅僅是一個(gè)語(yǔ)法糖,不是真正的類,本質(zhì)上還是構(gòu)造函數(shù)+原型 實(shí)現(xiàn)繼承
// ES6中class關(guān)鍵字的簡(jiǎn)單使用// - **ES6中的所有的代碼都是運(yùn)行在嚴(yán)格模式中的** // - 1 它是用來(lái)定義類的,是ES6中實(shí)現(xiàn)面向?qū)ο缶幊痰男路绞?// - 2 使用`static`關(guān)鍵字定義靜態(tài)屬性 // - 3 使用`constructor`構(gòu)造函數(shù),創(chuàng)建實(shí)例屬性 // - [參考](http://es6.ruanyifeng.com/#docs/class)// 語(yǔ)法: class Person {// 實(shí)例的構(gòu)造函數(shù) constructorconstructor(age){// 實(shí)例屬性this.age = age}// 在class中定義方法 此處為實(shí)例方法 通過(guò)實(shí)例打點(diǎn)調(diào)用sayHello () {console.log('大家好,我今年' + this.age + '了');}// 靜態(tài)方法 通過(guò)構(gòu)造函數(shù)打點(diǎn)調(diào)用 Person.doudou()static doudou () {console.log('我是小明,我新get了一個(gè)技能,會(huì)暖床');} } // 添加靜態(tài)屬性 Person.staticName = '靜態(tài)屬性' // 實(shí)例化對(duì)象 const p = new Person(19)// 實(shí)現(xiàn)繼承的方式class American extends Person {constructor() {// 必須調(diào)用super(), super表示父類的構(gòu)造函數(shù)super()this.skin = 'white'this.eyeColor = 'white'} }// 創(chuàng)建react對(duì)象 // 注意:基于 `ES6` 中的class,需要配合 `babel` 將代碼轉(zhuǎn)化為瀏覽器識(shí)別的ES5語(yǔ)法 // 安裝:`npm i -D babel-preset-env`// react對(duì)象繼承字React.Component class ShoppingList extends React.Component {constructor(props) { super(props)}// class創(chuàng)建的組件中 必須有rander方法 且顯示return一個(gè)react對(duì)象或者nullrender() {return (<div className="shopping-list"><h1>Shopping List for {this.props.name}</h1><ul><li>Instagram</li><li>WhatsApp</li></ul></div>)} }推薦大家使用Fundebug,一款很好用的BUG監(jiān)控工具~
給組件傳遞數(shù)據(jù) - 父子組件傳遞數(shù)據(jù)
- 組件中有一個(gè) 只讀的對(duì)象 叫做 props,無(wú)法給props添加屬性
- 獲取方式:函數(shù)參數(shù) props
- 作用:將傳遞給組件的屬性轉(zhuǎn)化為 props 對(duì)象中的屬性
封裝組件到獨(dú)立的文件中
// 創(chuàng)建Hello2.js組件文件 // 1. 引入React模塊 // 由于 JSX 編譯后會(huì)調(diào)用 React.createElement 方法,所以在你的 JSX 代碼中必須首先拿到React。 import React from 'react'// 2. 使用function構(gòu)造函數(shù)創(chuàng)建組件 function Hello2(props){return (<div><div>這是Hello2組件</div><h1>這是大大的H1標(biāo)簽,我大,我驕傲!!!</h1><h6>這是小小的h6標(biāo)簽,我小,我傲嬌!!!</h6></div>) } // 3. 導(dǎo)出組件 export default Hello2// app.js中 使用組件: import Hello2 from './components/Hello2'props和state
props
- 作用:給組件傳遞數(shù)據(jù),一般用在父子組件之間
- 說(shuō)明:React把傳遞給組件的屬性轉(zhuǎn)化為一個(gè)對(duì)象并交給 props
- 特點(diǎn):props是只讀的,無(wú)法給props添加或修改屬性
- props.children:獲取組件的內(nèi)容,比如:
- <Hello>組件內(nèi)容</Hello> 中的 組件內(nèi)容
state
狀態(tài)即數(shù)據(jù)
- 作用:用來(lái)給組件提供組件內(nèi)部使用的數(shù)據(jù)
- 注意:只有通過(guò)class創(chuàng)建的組件才具有狀態(tài)
- 狀態(tài)是私有的,完全由組件來(lái)控制
- 不要在 state 中添加 render() 方法中不需要的數(shù)據(jù),會(huì)影響渲染性能!
- 可以將組件內(nèi)部使用但是不渲染在視圖中的內(nèi)容,直接添加給 this
- 不要在 render() 方法中調(diào)用 setState() 方法來(lái)修改state的值
- 但是可以通過(guò) this.state.name = 'rose' 方式設(shè)置state(不推薦!!!!)
JSX語(yǔ)法轉(zhuǎn)化過(guò)程
// 1、JSX const element = (<h1 className="greeting">Hello, world!</h1> )// 2、JSX -> createElement const element = React.createElement('h1',{className: 'greeting'},'Hello, world!' )// React elements: 使用對(duì)象的形式描述頁(yè)面結(jié)構(gòu) // Note: 這是簡(jiǎn)化后的對(duì)象結(jié)構(gòu) const element = {type: 'h1',props: {className: 'greeting',},children: ['Hello, world'] }評(píng)論列表案例
- 鞏固有狀態(tài)組件和無(wú)狀態(tài)組件的使用
- 兩個(gè)組件:<CommentList></CommentList> 和 <Comment></Comment>
style樣式
// 1. 直接寫行內(nèi)樣式: <li style={{border:'1px solid red', fontSize:'12px'}}></li>// 2. 抽離為對(duì)象形式 var styleH3 = {color:'blue'} var styleObj = {liStyle:{border:'1px solid red', fontSize:'12px'},h3Style:{color:'green'} }<li style={styleObj.liStyle}><h3 style={styleObj.h3Style}>評(píng)論內(nèi)容:{props.content}</h3> </li>// 3. 使用樣式表定義樣式: import '../css/comment.css' <p className="pUser">評(píng)論人:{props.user}</p>組件的生命周期
- 簡(jiǎn)單說(shuō):一個(gè)組件從開始到最后消亡所經(jīng)歷的各種狀態(tài),就是一個(gè)組件的生命周期
組件生命周期函數(shù)的定義:從組件被創(chuàng)建,到組件掛載到頁(yè)面上運(yùn)行,再到頁(yè)面關(guān)閉組件被卸載,這三個(gè)階段總是伴隨著組件各種各樣的事件,那么這些事件,統(tǒng)稱為組件的生命周期函數(shù)!
- 通過(guò)這個(gè)函數(shù),能夠讓開發(fā)人員的代碼,參與到組件的生命周期中。也就是說(shuō),通過(guò)鉤子函數(shù),就可以控制組件的行為
- react component
- React Native 中組件的生命周期
- React 生命周期的管理藝術(shù)
- 智能組件和木偶組件
組件生命周期函數(shù)總覽
- 組件的生命周期包含三個(gè)階段:創(chuàng)建階段(Mounting)、運(yùn)行和交互階段(Updating)、卸載階段(Unmounting)
- Mounting:
constructor() componentWillMount() render() componentDidMount()
- Updating
componentWillReceiveProps() shouldComponentUpdate() componentWillUpdate() render() componentDidUpdate()
- Unmounting
componentWillUnmount()
組件生命周期 - 創(chuàng)建階段(Mounting)
- 特點(diǎn):該階段的函數(shù)只執(zhí)行一次
constructor()
- 作用:1 獲取props 2 初始化state
- 說(shuō)明:通過(guò) constructor() 的參數(shù)props獲取
- 設(shè)置state和props
componentWillMount()
- 說(shuō)明:組件被掛載到頁(yè)面之前調(diào)用,其在render()之前被調(diào)用,因此在這方法里同步地設(shè)置狀態(tài)將不會(huì)觸發(fā)重渲染
- 注意:無(wú)法獲取頁(yè)面中的DOM對(duì)象
- 注意:可以調(diào)用 setState() 方法來(lái)改變狀態(tài)值
- 用途:發(fā)送ajax請(qǐng)求獲取數(shù)據(jù)
render()
- 作用:渲染組件到頁(yè)面中,無(wú)法獲取頁(yè)面中的DOM對(duì)象
- 注意:不要在render方法中調(diào)用 setState() 方法,否則會(huì)遞歸渲染
- 原因說(shuō)明:狀態(tài)改變會(huì)重新調(diào)用render(),render()又重新改變狀態(tài)
componentDidMount()
- 組件已經(jīng)掛載到頁(yè)面中
- 可以進(jìn)行DOM操作,比如:獲取到組件內(nèi)部的DOM對(duì)象
- 可以發(fā)送請(qǐng)求獲取數(shù)據(jù)
- 可以通過(guò) setState() 修改狀態(tài)的值
- 注意:在這里修改狀態(tài)會(huì)重新渲染
組件生命周期 - 運(yùn)行階段(Updating)
- 特點(diǎn):該階段的函數(shù)執(zhí)行多次
- 說(shuō)明:每當(dāng)組件的props或者state改變的時(shí)候,都會(huì)觸發(fā)運(yùn)行階段的函數(shù)
componentWillReceiveProps()
- 說(shuō)明:組件接受到新的props前觸發(fā)這個(gè)方法
- 參數(shù):當(dāng)前組件props值
- 可以通過(guò) this.props 獲取到上一次的值
- 使用:若你需要響應(yīng)屬性的改變,可以通過(guò)對(duì)比this.props和nextProps并在該方法中使用this.setState()處理狀態(tài)改變
- 注意:修改state不會(huì)觸發(fā)該方法
shouldComponentUpdate()
- 作用:根據(jù)這個(gè)方法的返回值決定是否重新渲染組件,返回true重新渲染,否則不渲染
- 優(yōu)勢(shì):通過(guò)某個(gè)條件渲染組件,降低組件渲染頻率,提升組件性能
- 說(shuō)明:如果返回值為false,那么,后續(xù)render()方法不會(huì)被調(diào)用
- 注意:這個(gè)方法必須返回布爾值!!!
- 場(chǎng)景:根據(jù)隨機(jī)數(shù)決定是否渲染組件
componentWillUpdate()
- 作用:組件將要更新
- 參數(shù):最新的屬性和狀態(tài)對(duì)象
- 注意:不能修改狀態(tài) 否則會(huì)循環(huán)渲染
render() 渲染
- 作用:重新渲染組件,與Mounting階段的render是同一個(gè)函數(shù)
- 注意:這個(gè)函數(shù)能夠執(zhí)行多次,只要組件的屬性或狀態(tài)改變了,這個(gè)方法就會(huì)重新執(zhí)行
componentDidUpdate()
- 作用:組件已經(jīng)被更新
- 參數(shù):舊的屬性和狀態(tài)對(duì)象
組件生命周期 - 卸載階段(Unmounting)
- 組件銷毀階段:組件卸載期間,函數(shù)比較單一,只有一個(gè)函數(shù),這個(gè)函數(shù)也有一個(gè)顯著的特點(diǎn):組件一輩子只能執(zhí)行依次!
- 使用說(shuō)明:只要組件不再被渲染到頁(yè)面中,那么這個(gè)方法就會(huì)被調(diào)用( 渲染到頁(yè)面中 -> 不再渲染到頁(yè)面中 )
componentWillUnmount()
- 作用:在卸載組件的時(shí)候,執(zhí)行清理工作,比如
- 清除定時(shí)器
- 清除componentDidMount創(chuàng)建的DOM對(duì)象
React - createClass(不推薦)
- React.createClass({}) 方式,創(chuàng)建有狀態(tài)組件,該方式已經(jīng)被廢棄!!!
- 通過(guò)導(dǎo)入 require('create-react-class'),可以在不適用ES6的情況下,創(chuàng)建有狀態(tài)組件
- getDefaultProps() 和 getInitialState() 方法:是 createReactClass() 方式創(chuàng)建組件中的兩個(gè)函數(shù)
- React without ES6
- React 不適用ES6
state和setState
- 注意:使用 setState() 方法修改狀態(tài),狀態(tài)改變后,React會(huì)重新渲染組件
- 注意:不要直接修改state屬性的值,這樣不會(huì)重新渲染組件!!!
- 使用:1 初始化state 2 setState修改state
推薦大家使用Fundebug,一款很好用的BUG監(jiān)控工具~
組件綁定事件
- 通過(guò)React事件機(jī)制 onClick 綁定
- JS原生方式綁定(通過(guò) ref 獲取元素)
- 注意:ref 是React提供的一個(gè)特殊屬性
- ref的使用說(shuō)明:react ref
React中的事件機(jī)制(推薦)
- 注意:事件名稱采用駝峰命名法
- 例如:onClick 用來(lái)綁定單擊事件
JS原生方式(知道即可)
- 說(shuō)明:給元素添加 ref 屬性,然后,獲取元素綁定事件
事件綁定中的this
- 通過(guò) bind 綁定
- 通過(guò) 箭頭函數(shù) 綁定
通過(guò)bind綁定
- 原理:bind能夠調(diào)用函數(shù),改變函數(shù)內(nèi)部this的指向,并返回一個(gè)新函數(shù)
- 說(shuō)明:bind第一個(gè)參數(shù)為返回函數(shù)中this的指向,后面的參數(shù)為傳給返回函數(shù)的參數(shù)
- 在構(gòu)造函數(shù)中使用bind
通過(guò)箭頭函數(shù)綁定
- 原理:箭頭函數(shù)中的this由所處的環(huán)境決定,自身不綁定this
受控組件
- 表單和受控組件
- 非受控組件
在HTML當(dāng)中,像input,textarea和select這類表單元素會(huì)維持自身狀態(tài),并根據(jù)用戶輸入進(jìn)行更新。 在React中,可變的狀態(tài)通常保存在組件的state中,并且只能用 setState() 方法進(jìn)行更新. React根據(jù)初始狀態(tài)渲染表單組件,接受用戶后續(xù)輸入,改變表單組件內(nèi)部的狀態(tài)。 因此,將那些值由React控制的表單元素稱為:受控組件。
- 受控組件的特點(diǎn):
- 1 表單元素
- 2 由React通過(guò)JSX渲染出來(lái)
- 3 由React控制值的改變,也就是說(shuō)想要改變?cè)氐闹?#xff0c;只能通過(guò)React提供的方法來(lái)修改
- 注意:只能通過(guò)setState來(lái)設(shè)置受控組件的值
props校驗(yàn)
- 作用:通過(guò)類型檢查,提高程序的穩(wěn)定性
- 命令:npm i -S prop-types
- 類型校驗(yàn)文檔
- 使用:給類提供一個(gè)靜態(tài)屬性 propTypes(對(duì)象),來(lái)約束props
React 單向數(shù)據(jù)流
- React 中采用單項(xiàng)數(shù)據(jù)流
- 數(shù)據(jù)流動(dòng)方向:自上而下,也就是只能由父組件傳遞到子組件
- 數(shù)據(jù)都是由父組件提供的,子組件想要使用數(shù)據(jù),都是從父組件中獲取的
- 如果多個(gè)組件都要使用某個(gè)數(shù)據(jù),最好將這部分共享的狀態(tài)提升至他們最近的父組件當(dāng)中進(jìn)行管理
- 單向數(shù)據(jù)流
- 狀態(tài)提升
react中的單向數(shù)據(jù)流動(dòng):
- 數(shù)據(jù)應(yīng)該是從上往下流動(dòng)的,也就是由父組件將數(shù)據(jù)傳遞給子組件
- 數(shù)據(jù)應(yīng)該是由父組件提供,子組件要使用數(shù)據(jù)的時(shí)候,直接從子組件中獲取
在我們的評(píng)論列表案例中:
- 數(shù)據(jù)是由CommentList組件(父組件)提供的
- 子組件 CommentItem 負(fù)責(zé)渲染評(píng)論列表,數(shù)據(jù)是由 父組件提供的
- 子組件 CommentForm 負(fù)責(zé)獲取用戶輸入的評(píng)論內(nèi)容,最終也是把用戶名和評(píng)論內(nèi)容傳遞給了父組件,由父組件負(fù)責(zé)處理這些數(shù)據(jù)( 把數(shù)據(jù)交給 CommentItem 由這個(gè)組件負(fù)責(zé)渲染 )
組件通訊
- 父 -> 子:props
- 子 -> 父:父組件通過(guò)props傳遞回調(diào)函數(shù)給子組件,子組件調(diào)用函數(shù)將數(shù)據(jù)作為參數(shù)傳遞給父組件
- 兄弟組件:因?yàn)镽eact是單向數(shù)據(jù)流,因此需要借助父組件進(jìn)行傳遞,通過(guò)父組件回調(diào)函數(shù)改變兄弟組件的props
- React中的狀態(tài)管理: flux(提出狀態(tài)管理的思想) -> Redux -> mobx
- Vue中的狀態(tài)管理: Vuex
- 簡(jiǎn)單來(lái)說(shuō),就是統(tǒng)一管理了項(xiàng)目中所有的數(shù)據(jù),讓數(shù)據(jù)變的可控
- 組件通訊
Context特性
- 注意:如果不熟悉React中的數(shù)據(jù)流,不推薦使用這個(gè)屬性
- 這是一個(gè)實(shí)驗(yàn)性的API,在未來(lái)的React版本中可能會(huì)被更改
- 作用:跨級(jí)傳遞數(shù)據(jù)(爺爺給孫子傳遞數(shù)據(jù)),避免向下每層手動(dòng)地傳遞props
- 說(shuō)明:需要配合PropTypes類型限制來(lái)使用
react-router
- react router 官網(wǎng)
- react router github
- 安裝:npm i -S react-router-dom
基本概念說(shuō)明
- Router組件本身只是一個(gè)容器,真正的路由要通過(guò)Route組件定義
使用步驟
- 1 導(dǎo)入路由組件
- 2 使用 <Router></Router> 作為根容器,包裹整個(gè)應(yīng)用(JSX)
- 在整個(gè)應(yīng)用程序中,只需要使用一次
- 3 使用 <Link to="/movie"></Link> 作為鏈接地址,并指定to屬性
- 4 使用 <Route path="/" compoent={Movie}></Route> 展示路由內(nèi)容
注意點(diǎn)
- <Router></Router>:作為整個(gè)組件的根元素,是路由容器,只能有一個(gè)唯一的子元素
- <Link></Link>:類似于vue中的<router-link></router-link>標(biāo)簽,to 屬性指定路由地址
- <Route></Route>:類似于vue中的<router-view></router-view>,指定路由內(nèi)容(組件)展示位置
路由參數(shù)
- 配置:通過(guò)Route中的path屬性來(lái)配置路由參數(shù)
- 獲取:this.props.match.params 獲取
路由跳轉(zhuǎn)
- react router - history
- history.push() 方法用于在JS中實(shí)現(xiàn)頁(yè)面跳轉(zhuǎn)
- history.go(-1) 用來(lái)實(shí)現(xiàn)頁(yè)面的前進(jìn)(1)和后退(-1)
fetch
- 作用:Fetch 是一個(gè)現(xiàn)代的概念, 等同于 XMLHttpRequest。它提供了許多與XMLHttpRequest相同的功能,但被設(shè)計(jì)成更具可擴(kuò)展性和高效性。
- fetch() 方法返回一個(gè)Promise對(duì)象
fetch 基本使用
- fetch Response
- fetch 介紹
- Javascript 中的神器——Promise
推薦大家使用Fundebug,一款很好用的BUG監(jiān)控工具~
跨域獲取數(shù)據(jù)的三種常用方式
- JSONP
- 代理
- CORS
JSONP
- 安裝:npm i -S fetch-jsonp
- 利用JSONP實(shí)現(xiàn)跨域獲取數(shù)據(jù),只能獲取GET請(qǐng)求
- fetch-jsonp
- fetch-jsonp
- 限制:1 只能發(fā)送GET請(qǐng)求 2 需要服務(wù)端支持JSONP請(qǐng)求
代理
- webpack-dev-server 代理配置如下:
- 問(wèn)題:webpack-dev-server 是開發(fā)期間使用的工具,項(xiàng)目上線了就不再使用 webpack-dev-server
- 解決:項(xiàng)目上線后的代碼,也是會(huì)部署到一個(gè)服務(wù)器中,這個(gè)服務(wù)器配置了代理功能即可(要求兩個(gè)服務(wù)器中配置的代理規(guī)則相同)
CORS - 服務(wù)器端配合
- 示例:NodeJS設(shè)置跨域
- 跨域資源共享 CORS 詳解 - 阮一峰
redux
- 狀態(tài)管理工具,用來(lái)管理應(yīng)用中的數(shù)據(jù)
- Action:行為的抽象,視圖中的每個(gè)用戶交互都是一個(gè)action
- 比如:點(diǎn)擊按鈕
- Reducer:行為響應(yīng)的抽象,也就是:根據(jù)action行為,執(zhí)行相應(yīng)的邏輯操作,更新state
- 比如:點(diǎn)擊按鈕后,添加任務(wù),那么,添加任務(wù)這個(gè)邏輯放到 Reducer 中
- 創(chuàng)建State
- Store:
- Redux應(yīng)用只能有一個(gè)store
- getState():獲取state
- dispatch(action):更新state
推薦大家使用Fundebug,一款很好用的BUG監(jiān)控工具~
相關(guān)文章
- React數(shù)據(jù)流和組件間的溝通總結(jié)
- 單向數(shù)據(jù)流和雙向綁定各有什么優(yōu)缺點(diǎn)?
- 怎么更好的理解虛擬DOM?
- React中文文檔
- React 源碼剖析系列 - 不可思議的 react diff
- 深入淺出React(四):虛擬DOM Diff算法解析
轉(zhuǎn)載于:https://my.oschina.net/u/3375885/blog/3060016
總結(jié)
以上是生活随笔為你收集整理的React入门看这篇就够了的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Spark学习之Spark RDD算子
- 下一篇: Django路由与视图