# react例子
**Repository Path**: huatree/react-examples
## Basic Information
- **Project Name**: react例子
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 1
- **Forks**: 0
- **Created**: 2021-04-11
- **Last Updated**: 2022-05-11
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# react-examples
> wyh | 2021-04-11
**说明:**
通过重命名替换为`src`即可使用对应的项目案例,因为封装的 webpack 默认配置机制。以下例子都是基于create-react-app脚手架编写的。
## 00 src
creat-react-app 创建的原始文件
## 01 纯 react 版
## 02 redux 精简版
1. 去除 Count 组件自身的状态
2. src 下建立:
```js
- redux
- store.js
- count_reducer.js
```
3. store.js:
1).引入 redux 中的 createStore 函数,创建一个 store
2).createStore 调用时要传入一个为其服务的 reducer
3).记得暴露 store 对象
4. count_reducer.js:
- 1).reducer 的本质是一个函数,接收:preState,action,返回加工后的状态
- 2).reducer 有两个作用:初始化状态,加工状态
- 3).reducer 被第一次调用时,是 store 自动触发的
传递的 preState 是 undefined,
传递的 action 是:{type:'@@REDUX/INIT_a.2.b.4}
5. 在 index.js 中监测 store 中状态的改变,一旦发生改变重新渲染``
备注:redux 只负责管理状态,至于状态的改变驱动着页面的展示,要靠我们自己写。
## 03 redux 完整版
新增文件:
1.countAction.js 专门用于创建 action 对象
2.constant.js 放置容易写错的 type 值
## 04 redux 异步 acton 版
1. 明确:延迟的动作不想交给组件自身,想交给 action
2. 何时需要异步 action:想要对状态进行操作,但是具体的数据靠异步任务返回。
3. 具体编码:
- 1).yarn add redux-thunk,并配置在 store 中
- 2).创建 action 的函数不再返回一般对象,而是一个函数,该函数中写异步任务。
- 3).异步任务有结果后,分发一个同步的 action 去真正操作数据。
4. 备注:异步 action 不是必须要写的,完全可以自己等待异步任务的结果了再去分发同步 action。
## 05 react-redux 基础版
1. 明确两个概念:
- 1).UI 组件:不能使用任何 redux 的 api,只负责页面的呈现、交互等。
- 2).容器组件:负责和 redux 通信,将结果交给 UI 组件。
2. 如何创建一个容器组件————靠 react-redux 的 connect 函数
connect(mapStateToProps,mapDispatchToProps)(UI 组件)
-mapStateToProps:映射状态,返回值是一个对象
-mapDispatchToProps:映射操作状态的方法,返回值是一个对象
3. 备注 1:容器组件中的 store 是靠 props 传进去的,而不是在容器组件中直接引入
4. 备注 2:mapDispatchToProps,也可以是一个对象
## 06 react-redux 优化版
1. 容器组件和 UI 组件整合一个文件
2. 无需自己给容器组件传递 store,给``包裹一个``即可。
3. 使用了 react-redux 后也不用再自己检测 redux 中状态的改变了,容器组件可以自动完成这个工作。
4. mapDispatchToProps 也可以简单的写成一个对象
5. 一个组件要和 redux“打交道”要经过哪几步?
- 1).定义好 UI 组件---不暴露
- 2).引入 connect 生成一个容器组件,并暴露,写法如下:
```jsx
connect(
state => ({key:value}), //映射状态
{key:xxxxxAction} //映射操作状态的方法
)(UI 组件)
```
- 3).在UI组件中通过this.props.xxxxxxx读取和操作状态
## 07 react-redux 数据共享版
1. 定义一个 Pserson 组件,和 Count 组件通过 redux 共享数据。
2. 为 Person 组件编写:reducer、action,配置 constant 常量。
3. 重点:Person 的 reducer 和 Count 的 Reducer 要使用 combineReducers 进行合并,
合并后的总状态是一个对象!!!
4. 交给 store 的是总 reducer,最后注意在组件中取出状态的时候,记得“取到位”。
## 08 react-redux 开发者工具的使用
1. yarn add redux-devtools-extension
2. store 中进行配置
```js
import {composeWithDevTools} from 'redux-devtools-extension'
const store = createStore(allReducer,composeWithDevTools(applyMiddleware(thunk)))
```
## 09 react-redux 最终版
1. 所有变量名字要规范,尽量触发对象的简写形式。
2. reducers 文件夹中,编写 index.js 专门用于汇总并暴露所有的 reducer
**注意**:打包测试的话,以可用 serve 运行打包后的文件
```bash
yarn add serve -g
# create-react-app脚手架创建的项目,打包的目录默认为build
yarn serve ./build
```
## 10 route原理
> 2021-04-15
## 11 react-router-dom的基本使用
> 2021-04-15
react-route官方给出了三种:web、native、any。react-router-dom即为web类型。
> 2021-04-17
- 路由组件与一般组件
1. 写法不同:
一般组件:``
路由组件:``
2. 存放位置不同:
一般组件:components
路由组件:pages
3. 接收到的props不同:
一般组件:写组件标签时传递了什么,就能收到什么
路由组件:接收到三个固定的属性
```js
history:
go: ƒ go(n)
goBack: ƒ goBack()
goForward: ƒ goForward()
push: ƒ push(path, state)
replace: ƒ replace(path, state)
location:
pathname: "/about"
search: ""
state: undefined
match:
params: {}
path: "/about"
url: "/about"
```
## 12 NavLink的使用
> 2021-04-17
NavLink可以实现路由链接的高亮,通过activeClassName指定样式名
## 13 封装NavLink
> 2021-04-17
注意:`props.children`的简写方式
## 14 Switch的使用
> 2021-04-17
1. 通常情况下,path和component是一一对应的关系。
2. Switch可以提高路由匹配效率(单一匹配)。
## 15 模糊匹配与精准匹配
> 2021-04-17
1. 默认使用的是模糊匹配(简单记:【输入的路径】必须包含要【匹配的路径】,且顺序要一致)
2. 开启严格匹配:``
3. 严格匹配不要随便开启,需要再开,有些时候开启会导致无法继续匹配二级路由
## 16 Redirect重定向
> 2021-04-17
一般写在所有路由注册的最下方,当所有路由都无法匹配时,跳转到Redirect指定的路由
## 17 嵌套路由
> 2021-04-17
1. 注册子路由时要写上父路由的path值
2. 路由的匹配是按照注册路由的顺序进行的
## 18-20 路由组件传参
> 2021-04-17
1. params参数(地址栏带参)
路由链接(携带参数):`详情`
注册路由(声明接收):``
接收参数:props.match.params
2. search参数(地址栏带参)
路由链接(携带参数):`详情`
注册路由(无需声明,正常注册即可):``
接收参数:this.props.location.search
备注:获取到的search是urlencoded编码字符串,需要借助querystring解析
3. state参数(地址栏无参)
路由链接(携带参数):`详情`
注册路由(无需声明,正常注册即可):``
接收参数:this.props.location.state
备注:虽然地址栏没显示参数,但是刷新也可以保留住参数
## 21-23 编程式路由导航及withRouter
> 2021-04-17
借助this.prosp.history对象上的API对操作路由跳转、前进、后退
- this.prosp.history.push()
- this.prosp.history.replace()
- this.prosp.history.goBack()
- this.prosp.history.goForward()
- this.prosp.history.go()
## 24 BrowserRouter与HashRouter的区别
> 2021-04-17
1. 底层原理不一样:
BrowserRouter使用的是H5的history API,不兼容IE9及以下版本。
HashRouter使用的是URL的哈希值。
2. path表现形式不一样
BrowserRouter的路径中没有#,例如:localhost:3000/demo/test
HashRouter的路径包含#,例如:localhost:3000/#/demo/test
3. 刷新后对路由state参数的影响
BrowserRouter没有任何影响,因为state保存在history对象中。
HashRouter刷新后会导致路由state参数的丢失!!!
4. 备注:HashRouter可以用于解决一些路径错误相关的问题。如public的css样式丢失。
## 25 路由菜单遍历选中高亮及刷新不变
> 2021-04-18
**需求:**
1. 自定义菜单布局
2. 第一层菜单无路由配置,第二层菜单有路由
3. 选中第一层菜单,及第二层菜单高亮显示
4. 刷新页面,选中的显示状态不变
5. 前进、后退第一层菜单与第二层保持一致状态