摘要:高階組件以下的所有子組件都可以直接從中獲取數(shù)據(jù)。所以,修改數(shù)據(jù)的函數(shù)出現(xiàn)了即所有的數(shù)據(jù)都必須通過調(diào)用修改。
redux 只是一個狀態(tài)管理 簡述
本篇文章主要說明redux的基本原理以及如何使用
閱讀前需了解(本文中僅作簡單描述,詳細(xì)了解請自行Google)
純函數(shù)
符合以下兩點性質(zhì)的函數(shù)即為純函數(shù)
函數(shù)執(zhí)行不改變外部變量
函數(shù)的輸出結(jié)果僅依賴于輸入?yún)?shù)
高階組件
即一個函數(shù),接收一個組件作為參數(shù),輸出一個新組件
觀察者模式
即發(fā)布訂閱模式,可以理解為給一個事件綁定多個函數(shù),事件觸發(fā)時多個綁定函數(shù)全部執(zhí)行
react基礎(chǔ)
react官方中文文檔
wepy基礎(chǔ)(有vue基礎(chǔ)也可以)
wepy官方文檔
redux react中的context屬性簡單的說,context就是一個全局變量,它可以被一個高階組件及該高階組件的所有子組件,孫組建等等共享
舉個例子,下圖是一個react頁面react頁面樹形結(jié)構(gòu)
正常的狀態(tài)提升及數(shù)據(jù)下放
使用context的樹形結(jié)構(gòu)
由上面三圖可以看出,本應(yīng)一層一層傳遞的數(shù)據(jù),在使用context后,變得方便了。
高階組件以下的所有子組件都可以直接從context中獲取數(shù)據(jù)。
這看似方便的方法,實際上引發(fā)了一個老生常談的問題,即全局變量控制問題
context 里面的數(shù)據(jù)能被隨意接觸就能被隨意修改,每個組件都能夠改 context 里面的內(nèi)容會導(dǎo)致程序的運(yùn)行不可預(yù)料
同時context的出現(xiàn)也打破了組件和組件之間通過 props 傳遞數(shù)據(jù)的規(guī)范,極大地增強(qiáng)了組件之間的耦合性。
試想,若是所有組件都可以通過xxx="xxx"來修改狀態(tài),我們獲取并控制當(dāng)前狀態(tài)的難度是否變大?
在大型復(fù)雜項目中,我們可能都無法確定某數(shù)據(jù)是如何變成當(dāng)前值的
為了避免這種情況出現(xiàn),redux就出現(xiàn)了
為了解決模塊(組件)之間需要共享數(shù)據(jù)和數(shù)據(jù)可能被任意修改導(dǎo)致不可預(yù)料的結(jié)果時間的矛盾,
redux團(tuán)隊想出了一個辦法,即把事情搞復(fù)雜一些,提高數(shù)據(jù)修改的門檻:模塊(組件)之間可以共享數(shù)據(jù),也可以改數(shù)據(jù)。但是我們約定,這個數(shù)據(jù)并不能直接改,你只能執(zhí)行某些我允許的某些修改,而且你修改的必須大張旗鼓地告訴我。
function dispatch (action) { switch (action.type) { case "UPDATE_TITLE_TEXT": appState.title.text = action.text break case "UPDATE_TITLE_COLOR": appState.title.color = action.color break default: break } }
即所有的數(shù)據(jù)都必須通過調(diào)用dispatch修改。
dispatch({ type: "UPDATE_TITLE_TEXT", text: "hello world" }) // 修改標(biāo)題文本 dispatch({ type: "UPDATE_TITLE_COLOR", color: "blue" }) // 修改標(biāo)題顏色如圖所示
引入redux前,各組件直接修改數(shù)據(jù)
現(xiàn)在,必須通過dispatch修改數(shù)據(jù)
抽離store并監(jiān)控數(shù)據(jù)變化我們把它們集中到一個地方,給這個地方起個名字叫做 store,然后構(gòu)建一個函數(shù) createStore,用來專門生產(chǎn)這種 state 和 dispatch 的集合,這樣別的 App 也可以用這種模式了:
/** *@param *state 初始狀態(tài) *stateChanger 一個修改state的函數(shù) */ function createStore (state, stateChanger) { const getState = () => state const dispatch = (action) => stateChanger(state, action) return { getState, dispatch } }
本例中頁面通過renderApp等函數(shù)刷新,為了避免dispatch后頁面數(shù)據(jù)不變化(render函數(shù)不執(zhí)行)
我們必須引入觀察者模式,使dispatch后,app自動執(zhí)行render函數(shù)
function createStore (state, stateChanger) { const listeners = [] const subscribe = (listener) => listeners.push(listener) const getState = () => state const dispatch = (action) => { stateChanger(state, action) listeners.forEach((listener) => listener()) } return { getState, dispatch, subscribe } } function renderApp (appState) { renderTitle(appState.title) renderContent(appState.content) } function renderTitle (title) { const titleDOM = document.getElementById("title") titleDOM.innerHTML = title.text titleDOM.style.color = title.color } function renderContent (content) { const contentDOM = document.getElementById("content") contentDOM.innerHTML = content.text contentDOM.style.color = content.color } let appState = { title: { text: "React.js 小書", color: "red", }, content: { text: "React.js 小書內(nèi)容", color: "blue" } } function stateChanger (state, action) { switch (action.type) { case "UPDATE_TITLE_TEXT": state.title.text = action.text break case "UPDATE_TITLE_COLOR": state.title.color = action.color break default: break } } const store = createStore(appState, stateChanger) store.subscribe(() => renderApp(store.getState())) // 監(jiān)聽數(shù)據(jù)變化 renderApp(store.getState()) // 首次渲染頁面 store.dispatch({ type: "UPDATE_TITLE_TEXT", text: "《React.js 小書》" }) // 修改標(biāo)題文本 store.dispatch({ type: "UPDATE_TITLE_COLOR", color: "blue" }) // 修改標(biāo)題顏色
至此,我們已經(jīng)大概構(gòu)建了一個redux的骨架,接下來我們將完善它
嚴(yán)重的性能問題不知道讀者有沒有發(fā)現(xiàn),當(dāng)我們通過dispatch修改標(biāo)題的文字時,整個App就會刷新一次,
當(dāng)我們修改文本的顏色時,整個App也會刷新一次,這樣就頻繁的全部刷新就造成了極大的性能問題
那么,能否修改title,僅刷新title;修改content,也僅刷新content呢?
我們使render函數(shù)接收2個參數(shù)(newState, oldState = {})并且在刷新前進(jìn)行比較
function renderApp (newAppState, oldAppState = {}) { // 防止 oldAppState 沒有傳入,所以加了默認(rèn)參數(shù) oldAppState = {} if (newAppState === oldAppState) return // 數(shù)據(jù)沒有變化就不渲染了 console.log("render app...") renderTitle(newAppState.title, oldAppState.title) renderContent(newAppState.content, oldAppState.content) } function renderTitle (newTitle, oldTitle = {}) { if (newTitle === oldTitle) return // 數(shù)據(jù)沒有變化就不渲染了 console.log("render title...") const titleDOM = document.getElementById("title") titleDOM.innerHTML = newTitle.text titleDOM.style.color = newTitle.color } function renderContent (newContent, oldContent = {}) { if (newContent === oldContent) return // 數(shù)據(jù)沒有變化就不渲染了 console.log("render content...") const contentDOM = document.getElementById("content") contentDOM.innerHTML = newContent.text contentDOM.style.color = newContent.color }
這樣就可以提高性能了吧,每次只刷新需要刷新部分啦~~
才怪!
我們確實修改了對象內(nèi)的屬性值,但是newState和oldState所指的不還是一個對象嗎?
所以為了進(jìn)行判斷,我們還要修改前面的stateChanger函數(shù)
function stateChanger (state, action) { switch (action.type) { case "UPDATE_TITLE_TEXT": return { // 構(gòu)建新的對象并且返回 ...state, title: { ...state.title, text: action.text } } case "UPDATE_TITLE_COLOR": return { // 構(gòu)建新的對象并且返回 ...state, title: { ...state.title, color: action.color } } default: return state // 沒有修改,返回原來的對象 } }
現(xiàn)在我們才真正提高了性能
reduer為了讓程序的結(jié)構(gòu)更加清晰,我們把原始state放入stateChanger中,并把stateChanger改名為reducer
為什么叫redcer? 別問為什么,沒有理由!
function reducer (state, action) { if (!state) { return { title: { text: "hello world", color: "red", }, content: { text: "hello world content", color: "blue" } } } switch (action.type) { case "UPDATE_TITLE_TEXT": return { ...state, title: { ...state.title, text: action.text } } case "UPDATE_TITLE_COLOR": return { ...state, title: { ...state.title, color: action.color } } default: return state } }總結(jié)
現(xiàn)在的代碼和react,wepy關(guān)系都不大,在下一篇文章中,我會講述如何具體地在react中使用redux
感謝 @胡子大哈 老師的《react小書》,本章有很多代碼都是摘自該書
react小書
全部代碼make-redux
本文如果有錯,歡迎指出
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/100205.html
摘要:和的結(jié)合簡述相信很多前端開發(fā)者都聽說或使用過,我曾寫過一篇關(guān)于快速理解的文章,雖說是快速理解,但實際上更應(yīng)該叫做復(fù)習(xí)吧。它通過高階函數(shù),純函數(shù)使我們在編寫組件時完全不用接觸相關(guān)內(nèi)容,只通過將組件和數(shù)據(jù)連接起來即可。 react-redux react和redux的結(jié)合 簡述 相信很多前端開發(fā)者都聽說或使用過react-redux,我曾寫過一篇關(guān)于快速理解redux的文章,雖說是快...
摘要:深入簡述在快速理解中,我簡單的介紹了的基礎(chǔ)內(nèi)容,本篇文章中,我們將再度深入。二修改我曾在快速理解中提起,為了解決模塊組件之間需要共享數(shù)據(jù)和數(shù)據(jù)可能被任意修改導(dǎo)致不可預(yù)料的結(jié)果的矛盾,團(tuán)隊創(chuàng)建了。 深入Redux 簡述 在快速理解redux中,我簡單的介紹了redux的基礎(chǔ)內(nèi)容,本篇文章中,我們將再度深入redux。 redux解決的問題 數(shù)據(jù)和函數(shù)的層層傳遞 多個組件同時修改某全局變...
摘要:協(xié)調(diào)狀態(tài)的這三個方面是前端開發(fā)的重要組成部分,對這項任務(wù)有不同程度的支持。這使得保持高度統(tǒng)一。的真正威力到目前為止,看上去只是的輔助工具。在的術(shù)語中這稱之為派發(fā)動作。撤銷重做流行的撤銷重做功能需要系統(tǒng)級規(guī)劃。 想閱讀更多優(yōu)質(zhì)文章請猛戳GitHub博客,一年百來篇優(yōu)質(zhì)文章等著你! 你知道 Redux 真正的作用遠(yuǎn)不止?fàn)顟B(tài)管理嗎? 你是否想要了解 Redux 的工作原理? 讓我們深入研究 ...
摘要:相關(guān)配置請參考中文文檔。關(guān)于的更多使用方法及理解需要詳細(xì)具體講解,涉及篇幅較大,本文暫不涉及,有興趣可以看文檔中文文檔,我會整理后再單獨(dú)章節(jié)分享接下來我們將編寫路由組件這與有一些差別,原來的方法已經(jīng)不再使用,在中或組件從中引入。 ??????相信很多剛?cè)肟覴eact的小伙伴們有一個同樣的疑惑,由于React相關(guān)庫不斷的再進(jìn)行版本迭代,網(wǎng)上很多以前的技術(shù)分享變得不再適用。比如react-...
摘要:基礎(chǔ)瀏覽器渲染機(jī)制水平居中垂直居中數(shù)組的幾個方法對比閉包作用域原型與原型鏈繼承的介紹事件冒泡與捕獲只支持事件冒泡不支持事件捕獲,如何在上實現(xiàn)事件捕獲運(yùn)行機(jī)制相關(guān)介紹你經(jīng)常用到的的新特性方法網(wǎng)絡(luò)請求響應(yīng)分別有哪些頭字段,有什么作用緩存相關(guān)響 基礎(chǔ) 瀏覽器渲染機(jī)制 CSS 水平居中、垂直居中BFC 數(shù)組的幾個方法對比閉包作用域this原型與原型鏈、繼承的介紹事件冒泡與捕獲(IE6只支持事件...
閱讀 2776·2021-10-11 11:08
閱讀 1496·2021-09-30 09:48
閱讀 1055·2021-09-22 15:29
閱讀 1042·2019-08-30 15:54
閱讀 985·2019-08-29 15:19
閱讀 534·2019-08-29 13:12
閱讀 3168·2019-08-26 13:53
閱讀 966·2019-08-26 13:28