Redux收尾
- reducer做一個拆解
- 拆分到對應(yīng)的文件夾里面, 每個文件夾都有對應(yīng)的4個文件
- 目錄結(jié)構(gòu)劃分
- 實際項目會拆解的更細致
- combineReducers, redux提供的合并函數(shù)
const reducer = combineReducers({
counterInfo: counterReducer,
homeInfo: homeReducer
})

combineReducer的原理

- 看源碼
-
一點點的去讀
源碼.png - 返回值的本身又是一個函數(shù)
-
自己寫的reducer函數(shù)有什么缺點? action沒有改變?nèi)魏螖?shù)據(jù), 最終返回的還是原來的state對象, 沒有必要return一個新的對象
每次都會返回一個新的對象.png -
combineReduce幫我們做的一個操作, 又發(fā)生改變返回一個新的對象, 沒有發(fā)生改變不返回新的對象
是否需要返回一個新的對象.png - 核心邏輯就是根據(jù)action去獲取下個狀態(tài),然后進行比較
React中的state如何管理
三種方式
- 方式一: 組件中自己的state管理;
- 方式二: Context數(shù)據(jù)的共享狀態(tài);
- 方式三: Redux管理應(yīng)用狀態(tài);
在開發(fā)中如何選擇呢?
- 沒有一個標準的答案, 官網(wǎng)也說了
- 某些用戶, 選擇將所有的狀態(tài)放到Reduc中進行管理, 方便追蹤共享;
- 某些用戶, 選擇將某些組件自己的狀態(tài)放到組件內(nèi)部進行管理;
- 某些用戶, 將類似于主題、用戶信息等數(shù)據(jù)放到Context中進行共享和管理;
-
作為一個開發(fā)者, 到底選擇怎樣的狀態(tài)管理方式, 是開發(fā)者的工作之一
image.png
-
Redux的坐著給出的建議:
- 在區(qū)分到底如何選擇的時候, 作者判斷狀態(tài)是否需要被多個組件或頁面共享, 并且當路由發(fā)生改變的時候, 頁面銷毀, 有些狀態(tài)可能需要被保存持久化. 對于這種數(shù)據(jù), 作者認為需要被保存到redux中.
管理建議.png
- 在區(qū)分到底如何選擇的時候, 作者判斷狀態(tài)是否需要被多個組件或頁面共享, 并且當路由發(fā)生改變的時候, 頁面銷毀, 有些狀態(tài)可能需要被保存持久化. 對于這種數(shù)據(jù), 作者認為需要被保存到redux中.
coderwhy的建議:
-
UI相關(guān)的組件內(nèi)部可以維護的狀態(tài), 在組建累不自己來維護; Loading的顯示, isLoad = true; tabbar有三個選項, 用戶點擊操作, currentIndex = 1, 不需要進行共享, 交給組件自己管理
自己的組件進行維護.png
-
- 大部分是需要共享狀態(tài), 都交給redux來管理和維護;(并不是非常絕對的, 父子組件相互傳遞比較方便時自己管理)
- 從服務(wù)器請求的數(shù)據(jù)(包括請求的操作), 交給redux來維護;
根據(jù)不同的情況會進行適當?shù)恼{(diào)整.
后續(xù)想要補充的東西
- 結(jié)合實際的項目補充
- Redux和ImmutableJS結(jié)合使用;
- 一些性能優(yōu)化的知識;(防止組件動不動就發(fā)生刷新)
Redux回顧
- 純函數(shù), Redux的Reducer就是一個純函數(shù), (函數(shù)式編程)
- 為什么要使用Redux
- Redux核心理念, 三大原則
- Redux的基本使用, 自己搭建了一個簡單項目
- Redux里面的目錄結(jié)構(gòu)進行一個拆分, node對ES6模塊化的支持, node已經(jīng)可以升級到12.x的版本了, 建議升級到LTS最新版本
- Redux流程圖
- React結(jié)合Redux的使用, redux融入react代碼里面
- 自定義connect函數(shù), 返回一個高階組件, 公共代碼放到組件類里面, 之后通過map的方式告訴需要哪些事件
- context如何進行store共享, 原來直接導(dǎo)入store, 不好封裝庫
- => react-redux官方庫, 直接使用封裝好的Provider
- 異步操作, 中間件, redux-thunk, dispatch一個action函數(shù)
- devtools工具
- redux-saga, 補充generator, saga使用
- 中間件的原理, Monkey Patching修改dispatch
- Reducer的拆分, 通過封裝的reducer, combineReducer
- React中的state到底如何管理的分析
- thunk用起來容易點用的多, saga可以傳入一個函數(shù)
- 多練習, 項目中用起來
單向數(shù)據(jù)流
- 比較廣的一個概念
- 數(shù)據(jù)的傳遞應(yīng)該是一個單向的, 只能往一個方向傳
- 三個地方看到過這個概念,
- React官方中有提到單向數(shù)據(jù)流, 組件之前數(shù)據(jù)的傳遞, 組件樹, 數(shù)據(jù)在進行共享的時候只能從上往下傳遞, 像水流一樣流到下面. 通過props進行數(shù)據(jù)的傳遞
-
Vue和React中組件內(nèi)部都有單向數(shù)據(jù)流的概念; 在同一個組件里面, 有UI界面, 產(chǎn)生一個action, 有可能會修改State,
image.png -
Redux中, 一個固定的流程, 組件中發(fā)生事件, dispatch(action), 形成一個閉環(huán), 整個過程中不能越級
不能越級.png
TransitionGroup的警告問題
-
在group的里面, button, in去除不需要加上去
image.png
消除警告.png
React-router的使用
路由的由來
-
映射關(guān)系, 路由表
i路由的由來.png - 編程里面路由的概念, 最早是后端里面, 前后端分離, 單頁面富應(yīng)用(SPA), 編程和建筑學
階段一: 后端路由(渲染)階段
- 早期的網(wǎng)站開發(fā)整個HTML頁面是由服務(wù)器來渲染的.
- 服務(wù)器直接生產(chǎn)渲染好對應(yīng)的HTML頁面, 后面給客戶端進行展示. (SEO優(yōu)化, 爬蟲靜態(tài)頁面, ssr(服務(wù)端渲染), 谷歌執(zhí)行JavaScript代碼幫助發(fā)送Ajax請求, 搜索結(jié)果)
- 但是, 一個網(wǎng)站, 這么多頁面服務(wù)器如何處理呢?
- 一個頁面有自己對應(yīng)的網(wǎng)址, 也就是URL.
- URL會發(fā)送到服務(wù)器, 服務(wù)器會通過正則對該URL進行匹配, 并且最后交給一個Controller進行處理.
- Controller進行各種處理, 最終生成HTML或者數(shù)據(jù), 返回給前端.
- 這就完成了一個IO操作.
-
服務(wù)端完成頁面的渲染, 服務(wù)器端渲染(SSR) server side render.
后端路由, 服務(wù)端渲染.png
后端路由.png - 前后端分離, 解耦
階段二: 前后端分離階段
- 前端渲染的理解:
- 每次請求涉及到的靜態(tài)資源都會從靜態(tài)資源服務(wù)器獲取;
- 這些資源包括HTML+CSS+JS, 然后在前端對這些請求回來的資源進行渲染;
- 需要注意的是, 客戶端的每一次請求, 都會從靜態(tài)資源服務(wù)器請求文件;
- 同時可以看到, 和之前的后端路由不同, 這時后端只是負責提供API了;
- restful接口規(guī)范, 后端提供接口文檔, 不需要關(guān)注前端實現(xiàn)
-
這樣后端不僅能給web端提供數(shù)據(jù), 還能給iOS、安卓、PC提供支持
image.png
階段三: 單頁面富應(yīng)用(SPA)
- 單頁面富應(yīng)用的理解:
- 單頁面富應(yīng)用的英文是single-page application, 簡稱SPA;
- 整個Web應(yīng)用實際上只有一個頁面, 當URL發(fā)生改變時, 并不會從服務(wù)器請求新的靜態(tài)資源;
-
而是通過JavaScript監(jiān)聽URL的改變, 并且根據(jù)URL的不同區(qū)渲染新的頁面;
image.png
-

-目前比較多的是處于第三個階段, 單頁面富應(yīng)用
前端路由的原理
前端路由的核心:
- 改變URL, 但使頁面不要進行強制刷新(a元素不行)
- 自己來監(jiān)聽URL的改變, 并且改變之后自己改變頁面的內(nèi)容
- URL后面跟上一個哈希值, 頁面不會發(fā)生刷新, URL的哈希, 有一個缺點, 中間莫名多了一個#
- HTML5中的history模式修改URL
- 當監(jiān)聽到URL發(fā)生改變的時候, 自己決定顯示什么內(nèi)容
URL的hash
- URL的hash
- URL的hash也就是錨點(#), 本質(zhì)上是改變window.location的href屬性;
- 我們可以通過直接賦值location.href
window.addEventLIstener("hashchange", () => {
switch (location.hash) {
case: "#/home":
routerViewEl.innerHTML = "首頁";
break;
case "#/about":
routerViewEl.innerHTML = "關(guān)于";
break;
default:
routertViewEl.innerHTML = "";
}
})

HTML5的history
-
history接口是HTML5新增的, 他有六種模式改變URL而不刷新頁面
image.png
// 1. 獲取reouter-view的DOM
const routerViewEl = document.getElementsByClassName("router-view")[0];
// 獲取所有的a元素, 自己來監(jiān)聽a元素的改變
const aEls = document.getElementsByTagName("a");
for (let el of aEls) {
el.addEventListener("click", e => {
e.preventDefault();
const href = el.getAttribute("href");
console.log("a元素發(fā)生了點擊");
history.pushState({}, "", href);
})
}
// 執(zhí)行返回操作時, 依然來到urlChange
window.addEventListener("popState", urlChange);
// window.addEventListener("go", urlChange);// 手動執(zhí)行g(shù)o時監(jiān)聽
// 監(jiān)聽URL的改變
function urlChange() {
switch (location.pathname) {
case: "/home":
routerViewEl.innerHTML = "首頁";
break;
case "/about":
routerViewEl.innerHTML = "關(guān)于";
break;
default:
routertViewEl.innerHTML = "";
}
}

react-router
- 目前前端流行的三大框架, 都有自己的路由實現(xiàn):
- Angular的ngRouter
- React的react-router
- Vue的vue-router
- React Router的版本4開始, 路由不再集中在一個包中進行管理了:
- react-router是router的核心部分代碼;
- react-router-dom是用于瀏覽器的;
- react-router-native是用于原生應(yīng)用的;
- 目前我們使用React Router最新的版本是v5的版本:
- 實際上v4的版本和v5的版本差異不大;(寫錯了一個版本依賴, 直接升級了)
- 安裝react-router:
- 安裝dom會自動幫助我們安裝react-router的依賴
yarn add react-router-dom
- 安裝dom會自動幫助我們安裝react-router的依賴
Router的基本使用
- react-router最主要的API是給我們提供的一些組件:
- BrowserRouter或HashRouter:
- Link和NavLink:
-
Route:
image.png
-
<HashRouter>
<Link to="/" >首頁</Link>
<Link to="/about" >關(guān)于</Link>
<Link to="/profile" >我的</Link>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/profile" component={Profile} />
</HashRouter>
coderwhy的React核心技術(shù)與開發(fā)實戰(zhàn)課程鏈接

















