Redux收尾
- reducer做一个拆解
- 拆分到对应的文件夹里面, 每个文件夹都有对应的4个文件
- 目录结构划分
- 实际项目会拆解的更细致
- combineReducers, redux提供的合并函数
const reducer = combineReducers({
counterInfo: counterReducer,
homeInfo: homeReducer
})
内部帮助执行.png
combineReducer的原理
image.png- 看源码
-
一点点的去读
源码.png - 返回值的本身又是一个函数
-
自己写的reducer函数有什么缺点? action没有改变任何数据, 最终返回的还是原来的state对象, 没有必要return一个新的对象
每次都会返回一个新的对象.png -
combineReduce帮我们做的一个操作, 又发生改变返回一个新的对象, 没有发生改变不返回新的对象
是否需要返回一个新的对象.png - 核心逻辑就是根据action去获取下个状态,然后进行比较
React中的state如何管理
-
三种方式
- 方式一: 组件中自己的state管理;
- 方式二: Context数据的共享状态;
- 方式三: Redux管理应用状态;
-
在开发中如何选择呢?
- 没有一个标准的答案, 官网也说了
- 某些用户, 选择将所有的状态放到Reduc中进行管理, 方便追踪共享;
- 某些用户, 选择将某些组件自己的状态放到组件内部进行管理;
- 某些用户, 将类似于主题、用户信息等数据放到Context中进行共享和管理;
-
作为一个开发者, 到底选择怎样的状态管理方式, 是开发者的工作之一
image.png
-
-
Redux的坐着给出的建议:
- 在区分到底如何选择的时候, 作者判断状态是否需要被多个组件或页面共享, 并且当路由发生改变的时候, 页面销毁, 有些状态可能需要被保存持久化. 对于这种数据, 作者认为需要被保存到redux中.
管理建议.png
- 在区分到底如何选择的时候, 作者判断状态是否需要被多个组件或页面共享, 并且当路由发生改变的时候, 页面销毁, 有些状态可能需要被保存持久化. 对于这种数据, 作者认为需要被保存到redux中.
-
coderwhy的建议:
-
UI相关的组件内部可以维护的状态, 在组建累不自己来维护; Loading的显示, isLoad = true; tabbar有三个选项, 用户点击操作, currentIndex = 1, 不需要进行共享, 交给组件自己管理
自己的组件进行维护.png
-
- 大部分是需要共享状态, 都交给redux来管理和维护;(并不是非常绝对的, 父子组件相互传递比较方便时自己管理)
- 从服务器请求的数据(包括请求的操作), 交给redux来维护;
-
根据不同的情况会进行适当的调整.
后续想要补充的东西
- 结合实际的项目补充
- Redux和ImmutableJS结合使用;
- 一些性能优化的知识;(防止组件动不动就发生刷新)
Redux回顾
- 纯函数, Redux的Reducer就是一个纯函数, (函数式编程)
- 为什么要使用Redux
- Redux核心理念, 三大原则
- Redux的基本使用, 自己搭建了一个简单项目
- Redux里面的目录结构进行一个拆分, node对ES6模块化的支持, node已经可以升级到12.x的版本了, 建议升级到LTS最新版本
- Redux流程图
- React结合Redux的使用, redux融入react代码里面
- 自定义connect函数, 返回一个高阶组件, 公共代码放到组件类里面, 之后通过map的方式告诉需要哪些事件
- context如何进行store共享, 原来直接导入store, 不好封装库
- => react-redux官方库, 直接使用封装好的Provider
- 异步操作, 中间件, redux-thunk, dispatch一个action函数
- devtools工具
- redux-saga, 补充generator, saga使用
- 中间件的原理, Monkey Patching修改dispatch
- Reducer的拆分, 通过封装的reducer, combineReducer
- React中的state到底如何管理的分析
- thunk用起来容易点用的多, saga可以传入一个函数
- 多练习, 项目中用起来
单向数据流
- 比较广的一个概念
- 数据的传递应该是一个单向的, 只能往一个方向传
- 三个地方看到过这个概念,
- React官方中有提到单向数据流, 组件之前数据的传递, 组件树, 数据在进行共享的时候只能从上往下传递, 像水流一样流到下面. 通过props进行数据的传递
-
Vue和React中组件内部都有单向数据流的概念; 在同一个组件里面, 有UI界面, 产生一个action, 有可能会修改State,
image.png -
Redux中, 一个固定的流程, 组件中发生事件, dispatch(action), 形成一个闭环, 整个过程中不能越级
不能越级.png
TransitionGroup的警告问题
-
在group的里面, button, in去除不需要加上去
image.png
消除警告.png
React-router的使用
路由的由来
-
映射关系, 路由表
i路由的由来.png - 编程里面路由的概念, 最早是后端里面, 前后端分离, 单页面富应用(SPA), 编程和建筑学
阶段一: 后端路由(渲染)阶段
- 早期的网站开发整个HTML页面是由服务器来渲染的.
- 服务器直接生产渲染好对应的HTML页面, 后面给客户端进行展示. (SEO优化, 爬虫静态页面, ssr(服务端渲染), 谷歌执行JavaScript代码帮助发送Ajax请求, 搜索结果)
- 但是, 一个网站, 这么多页面服务器如何处理呢?
- 一个页面有自己对应的网址, 也就是URL.
- URL会发送到服务器, 服务器会通过正则对该URL进行匹配, 并且最后交给一个Controller进行处理.
- Controller进行各种处理, 最终生成HTML或者数据, 返回给前端.
- 这就完成了一个IO操作.
-
服务端完成页面的渲染, 服务器端渲染(SSR) server side render.
后端路由, 服务端渲染.png
后端路由.png - 前后端分离, 解耦
阶段二: 前后端分离阶段
- 前端渲染的理解:
- 每次请求涉及到的静态资源都会从静态资源服务器获取;
- 这些资源包括HTML+CSS+JS, 然后在前端对这些请求回来的资源进行渲染;
- 需要注意的是, 客户端的每一次请求, 都会从静态资源服务器请求文件;
- 同时可以看到, 和之前的后端路由不同, 这时后端只是负责提供API了;
- restful接口规范, 后端提供接口文档, 不需要关注前端实现
-
这样后端不仅能给web端提供数据, 还能给iOS、安卓、PC提供支持
image.png
阶段三: 单页面富应用(SPA)
- 单页面富应用的理解:
- 单页面富应用的英文是single-page application, 简称SPA;
- 整个Web应用实际上只有一个页面, 当URL发生改变时, 并不会从服务器请求新的静态资源;
-
而是通过JavaScript监听URL的改变, 并且根据URL的不同区渲染新的页面;
image.png
-
-目前比较多的是处于第三个阶段, 单页面富应用
前端路由的原理
前端路由的核心:
- 改变URL, 但使页面不要进行强制刷新(a元素不行)
- 自己来监听URL的改变, 并且改变之后自己改变页面的内容
- URL后面跟上一个哈希值, 页面不会发生刷新, URL的哈希, 有一个缺点, 中间莫名多了一个#
- HTML5中的history模式修改URL
- 当监听到URL发生改变的时候, 自己决定显示什么内容
URL的hash
- URL的hash
- URL的hash也就是锚点(#), 本质上是改变window.location的href属性;
- 我们可以通过直接赋值location.href
window.addEventLIstener("hashchange", () => {
switch (location.hash) {
case: "#/home":
routerViewEl.innerHTML = "首页";
break;
case "#/about":
routerViewEl.innerHTML = "关于";
break;
default:
routertViewEl.innerHTML = "";
}
})
image.png
HTML5的history
-
history接口是HTML5新增的, 他有六种模式改变URL而不刷新页面
image.png
// 1. 获取reouter-view的DOM
const routerViewEl = document.getElementsByClassName("router-view")[0];
// 获取所有的a元素, 自己来监听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元素发生了点击");
history.pushState({}, "", href);
})
}
// 执行返回操作时, 依然来到urlChange
window.addEventListener("popState", urlChange);
// window.addEventListener("go", urlChange);// 手动执行go时监听
// 监听URL的改变
function urlChange() {
switch (location.pathname) {
case: "/home":
routerViewEl.innerHTML = "首页";
break;
case "/about":
routerViewEl.innerHTML = "关于";
break;
default:
routertViewEl.innerHTML = "";
}
}
image.png
react-router
- 目前前端流行的三大框架, 都有自己的路由实现:
- Angular的ngRouter
- React的react-router
- Vue的vue-router
- React Router的版本4开始, 路由不再集中在一个包中进行管理了:
- react-router是router的核心部分代码;
- react-router-dom是用于浏览器的;
- react-router-native是用于原生应用的;
- 目前我们使用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" >关于</Link>
<Link to="/profile" >我的</Link>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/profile" component={Profile} />
</HashRouter>
网友评论