# react_demo **Repository Path**: ren_yizhong/react_demo ## Basic Information - **Project Name**: react_demo - **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-06-08 - **Last Updated**: 2021-07-06 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README 1. link为跳转标签 2. Route为放置路由组件的壳子 3. BrowserRouter 包起整个app组件用于app内部的切换 4. 路由组件与普通组件的区别 1. 写法不同 一般组件: 路由组件: 2. 存放位置不同 一般组件:components 路由组件:pages 3. 接收到的信息不同 一般组件:传递什么接收什么 路由组件:props会有一个对象 5. navlink 与 link 的区别 1. navlink在切换时默认会加上active类 如果想防止类冲突 可以使用 activeClassName="xxx" 来使用选中时使用自己的类 6.Switch 用于匹配相对应标签 如果其中路由组件有重用的路由名 则匹配第一个路由组件 7.exact 放到Route标签中 用于严格匹配 用于场景 不出问题不用 8.Redirect 重定向路由 9.嵌套路由 1.注册子路由时要写上父路由的path值 2.路由的匹配是按照注册路由的顺序决定的 10. params 传参数 路由链接(携带参数): {v.title} 注册路由(声明参数): 接收参数 this.props.match.params.XXX 11. search参数 路由链接(携带参数): {v.title} 注册路由(无需声明): 需要引入 import qs from 'querystring' 接收参数 let {XXX,XXX} = qs.parse(this.props.location.search.slice(1)) 11. search参数 路由链接(携带参数): {v.title} 注册路由(无需声明): 接收参数 let {title,id} = this.props.location.state 备注:刷新也会保留参数 12. 路由跳转不留下痕迹直接把 replace 写到 Link中,默认为push模式 13. 编程式路由导航 借助this.props.history对象上的API对操作路由跳转、前进、后退 this,props.history.push('path',{data}) this,props.history.replace('path/data/data') this,props.history.goback 返回上一步 this,props.history.goforward() 前进一步 this,props.history.go(number) number = 1前进 number = -1 后退 14. import {withRouter} from 'react-router-dom' withRouter(XXX组件) 加工一般组件使其拥有路由组件的三个对象属性 15. BrowserRouter 与 HashRouter 的区别 1. BrowserRouter 使用的是H5的history API 不兼容IE9以下版本 HashRouter 使用的是URL的哈希值 2. url表现形式不一样 BrowserRouter 使用的是H5的history路径中没有 # 例如 localhost:8080/ace/ace HashRouter 的路径中包含# 例如 localhost:8080/#/ace/ace 3. 刷新后对state传参的影响 BrowserRouter 没有任何影响,因为state保存在history对象中 HashRouter 刷新后会导致state丢失 4. 备注:HashRouterh 可以解决一些路径错误相关的问题 16. 精简版求和案例 1. 去除Count组件自身的状态 2. src下建立 -redux -stroe.js -count_reducer.js 3. store.js 1- 引入redux中得createStore函数,创建一个store 2- createStore调用时要传入一个为其服务的reducer 3- 记得暴露store对象 4. count_reducer.js 1- reducer的本质是一个函数,接收:preStore,action 返回加工后的状态 2- reducer 有两个作用:初始化状态,加工状态 3- reducer 被第一次调用时,是store自动触发的,传递的preStore是undifind 5. 在index.js中检测store中状态的改变,一旦发生改变重新渲染app 备注:redux只负责管理状态,至于状态的改变驱动页面的显示,需要自行手动 this.forUpdate强刷新或者其他方式 17. 完整版增加了俩个文件 1. count_action.js 专门用于创建action对象 2. constant.js 放置编码中容易写错action中的type 18. redux异步的aciton 1. 明确延迟的动作不想交给组件自身,想交给action 2. 何时需要异步action 想要对状态进行操作,但是具体的数据靠异步任务返回(非必须) 3. 安装 npm i redux-thunk 配置在store中 4. 创建action的函数不再返回一般对象,而是一个函数,在该函数中写一个异步任务 5. 创建异步任务结束后,分发一个同步的action去真正的操作数据 6. 异步的action不是必须去写的,完全可以等待异步任务结束后去分发同步的action去进行状态的维护 19. 求和案例_react-redux 1. 明确两个概念 1)ui组件不能使用任何redux的api,只负责页面的呈现·交互等 2)如何创建一个容器组件-靠react-redux的connect函数 connect(mapStateToProps,mapDispatchToProps) mapStateToProps:映射状态,返回值是一个对象 mapDispatchToProps:映射操作状态的方法,返回值是一个对象 2. 容器组件中的store是靠props传进去的,而不是在容器组件中直接引入 20. 求和案例_react_redux 优化 1. 容器和UI浑成一个文件 2. 无需给自己的容器组件传递store,给包裹一个 3. 无需自己检测状态的改变,容器组件可以自己完成这个动作 4. mapDisPatchToProps可以写成简单的一个对象 5. 一个组件和redux打交道经过那几步 1.定义好UI组件---不暴露 2.引入connect生成一个容器组件,并暴露 写法如下 3.connent(state=>({key:value})){key:xxxAction} 4.在UI组件种通过this.props.xxxxxx读取和操作状态 21. react_redux 数据共享 1. 定义一个person组件,和count组件通过redux进行数据共享 2. 使用react_redux得combineReducers进行reducer合并成一个对象 3. 取出状态要 {state.xxx} 22. redux得reducer必须是一个纯函数 1. 不得改写参数数据 2. 不会产生副作用:网络请求 输入和输出设备 3. 不能调用Math.random等等方法 23. npm i redux-devtools-extension 安装redux开发调试工具 24. 项目打包运行 1. npm install -g serve 首先全局安装serve(安装一次) 2. serve -s build 启动服务器 查看打包 25. setState使用方法 1.使用对象形式 let { count } = this.state this.setState({ count: count + 1 }, () => { }) 2.使用函数形式 this.setState((state, props) => { return { count: state.count + 1 } }) 3. 原则:1. 1. 如果更新状态不依赖于原状态 ===》 使用对象方式 2. 如果新状态依赖原状态 ===》 使用函数方式 3. 如果需要在setState() 执行获取最新得状态数据,在第二个参数中回调函数获取 26. hooks setState 1. 语法 const [count, setCount] = React.useState(initCount) 2. useState说明 1. 参数第一次初始化指定的值储存在内部 2. 返回值:包含两个元素的数组 第一个为内部当前状态值 第二个为更新状态的函数 3. setXXX的写法 1. setXXX(newValue) 参数为非函数值,直接指定新的状态值 2. setXXX(value => newValue) 参数为函数 接收原来的值 return 修改过后的值 27. hooks useEffect 1. Effect Hook 可以再函数中执行副作用操作(用于模拟类组件中的生命周期钩子) 2. react 中的副作用操作 1. 发送ajax请求 2. 设置订阅 / 启动定时器 3. 手动更改真实dom 3. 语法说明 1. useEffect( ()=>{ 可以在这里执行任何副作用操作 return () =>{ //做一些收尾工作 清除定时器取消订阅等 } },[statevalue]) //如果指定的是[], 回调函数只会在第一次render() 执行 [count]监听count 如果count发生改变 则调用函数 []空数组为谁也不检测 如果不写空数组 则默认监听所有state 4. 可以把 hooks useEffect看作以下函数的组合 1. 组件将要挂载 didmount 2. 组件state将要修改 didUpdate 3. willonmount 组件将要卸载 28. Ref hook 1. ref hook可以在函数组件中存储/查找组件内的标签或任意其他数据 2. 语法: const refContaier = useRef() 3. 作用:保存标签对象,功能与对象写法的create.Ref() 一样 29. Fragment 类似于空标签 约等于vue中的templent 1. import React, { Component,Fragment } from 'react' 2. 特性:只可以传入key标签 key={xxx} 30. context 祖宗组件向下传值 1. const UserNameContext = React.createContext() 创建context对象 const { Provider, Consumer } = UserNameContext 拿出Provider包裹需要传递的子标签 2. static contextType = UserNameContext 对象子组件需要声明接收 this.context 拿到接收的值 3. 函数式子组件 使用 { value => { return value } } 组织接收 31. Componment 的两个问题 1. 只要执行setState()即使不改变状态数据,组件也会重新render() 2. 只要当前组件执行render()就会自动更新render子组件 32. 解决 Componment 的两个问题 1. 只有当前组件state或props数据发生改变时才重新render() 33. 原因 1. Componment中的 shouldComponmentUpdate() 总是返回true 34. 解决 1. 重写阀门shouldComponmentUpdate()方法,比较props或state数据 2. 使用 PureComponment 代替 Componment 1. 只有state或者props改变才会调render 2. 但是只进行浅比较,必须修改state的地址 才会发生render的改变 3. 项目中一般使用 PureComponment 进行优化 35. 插槽的使用 1. } /> 2. A组件内部 {this.props.render(value)} 3. B组件内部 照常写就好 36. 错误边界 1. static getDerivedStateFromError(err) { return { hasError: err } } 2. {this.state.hasError ?

当前网络错误,请稍后

: } 3. 只在生产环境下生效 37. 组件通信方式的总结 1. 父子组件 2. 兄弟组件(非嵌套组件) 3. 祖孙组件(跨级组件) 38. 通信方式 1. props 1. children props render props 2. 消息订阅与发布 1. pubs-sub 3. 集中式管理 1. redux dva 4. context 1. 生产者---消费者模式 39. 比较好的搭配方式 1. 父子组件 props 2. 兄弟组件 消息订阅与发布 3. 祖孙组件 消息订阅发布---集中管理---context(开发用的少,封装插件用的多) ### 2021-7-6 完成react相关全部用法