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