您好,登錄后才能下訂單哦!
怎樣深入理解的數(shù)據(jù)流和事件原理,針對(duì)這個(gè)問題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問題的小伙伴找到更簡(jiǎn)單易行的方法。
在React中,數(shù)據(jù)流是自上而下單向的從父節(jié)點(diǎn)傳遞到子節(jié)點(diǎn),所以組件是簡(jiǎn)單且容易把握的,他們只需要從父節(jié)點(diǎn)提供的props中獲取數(shù)據(jù)并渲染即可。如果頂層組件的某個(gè)prop改變了,React會(huì)遞歸地向下遍歷整棵組件數(shù),重新渲染所有使用這個(gè)屬性的組件。
這個(gè)是前面看到的 KM 熱點(diǎn)問題組件,擁有一個(gè)叫做 articles 的屬性。
在組件內(nèi)部,可以通過this.props來訪問props,props是組件唯一的數(shù)據(jù)來源,對(duì)于組件來說:
props永遠(yuǎn)是只讀的。
不要嘗試在組件內(nèi)部調(diào)用setProps方法來修改props,如果你不小心這么做了,React會(huì)報(bào)錯(cuò)并給出非常詳細(xì)的錯(cuò)誤提示。
組件的屬性類型如果不進(jìn)行聲明和驗(yàn)證,那么很可能使用者傳給你的屬性值或者類型是無效的,那會(huì)導(dǎo)致一些意料之外的故障。好在React已經(jīng)為我們提供了一套非常簡(jiǎn)單好用的屬性校驗(yàn)機(jī)制——
React有一個(gè)PropTypes屬性校驗(yàn)工具,經(jīng)過簡(jiǎn)單的配置即可。當(dāng)使用者傳入的參數(shù)不滿足校驗(yàn)規(guī)則時(shí),React會(huì)給出非常詳細(xì)的警告,定位問題不要太容易。
PropTypes包含的校驗(yàn)類型包括基本類型、數(shù)組、對(duì)象、實(shí)例、枚舉——
以及對(duì)象類型的深入驗(yàn)證等等。如果內(nèi)置的驗(yàn)證類型不滿足需求,還可以通過自定義規(guī)則來驗(yàn)證。
如果某個(gè)屬性是必須的,在類型后面加上 isRequired 就可以了。
React的一大創(chuàng)新,就是把每一個(gè)組件都看成是一個(gè)狀態(tài)機(jī),組件內(nèi)部通過state來維護(hù)組件狀態(tài)的變化,這也是state唯一的作用。
state一般和事件一起使用,我們先看state,然后看看state和事件怎樣結(jié)合。
這是一個(gè)簡(jiǎn)單的開關(guān)組件,開關(guān)狀態(tài)會(huì)以文字的形式表現(xiàn)在按鈕的文本上。
首先看render方法,返回了一個(gè)button元素,給button注冊(cè)了一個(gè)事件用來處理點(diǎn)擊事件,在點(diǎn)擊事件中對(duì)state的on字段取反,并執(zhí)行 this.setState() 方法設(shè)置on字段的新值。一個(gè)開關(guān)組件就完成了。
組件渲染完成后,必須有UI事件的支持才能正常工作。
React通過將事件處理器綁定到組件上來處理事件。
React事件本質(zhì)上和原生JS一樣,鼠標(biāo)事件用來處理點(diǎn)擊操作,表單事件用于表單元素變化等,Rreact事件的命名、行為和原生JS差不多,不一樣的地方是React事件名區(qū)分大小寫。
比如這段代碼中,Article組件的section節(jié)點(diǎn)注冊(cè)了一個(gè)onClick事件,點(diǎn)擊后彈出alert。
有時(shí)候,事件的處理器需要由組件的使用者來提供,這時(shí)可以通過props將事件處理器傳進(jìn)來。
這個(gè)是剛才那個(gè)Article組件的使用者,它提供給Article組件的props中包含了一個(gè)onClick屬性,這個(gè)onClick指向這個(gè)組件自身的一個(gè)事件處理器,這樣就實(shí)現(xiàn)了在組件外部處理事件回調(diào)。
這是一個(gè)React組件實(shí)現(xiàn)組件可交互所需的流程,render()輸出虛擬DOM,虛擬DOM轉(zhuǎn)為DOM,再在DOM上注冊(cè)事件,事件觸發(fā)setState()修改數(shù)據(jù),在每次調(diào)用setState方法時(shí),React會(huì)自動(dòng)執(zhí)行render方法來更新虛擬DOM,如果組件已經(jīng)被渲染,那么還會(huì)更新到DOM中去。
這些是React目前支持的事件列表。
React的組件擁有一套清晰完整而且非常容易理解的生命周期機(jī)制,大體可以分為三個(gè)過程:初始化、更新和銷毀,在組件生命周期中,隨著組件的props或者state發(fā)生改變,它的虛擬DOM和DOM表現(xiàn)也將有相應(yīng)的變化。
首先是初始化過程,這里會(huì)著重講,需要充分理解。
組件類在聲明時(shí),會(huì)先調(diào)用 getDefaultProps() 方法來獲取默認(rèn)props值,這個(gè)方法會(huì)且只會(huì)在聲明組件類時(shí)調(diào)用一次,這一點(diǎn)需要注意,它返回的默認(rèn)props由所有實(shí)例共享。
在組件被實(shí)例化之前,會(huì)先調(diào)用一次實(shí)例方法 getInitialState() 方法,用于獲取這個(gè)組件的初始state。
實(shí)例化之后就是渲染,componentWillMount方法會(huì)在生成虛擬DOM之前被調(diào)用,你可以在這里對(duì)組件的渲染做一些準(zhǔn)備工作,比如計(jì)算目標(biāo)容器尺寸然后修改組件自身的尺寸以適應(yīng)目標(biāo)容器等等。
接下來就是渲染工作,在這里你會(huì)創(chuàng)建一個(gè)虛擬DOM用來表示組件的結(jié)構(gòu)。對(duì)于一個(gè)組件來說,render 是唯一一個(gè)必須的方法。render方法需要滿足這幾點(diǎn):
1.只能通過 this.props 或 this.state 訪問數(shù)據(jù)
2.只能出現(xiàn)一個(gè)頂級(jí)組件
3.可以返回 null、false 或任何 React 組件
4.不能對(duì) props、state 或 DOM 進(jìn)行修改
需要注意的是,render 方法返回的是虛擬DOM。
渲染完成以后,我們可能需要對(duì)DOM做一些操作,比如截屏、上報(bào)日志、或者初始化iScroll等第三方非React插件,可以在 componentDidMount() 方法中做這些事情。當(dāng)然,你也可以在這個(gè)方法里通過 this.getDOMNode() 方法取得最終生成DOM節(jié)點(diǎn),然后對(duì)DOM節(jié)點(diǎn)做愛做的事情,但需要注意做好安全措施,不要緩存已經(jīng)生成的DOM節(jié)點(diǎn),因?yàn)檫@些DOM節(jié)點(diǎn)隨時(shí)可能被替換掉,所以應(yīng)該在每次用的時(shí)候去讀取。
組件被初始化完成后,它的狀態(tài)會(huì)隨著用戶的操作、時(shí)間的推移、數(shù)據(jù)更新而產(chǎn)生變化,變化的過程是組件聲明周期的另一部分 ——
更新過程。
當(dāng)組件已經(jīng)被實(shí)例化后,使用者調(diào)用 setProps() 方法修改組件的數(shù)據(jù)時(shí),組件的 componentWillReceiveProps() 方法會(huì)被調(diào)用,在這里,你可以對(duì)外部傳入的數(shù)據(jù)進(jìn)行一些預(yù)處理,比如從props中讀取數(shù)據(jù)寫入state。
默認(rèn)情況下,使用者調(diào)用組件的 setProps() 方法后,React會(huì)遍歷這個(gè)組件的所有子組件,進(jìn)行“灌水”,將props從上到下一層一層傳下去,并逐個(gè)執(zhí)行更新操作,雖然React內(nèi)部已經(jīng)進(jìn)行過很多的優(yōu)化,這個(gè)過程并不會(huì)花費(fèi)多少時(shí)間,但是程序員里永遠(yuǎn)不缺乏長(zhǎng)期性能饑渴的同學(xué),不用擔(dān)心,React有一個(gè)能夠解決你性能饑渴的辦法——shouldComponentUpdate()。
有時(shí)候,props發(fā)生了變化,但組件和子組件并不會(huì)因?yàn)檫@個(gè)props的變化而發(fā)生變化,打個(gè)比方,你有一個(gè)表單組件,你想要修改表單的name,同時(shí)你能夠確信這個(gè)name不會(huì)對(duì)組件的渲染產(chǎn)生任何影響,那么你可以直接在這個(gè)方法里return false來終止后續(xù)行為。這樣就能夠避免無效的虛擬DOM對(duì)比了,對(duì)性能會(huì)有明顯提升。
如果這個(gè)時(shí)候有同學(xué)仍然饑渴難耐,那么你可以嘗試 不可變數(shù)據(jù)結(jié)構(gòu)(用過mongodb的同學(xué)應(yīng)該懂)。
組件在更新前,React會(huì)執(zhí)行componentWillUpdate() 方法,這個(gè)方法類似于前面看到的 componentWillMount()方法,唯一不同的地方只是這個(gè)方法在執(zhí)行的時(shí)候組件是已經(jīng)渲染過的。需要注意的是,不可以在這個(gè)方法中修改props或state,如果要修改,應(yīng)當(dāng)在 componentWillReceiveProps() 中修改。
然后是渲染,React會(huì)拿這次返回的虛擬DOM和緩存中的虛擬DOM進(jìn)行對(duì)比,找出【最小修改點(diǎn)】,然后替換。
更新完成后,React會(huì)調(diào)用組件的componentDidUpdate 方法,這個(gè)方法類似于前面 componentDidMount 方法,你仍然可以在這里可以通過 this.getDOMNode() 方法取得最終的DOM節(jié)點(diǎn)。
香港電影結(jié)尾經(jīng)??吹揭粋€(gè)劇情,就是英雄打敗了壞人,然后警察出來擦屁股——
警察偶爾還能立功,而 componentWillUnmount 最可憐,他除了擦屁股什么也做不了。
你可以在這個(gè)方法中銷毀非React組件注冊(cè)的事件、插入的節(jié)點(diǎn),或者一些定時(shí)器之類。這個(gè)過程可能容易出錯(cuò),比如綁定了事件卻沒銷毀,這個(gè)React可幫不了你,你自己約的炮,含著淚也要打完。
兩節(jié)內(nèi)容講了上手React所必備的知識(shí)。
后面講價(jià)值。
直出有多快我就不多說了。
因?yàn)橛刑摂MDOM的存在,React可以很容易的將虛擬DOM轉(zhuǎn)換為字符串,這便使我們可以只寫一份UI代碼,同時(shí)運(yùn)行在node里和和瀏覽器里。
在node里將組件HTML渲染為一段HTML一句話即可。
不過圍繞這個(gè)renderToString我們還要做一些準(zhǔn)備工作。代碼有點(diǎn)多,大家做好心理準(zhǔn)備。
這是一個(gè)express的路由方法,在這里:
1.從后臺(tái)server或數(shù)據(jù)庫等來源拉取數(shù)據(jù)
2.引入要渲染的React組件
3.調(diào)用React.renderToString()方法來生成HTML
4.最后發(fā)送HTML和數(shù)據(jù)給瀏覽器
這里為了方便描述,沒有寫拉取數(shù)據(jù)的代碼,大家自行腦補(bǔ)。
需要注意的是這里的JSON字符串中可能出現(xiàn)結(jié)尾標(biāo)簽或HTML注釋,可能會(huì)導(dǎo)致語法錯(cuò)誤,這里需要進(jìn)行轉(zhuǎn)義。
頁面的示例代碼本來打算用大家更熟悉的HTML,但發(fā)現(xiàn)代碼量太多了PPT里一頁放不下,所以換成了jade代碼,沒用過jade的同學(xué)也順便了解一下,我也順便給jade打個(gè)廣告。
這個(gè)頁面做了X個(gè)事:
1.將前面在action里生成的HTML寫到#container元素里
2.引入必須的JS文件
3.獲取action提供的數(shù)據(jù)
4.渲染組件
這就是React的服務(wù)端渲染,組件的代碼前后端都可以復(fù)用。
<有沒有沒理解清楚的同學(xué)?>
是不是感覺React挺牛逼的?大家以為React就這么點(diǎn)能耐嗎?
React能夠用一套代碼同時(shí)運(yùn)行在瀏覽器和node里,而且能夠以原生App的姿勢(shì)運(yùn)行在iOS和Android系統(tǒng)中,即擁有了web迭代迅速的特性,又擁有原生App的體驗(yàn)。
這個(gè)姿勢(shì)叫做 React-Native。
這是React和React-Native在github上的數(shù)據(jù),可以看出React-Native也是相當(dāng)熱門——因?yàn)镽eact-Native能夠使React的價(jià)值最大化,這個(gè)價(jià)值是什么呢——對(duì)業(yè)務(wù)來說,意味著不需要為了做終端版本就招聘和前端等量人力的終端開發(fā),同時(shí)意味著我們成為全棧工程師有了一個(gè)捷徑。
了解iOS開發(fā)的同學(xué)都知道,水果公司對(duì)應(yīng)用上架的審核效率實(shí)在讓人無力吐槽,很多團(tuán)隊(duì)上一個(gè)版本還沒審核結(jié)束,下一個(gè)版本就已經(jīng)做好了。而React-Native支持從網(wǎng)絡(luò)拉取JS,這樣iOS應(yīng)用也能夠像web一樣實(shí)現(xiàn)快速迭代了。
這個(gè)是react-native的調(diào)試過程
作為一個(gè)沒寫過一句Object-C代碼的web前端開發(fā),我只用了一天時(shí)間就上手了react-native,然后用了半天時(shí)間做出了一個(gè)簡(jiǎn)單的demo頁面,可以看到react-native的生產(chǎn)效率還是非常高的。
單元測(cè)試顧名思義,是對(duì)各個(gè)模塊進(jìn)行最小范圍的測(cè)試,容易。
因?yàn)樘摂MDOM的存在,使得react的代碼很容易做好單元測(cè)試,這是上面那段代碼的測(cè)試用例,通過karma執(zhí)行后即可看到結(jié)果。
關(guān)于怎樣深入理解的數(shù)據(jù)流和事件原理問題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識(shí)。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。