【D1N910】一線大廠React實(shí)踐寶典 React中的數(shù)據(jù)管理(進(jìn)度 5/9)
正常操作,正常分析,大家好,我是D1N910。
在大約兩年前,我購買了?騰訊課堂【NEXT】一線大廠 React 實(shí)踐寶典 這門課。?
因?yàn)槲乙恢被旧鲜鞘褂肰ue來進(jìn)行前端頁面的開發(fā),但是一直沒有時(shí)間去實(shí)踐看完。 兩年沒去看了,真的很慚愧,時(shí)間,唉,過得真快啊。
為了在這門課過期之前看完,所以我要抓緊時(shí)間學(xué)完了。
本系列的專欄記錄了我學(xué)習(xí)?一線大廠React實(shí)踐寶典? 的筆記。?
下面的內(nèi)容版權(quán)歸屬是??騰訊課堂【NEXT】一線大廠 React 實(shí)踐寶典 這門課。
當(dāng)然,如果我微不足道的筆記也算是我自己的版權(quán),那么也是有我的小小一份。
你可以用來學(xué)習(xí) React。
但是如果你用來商業(yè)化盈利,請先獲得??騰訊課堂【NEXT】一線大廠 React 實(shí)踐寶典 制作方的許可。
BTW,作為挖坑狂魔,如果這篇專欄沒有更新,那么當(dāng)我沒說過。
這是一個(gè)系列的文章,如果你沒有看過前面的內(nèi)容,那么建議你先看一看



這是一個(gè)自己的約定,五一,沖沖沖!
現(xiàn)在,拿下 《?React中的數(shù)據(jù)管理》這座山,能達(dá)到今天進(jìn)度的 2/3,寶貝,加油!
而且很重要的是,如果成功翻越了這座大山,那么對(duì)于我自己來說接下來都是船新版本!從之前到現(xiàn)在的?React中的數(shù)據(jù)管理 ,是我兩年前已經(jīng)學(xué)習(xí)過的內(nèi)容!后面就沒學(xué)習(xí)了,所以,要堅(jiān)持下去!
五一還有一天又一個(gè)小時(shí),沖沖沖!

組件間的簡單通信
玩轉(zhuǎn)?React 單向數(shù)據(jù)流(小劇場)
A:最近 React 學(xué)習(xí)得如何了
B:最近我正在用父組件包裹子組件,對(duì)于子組件之間的共享數(shù)據(jù),我正在研究應(yīng)該如何處理呢。
C:其實(shí)你可以把所有的數(shù)據(jù)都放在父組件中進(jìn)行存儲(chǔ),然后再由父組件傳遞給子組件,這樣也不會(huì)違反單向數(shù)據(jù)流的原則。
B:但這樣有一個(gè)問題啊。子組件該如何重新接受數(shù)據(jù),并重新渲染呢?
A:如果你采用 props 傳輸數(shù)據(jù),子組件是會(huì)自動(dòng)接收到更新并渲染的,無需手動(dòng)處理。
數(shù)據(jù)流
這一節(jié),將從數(shù)據(jù)流的角度研究?React。
數(shù)據(jù)流表示了系統(tǒng)中數(shù)據(jù)的傳遞方向
React 的特性之一就是單向數(shù)據(jù)流
數(shù)據(jù)只能從上層傳入,或者由自己維護(hù)
以一個(gè) Component 為例子,它可以從父組件中拿到 props,這樣從父組件從上到下拿到數(shù)據(jù),就是 React 中的數(shù)據(jù)流。
Component 本身也可以維護(hù) state,組件內(nèi)部定義、使用和改變 State。
在構(gòu)造函數(shù)中初始化我們的 state,用 this.state 調(diào)用,用 this.setState 進(jìn)行修改,這些都是在組件內(nèi)部完成的。
那么組件與組件是如何傳遞數(shù)據(jù)的呢?
組件之間彼此相互獨(dú)立,實(shí)現(xiàn)特定的功能。想要能夠互相傳遞數(shù)據(jù),那么就要有關(guān)聯(lián)關(guān)系,比如父子組件的關(guān)系。
組件間傳遞數(shù)據(jù)的四種類型
1、父組件向子組件傳遞數(shù)據(jù)(單獨(dú)使用?props?即可實(shí)現(xiàn))
2、子組件向父組件傳遞數(shù)據(jù)
3、兄弟組件之間傳遞數(shù)據(jù)
4、任意兩個(gè)組件之間傳遞數(shù)據(jù)

狀態(tài)提升
上一節(jié)說了組件之間傳遞數(shù)據(jù)的幾種情況,也明白父組件向子組件傳遞數(shù)據(jù)的方法是通過 props,這個(gè)是我們已經(jīng)接觸過的。
剩下的三種類型將在這一節(jié)進(jìn)行論述。
子組件向父組件傳遞數(shù)據(jù)
父組件可以通過 props 傳遞任何數(shù)據(jù)給子組件,包括函數(shù)。
當(dāng)我們把函數(shù)傳遞到子組件的時(shí)候,我們的子組件是可以調(diào)用這個(gè)函數(shù)的,通過調(diào)用這個(gè)函數(shù),可以讓函數(shù)把數(shù)據(jù)傳入到父組件的函數(shù)體內(nèi)。
父組件 -> 傳遞函數(shù) ->? 子組件 -> 調(diào)用函數(shù)(帶參)->? 父組件
將 props 設(shè)置為回調(diào)函數(shù)可以解決子組件向父組件傳遞數(shù)據(jù)的問題。
將函數(shù)通過 props 傳遞給子組件
這邊舉了一個(gè)簡單的例子,在子組件掛載的時(shí)候調(diào)用父組件的方法。

當(dāng)然,如果想要調(diào)用的時(shí)候執(zhí)行父組件的更新狀態(tài),則需要在父組件里綁定 this 。

兄弟組件傳遞數(shù)據(jù)
兄弟組件傳遞數(shù)據(jù)的方式是:通過父組件連接子組件進(jìn)行數(shù)據(jù)交換
兄弟A -> 數(shù)據(jù) -> 父組件 -> 數(shù)據(jù) -> 兄弟B
舉個(gè)例子,下面的兩個(gè)兄弟組件分別可以影響它們的兄弟數(shù)據(jù)。

我們這里沒有單獨(dú)在子組件的 state 中維護(hù)我們的 count 變量,而是放到了父組件中,這也就相當(dāng)于數(shù)據(jù)被“提升”到父組件中。這個(gè)就叫狀態(tài)提升。
任意兩個(gè)組件傳遞數(shù)據(jù)
通過全局變量連接各個(gè)組件
發(fā)布-訂閱模式:實(shí)現(xiàn)一個(gè)消息組件,每次需要傳遞數(shù)據(jù)的時(shí)候,會(huì)拋出一個(gè)事件,對(duì)這個(gè)事件有興趣的組件會(huì)監(jiān)聽這個(gè)消息,監(jiān)聽到這個(gè)消息會(huì)進(jìn)行數(shù)據(jù)變換。
window下的全局變量:這種一般是用來讀取配置。
Context:這種是通過 React 的 Context,通過訪問上下文,使得能夠訪問得到應(yīng)用的共同區(qū)域。這種也一般是用來讀取全局配置,比如應(yīng)用的主題色,各個(gè)組件都需要訪問,但是不會(huì)去進(jìn)行配置的一些東西。
* 這部分的內(nèi)容,按照課程安排,放在下下節(jié)的資料篇進(jìn)行講解
本小節(jié)完畢,相關(guān)代碼如下
https://github.com/D1N910/learn-react/tree/master/Chapter4/demo-1-send-data

簡易聊天室
這個(gè)算是要自己完成的項(xiàng)目了,就是利用上面講的狀態(tài)提升的概念,完成一個(gè)聊天室。
效果如下,發(fā)送的時(shí)候,三個(gè)聊天框能出現(xiàn)剛剛發(fā)送的內(nèi)容。

能夠?qū)崿F(xiàn)就好,當(dāng)然,你也可以看看我的做法,代碼如下
https://github.com/D1N910/learn-react/tree/master/Chapter4/demo-2-chatroom
我的代碼里沒有添加類型檢查,你加了就最好了

【資料】發(fā)布-訂閱模式(大量參考了原資料)
剛剛我們有聊過,不同組件之間可以通過發(fā)布-訂閱模式來實(shí)現(xiàn)數(shù)據(jù)更新。
首先介紹下 發(fā)布-訂閱 概念。
什么是發(fā)布-訂閱模式?
發(fā)布-訂閱模式一般由下面三個(gè)部分組成
發(fā)布者:發(fā)布消息,供訂閱者訂閱(不知道是誰訂閱了,他也一般沒必要知道)
訂閱者:訂閱特定類型的消息(不知道是誰發(fā)布的消息,他也一般沒必要知道)
功能器:作為中介連接發(fā)布者和訂閱者,發(fā)布者可以向功能器發(fā)布消息以供訂閱者訂閱,訂閱者可以向功能器訂閱特性類型的消息。
生活中,有一種類似發(fā)布-訂閱模式的例子就是廣播電臺(tái)。
不同的廣播站發(fā)布消息 -> 廣播臺(tái)處理轉(zhuǎn)發(fā)出去 -> 用戶收聽自己愛聽某個(gè)廣播站
發(fā)布-訂閱模式優(yōu)點(diǎn)
松耦合
發(fā)布者不需要知道訂閱者的數(shù)量,或者訂閱者是通過什么方式運(yùn)行的。他們能夠相互獨(dú)立地運(yùn)行,這樣就可以讓你分開開發(fā)這兩部分而不需要擔(dān)心對(duì)狀態(tài)或?qū)崿F(xiàn)的任何細(xì)微的影響。
更干凈的設(shè)計(jì)
充分地利用好發(fā)布-訂閱模式,你不得不深入地思考不同的組件是如何交互的。這通常會(huì)讓我們的設(shè)計(jì)更加干凈整潔。
靈活性
你不需要擔(dān)心不同的組件是如何組合在一起的。只要他們采用同一種發(fā)布-訂閱的實(shí)現(xiàn)。
容易測試
你可以很好地找出發(fā)布者或訂閱者是否會(huì)得到錯(cuò)誤的信息。
當(dāng)然,發(fā)布者和訂閱者隔離也會(huì)導(dǎo)致系統(tǒng)不穩(wěn)定、發(fā)布者或訂閱者數(shù)量激增時(shí)出現(xiàn)問題等缺點(diǎn),但是一般而言,項(xiàng)目中恰當(dāng)?shù)厥褂冒l(fā)布-訂閱模式是有助于我們的實(shí)際開發(fā)的。
發(fā)布-訂閱模式實(shí)現(xiàn)
下面是原生代碼實(shí)現(xiàn)應(yīng)用的 發(fā)布-訂閱 模式
class Events {
constructor() {
? ? ? ? ?// 緩存 被訂閱的事件以及對(duì)應(yīng)的回調(diào)函數(shù)
? ? ? ? ?this.cache = {}
? ? ? ?}
/**
? ? ? ? * 發(fā)布
? ? ? ? * topic 發(fā)布的事件名稱
? ? ? ? * parameter 傳遞的參數(shù)
? ? ? ? * scope 綁定執(zhí)行的對(duì)象
? ? ? ?**/
publish(topic, parameter, scope) {
? ? ? ? ?const thisTopic = this.cache[topic]
? ? ? ? ?// 如果有訂閱
? ? ? ? ?if (thisTopic) {
? ? ? ? ? ?let i = thisTopic.length - 1
? ? ? ? ? ?for (i; i >=0; i -= 1) {
? ? ? ? ? ? ?// 執(zhí)行訂閱回調(diào)
? ? ? ? ? ? ?thisTopic[i].apply(scope || this, parameter || [])
? ? ? ? ? ?}
? ? ? ? ?}
? ? ? ?}
/**
? ? ? ? * 訂閱
? ? ? ? * topic 發(fā)布的事件名稱
? ? ? ? * callback 回調(diào)參數(shù)
? ? ? ?**/
subscribe(topic, callback) {
? ? ? ? ?if (!this.cache[topic]) {
? ? ? ? ? ?this.cache[topic] = []
? ? ? ? ?}
? ? ? ? ?// 添加回調(diào)
? ? ? ? ?this.cache[topic].push(callback)
? ? ? ? ?// 可以方便用于取消訂閱
? ? ? ? ?return [topic, callback]
? ? ? ?}
/**
? ? ? ? * 取消訂閱
? ? ? ? * handle [topic, callback]
? ? ? ? * complety 是否把所有該同名事件訂閱都取消
? ? ? ?**/
unsubscribe(handle, complety) {
? ? ? ? ?const topic = handle[0];
? ? ? ? ?const callback = handle[1];
? ? ? ? ?const thisTopic = this.cache[topic]
? ? ? ? ?if (thisTopic) {
? ? ? ? ? ?if (complety) {
? ? ? ? ? ? ?delete this.cache[topic]
? ? ? ? ? ? ?return false
? ? ? ? ? ?}
? ? ? ? ? ?let i = thisTopic.length - 1
? ? ? ? ? ?for (i; i >= 0; i -= 1) {
? ? ? ? ? ? ?if (thisTopic[i] === callback) {
? ? ? ? ? ? ? ?this.cache[topic].splice(i)
? ? ? ? ? ? ?}
? ? ? ? ? ?}
? ? ? ? ?}
? ? ? ?}
}
? ? ?// 測試
? ? ?// 廣播臺(tái)
const event = new Events()
? ? ?// 訂閱一個(gè)天氣
const theWeather = event.subscribe('weatherChange', (e) => {
? ? ? ?console.log('現(xiàn)在的天氣是', e)
? ? ?})
? ? ?// 發(fā)布一個(gè)陰天
const weather0504 = event.publish('weatherChange', ['陰天'])
? ? ?// 發(fā)布一個(gè)晴天
const weather0505 = event.publish('weatherChange', ['晴天'])
? ? ?// 取消訂閱
event.unsubscribe(theWeather)
? ? ?// 發(fā)布一個(gè)下雨天
const weather0506 = event.publish('weatherChange', ['下雨天'])

你也可以直接用下面的方式獲得代碼 (記得把注釋打開)
https://github.com/D1N910/learn-react/blob/master/Chapter4/demo-3-publish-subscribe/index.html
在剛剛的聊天室中使用 訂閱-發(fā)布模式
1、添加一個(gè)工具包文件夾,里面放置各種工具,比如這個(gè) 訂閱-發(fā)布 工具

2、在 index.js 中使用??訂閱-發(fā)布 工具,并且在公共對(duì)象上創(chuàng)建一個(gè)廣播臺(tái)實(shí)例

3、整理干掉父組件剛剛綁定的修改聊天室記錄的方法

4、修改 talker
在 componentDidMount 生命周期里,訂閱 聊天記錄更新 的消息

原來的提交,改為發(fā)布一個(gè)消息

最后效果發(fā)現(xiàn)保持一致

(1)原來文章寫的取消訂閱方法有問題,我上邊的整理優(yōu)化了

(2)聊天室的 消息-訂閱 模式 原創(chuàng)整理完成,所以我也知道為啥 componentDidMount 這個(gè)方法推薦的除了做 ajax 請求,還可以做消息訂閱是怎么回事了。
聊天室改造為 消息-訂閱 模式的代碼在下面
https://github.com/D1N910/learn-react/tree/master/Chapter4/demo-3-publish-subscribe

【資料】Cntext(大量參考了原資料)
什么是 Context?
在一般的 React 程序中,數(shù)據(jù)通過 props 自上而下由父對(duì)象傳遞給子對(duì)象,但是對(duì)于某些變量來說(比如全局環(huán)境變量、全局主題等)如果層層傳遞,會(huì)增加很多麻煩。而 Context 提供了一種在組件之間共享這些值的方法,無需通過組件層層傳遞 props。
在 Context 的使用中,有兩種角色,一種是 Context 的生產(chǎn)者(Provider),通常是一個(gè)父節(jié)點(diǎn),另外一種是 Context 的消費(fèi)者(Consumer),通常是一個(gè)或多個(gè)子節(jié)點(diǎn),因此,我們也可以將 Context 理解為一種生產(chǎn)者-消費(fèi)者模式。
這里用的 Context 主要基于 V16.3+
Context 的使用 —— 以用 Context 來將 theme 到孫子組件為例子。
下面用?context?實(shí)現(xiàn)按鈕主題色變化。

代碼如下
https://github.com/D1N910/learn-react/tree/master/Chapter4/demo-4-context
這邊其實(shí)不建議用 Context,這屬于高級(jí)的 API,而且感覺改動(dòng)得有點(diǎn)快。
使用 Context 傳遞的內(nèi)容過多,反而會(huì)讓我們的數(shù)據(jù)流向不清晰,從而讓我們的應(yīng)用變得難以維護(hù)和調(diào)試。

Flux
它來了,它來了,它作為一個(gè)新的知識(shí)走來了 —— 雖然上面的,對(duì)于我來說,也是新的知識(shí)。
Flux介紹(小劇場)
A:我看你在這里愁眉苦臉半天了,是在解決什么復(fù)雜的問題嗎?
B:對(duì)啊,本周我收到一個(gè)任務(wù),是要給一個(gè)社區(qū)頁面增加一些新的功能。但是涉及到很多組件的聯(lián)動(dòng)。一些組件的更改,往往需要其他組件也會(huì)進(jìn)行反應(yīng),這個(gè)問題做起來比較復(fù)雜。
A:那你現(xiàn)在是怎么做的呢?
B:我現(xiàn)在采用的是父子組件的通信以及子組件事件通知的方式。但是管理起來,還是很復(fù)雜。
C:聽你們講述的內(nèi)容,感覺你們可以用一下 Flux 架構(gòu)。
A:通過使用 Flux 架構(gòu),我們可以把共有的數(shù)據(jù)管理起來,我們可以比較方便地實(shí)現(xiàn)你這里的這些功能,而且我們的代碼邏輯也能更加清晰。
B:那我就需要很好了解 Flux 了。
Flux 設(shè)計(jì)理念
通過上面的學(xué)習(xí),我們以及可以在各個(gè)組件之間傳遞數(shù)據(jù)了,但是大量的 props 、全局變量的情況下,會(huì)讓我們的項(xiàng)目難以維護(hù)。
Flux 是一種使得 React 應(yīng)用數(shù)據(jù)更加嚴(yán)謹(jǐn)?shù)貑蜗蛄鲃?dòng)的架構(gòu)。
以往的數(shù)據(jù)架構(gòu)是什么?
有名的 MVC 架構(gòu)
Action -> Controller -> Modal -> View
看起來清晰,但是在我們的數(shù)據(jù)模型復(fù)雜后,就會(huì)發(fā)現(xiàn)變得非常繁雜了,交互會(huì)變得很凌亂,因?yàn)闆]有一個(gè)單向數(shù)據(jù)流。項(xiàng)目很大以后,會(huì)顯得很難維護(hù)。
比如某個(gè) Model 的更改,并不知道會(huì)影響哪個(gè) View。

同樣的,如果 React 當(dāng)中的數(shù)據(jù)流,如果不加以控制,也同樣會(huì)復(fù)雜不清晰,難以維護(hù)

如何有效管理數(shù)據(jù)流的變化?
解決方案:兩者結(jié)合,更加受限的單向數(shù)據(jù)流。
提供一個(gè) control center,數(shù)據(jù)中心,所有的數(shù)據(jù)會(huì)上傳到數(shù)據(jù)中心處理,然后再從數(shù)據(jù)中心獲取值。
這樣的數(shù)據(jù)交互方式就很清晰了。

只需要和數(shù)據(jù)中心做交互,而不需要和其他組件做交互。
數(shù)據(jù)總是從源節(jié)點(diǎn)流向控制中心,再流向目標(biāo)節(jié)點(diǎn)。
流程如下

通過唯一的 Dispatcher 來去控制傳遞事件。
React 作為視圖層 View,F(xiàn)lux 中的 Store 則作為數(shù)據(jù)中心 M, Flux 中的 Dispatcer 則可作為一個(gè)控制中心 C,負(fù)責(zé)用戶行為的響應(yīng)和 Modal 層的改變,。
React 不一定需要綁定 Flux,但在復(fù)雜度高的項(xiàng)目中使用 Flux 架構(gòu),可以讓項(xiàng)目中的數(shù)據(jù)流更加清晰可預(yù)測,利于項(xiàng)目的維護(hù)和迭代。可以說項(xiàng)目復(fù)雜度越高,越適合引入 Flux 架構(gòu),。
Flux 約定我們視圖層不直接修改組件的狀態(tài),應(yīng)用的狀態(tài)應(yīng)當(dāng)放到 Store 中進(jìn)行管理,組件狀態(tài)的修改需要觸發(fā) Action 。
這上面就是 Flux 的主要流程。(感覺有點(diǎn)像是基于上面學(xué)的 發(fā)布-訂閱 模式)
使用 Flux 管理數(shù)據(jù)
Flux 是一個(gè)架構(gòu)而不是框架,業(yè)界有很多的實(shí)踐,比如 React-Flux,Redux(下一節(jié)的內(nèi)容)。其中的 View 層可以有很多實(shí)現(xiàn),比如這里,我們就是在 React 上實(shí)現(xiàn)。
生產(chǎn)開發(fā)的時(shí)候,不一定就要選用這種架構(gòu)進(jìn)行開發(fā),這里只是作為教學(xué)的介紹。
下面將通過實(shí)現(xiàn)一個(gè) TodoList 項(xiàng)目來實(shí)踐 Flux。
在我們的普通文件下, 新增了 action.js、dispatcher.js、store.js,分別就對(duì)應(yīng)上了剛剛流程里的部分內(nèi)容。

Actions.js

發(fā)生的事件
語義化
準(zhǔn)確描述的對(duì)象
首先定義一個(gè) ActionsTypes 對(duì)象
定義所有 Action 類型
一般我們用大寫字母表示是一個(gè)敞亮
這里類似于枚舉值
盡管它的值可以為任何類型,但是為了便于區(qū)分和比較,我們一般用字符串

其次定義各種行為方法。
可以使用 Dispacher.dispatch() 方法去派發(fā) action,雖然沒有明確的定義,但一般約定。
type:用以區(qū)分類型,值必須是上文中定義的 ActionTypes 之一。
payload: 觸發(fā)這個(gè)行為的時(shí)候攜帶的要傳遞參數(shù)。
上面這兩個(gè)變量名稱,具體有沒有這兩個(gè)變量,都是我們自定義的,而不是需要特別約束的。
上面的編碼只是一種老師認(rèn)為好的開發(fā)風(fēng)格。
后面的 store.js 就可以證明這一點(diǎn)。
整個(gè)派發(fā)方法類似這樣

* 感覺很像?發(fā)布-訂閱 模式的發(fā)布方法。
Dispatcher.js

控制中心
保持單例(整個(gè)項(xiàng)目中,只有唯一的 dispathcer)
接收 action 派發(fā)給 store
這個(gè)文件就簡單了,就是從 flux 組件中導(dǎo)入了 Dispatcher,然后導(dǎo)出了這個(gè)?Dispatcher 創(chuàng)建的實(shí)例。

* 感覺很像像?發(fā)布-訂閱 模式的實(shí)例化廣播臺(tái)。
Store.js

存儲(chǔ)應(yīng)用中的數(shù)據(jù)
用于接受 actions
只可被 action 修改
允許多個(gè)實(shí)例(下面的例子我們只用了一個(gè))
首先引入? ReduceStore 。ReduceStore 是 Store 的一種實(shí)現(xiàn),這里借鑒了 Redux 的純函數(shù)的方式,我們之后會(huì)涉及。然后需要在構(gòu)造函數(shù)中綁定 Dispatcher,這里的目的是為了能夠監(jiān)聽自動(dòng)執(zhí)行后面的方法。

getInitialState() 在這里我們相當(dāng)于在 Store 定義了 state,這里會(huì)填寫我們要的 state 以及對(duì)應(yīng)的初始值。

reduce(state, acton) {}?
?@return {*} 返回下一個(gè)狀態(tài)
?@param {*} state 上一個(gè)狀態(tài)
?@param {*} action 傳入的action
??ReduceStore 中一定要有一個(gè) reduce 方法
? 它應(yīng)該是一個(gè)純函數(shù)
? Dispatcher 派發(fā)的所有 action 都會(huì)到這里來
? 我們根據(jù) action 的類型來改變我們的 state
比如下面的 reduce,我們就用 switch 實(shí)現(xiàn)了分別對(duì) 添加方法 以及 刪除方法 的處理

這里其實(shí)相當(dāng)于就是廣播站站長很閑,專門針對(duì)觸發(fā)的事件做個(gè)歸類,然后在廣播站針對(duì)這些事件做一些處理。
最后也是導(dǎo)出一個(gè) Store 實(shí)例

只要這里的 state 發(fā)生了變化,那么就會(huì)通知到 view 里面去
View?

展示 stores 中的數(shù)據(jù)形態(tài)
可以是任何的前端框架(這里是?React)
和 Store 共享數(shù)據(jù)
下面介紹在 React 中如何監(jiān)聽到 state?變化并更新。
首先,通過 getInitialState 方法獲得初始值

在組件掛載后 componentDidMount 綁定監(jiān)聽函數(shù) addListener ,這個(gè)監(jiān)聽函數(shù)傳參是 state 變化后會(huì)執(zhí)行的方法。addListener?會(huì)返回一個(gè)函數(shù),這個(gè)函數(shù)在調(diào)用后會(huì)移除監(jiān)聽。
所以我們也會(huì)在 componentWillUnmount 里移除監(jiān)聽。
這里就很像是 發(fā)布-訂閱 機(jī)制里的訂閱機(jī)制了。

每次 Store 更新之后我們都需要重設(shè)組件的 state,用?getState 方法獲得最新的 state。

觸發(fā)指令事件的方法
剛剛我們引入了?Action
import Action from './action'
那么只需要調(diào)用對(duì)應(yīng)的方法即可。

最后嘗試執(zhí)行~

上面的例子,能夠總結(jié) flux 的特點(diǎn)。
中心化控制,改變通過 action 發(fā)出,由 dispatcher 分配
view 保持簡介,只需要關(guān)心傳進(jìn)的數(shù)據(jù)
數(shù)據(jù)始終保持單向流動(dòng)
本小節(jié)完畢,代碼如下
https://github.com/D1N910/learn-react/tree/master/Chapter4/demo-5-flux

本節(jié)最開心的還是學(xué)到了 發(fā)布-訂閱者?模式!
上面的內(nèi)容都是學(xué)習(xí)自 騰訊課堂 【NEXT】學(xué)院?一線大廠React實(shí)踐寶典?
個(gè)人學(xué)習(xí)筆記
本期的課后作業(yè)抄錄
給博客配置并且增加主題可選項(xiàng)
我們可以在博客的底部增加一些可點(diǎn)擊項(xiàng)目,從而讓我們的博客可以展示不同的主題:
增加 Show Tags | Hide Tags 可選項(xiàng),從而可以配置是否在首頁的博客列表展示博客的標(biāo)簽,在不展示標(biāo)簽的情況下,相同范圍內(nèi)可以顯示更多的博客條目。
增加 Pagination | No Pagination 可選項(xiàng),從而可以配置博客首頁文章列表是否分頁展示,由于我們的文章列表之前采用的是前端分頁,因此這方面的實(shí)現(xiàn)較為簡單。
在完成以上幾個(gè)可選項(xiàng)之后,大家可以按照相同的方式添加更多的可選項(xiàng),比如配置顏色、背景底紋、深淺主題等。
將博客主題可選項(xiàng)配置持久化
假設(shè)用戶選擇了我們提供的可選配置的能力,但是如果頁面一刷新又恢復(fù)如初,這樣的用戶體驗(yàn)顯然不佳,所以我們需要做的就是“記住”用戶選擇的配置,持久化存儲(chǔ)在瀏覽器里面,這樣當(dāng)用戶下次來訪問的時(shí)候,可以預(yù)先讀取用戶之前選擇的主題項(xiàng)目配置,并且依此展示。
這方面的實(shí)現(xiàn),我們可以采用瀏覽器提供的 Window.localStorage。
嘆氣
五一勞動(dòng)節(jié),五一、五二發(fā)爛渣 + 玩游戲
五三、五四、五五才開始繼續(xù)學(xué)習(xí)
所以現(xiàn)在還沒學(xué)完~
還剩下 4 個(gè)項(xiàng)目
不過~感覺收獲頗多!
剩下的,希望這周能夠完成吧 ?
加油,加油,加油
前路肯定苦難重重,無邊無際的地獄
熬夜的痛苦,肝的魔咒
頭發(fā)會(huì)沒有
幸福會(huì)沒有
但是還是喜歡這樣
這大概就是~
做好了喜歡你的準(zhǔn)備吧
感謝也很努力的你,喜歡你!
感謝 曾軼可 的 《獅子座》陪伴我寫完這最后一點(diǎn)點(diǎn)內(nèi)容
學(xué)習(xí)進(jìn)度( 5 / 9 )
from 蛋糕