react最新版本@18.2.0 中文官网地址:https://zh-hans.react.dev/reference/react
介绍:
项目搭建逻辑:1)项目中index.html中渲染的内容。2)看main.js中绑定的组件渲染
React框架 由Facebock开源的一款前端框架。
工作中使用的版本:
react:16.2.0(太老了,都更新到16.14.0-18.0.2)
ant:3.x 蚂蚁研发(0.9x-1.x-2.x-3.x-4.x)
React+anted+axios+redux+mobx
推荐可以在React中使用的工具库
(1)UI组件库 https://ant.design/components/table-cn/ (最新版本4.x)
(2)状态管理工具Dvajs:是基于 redux , react-redux ,redux-saga 的状态管理工具
(3)拖拽库dnd
(4)可视化图表 echarts-for-react(基echarts 封装的图表库,能够满足基本的可视化图表需求)https://git.hust.cc/echarts-for-react/ (公司用 的是echarts )
(5)链接生成二维码:qrcode.react(import QRCode from ‘qrcode.react’)
内容:
一、基础知识
⚠️:props不是光指调用函数组件或类组件时通过属性传的参数,还有全局引入的及自己定义的初始化属性
生命周期详解
(1)初始化阶段:对类设置默认的属性defaultProps和类型propType及constructor 中的内容,在 constructor 中进行 state、props 的初始化,在这个阶段修改 state,不会执行更新阶段的生命周期,可以直接对 state 赋值。该阶段是在render前进行的
(2)挂在阶段
挂在前的生命周期即render前执行:componentWillMount,一般在此声明周期中进行接口的请求,定时器等更新组件中的状态,用于渲染页面(此时可以取到this.state中值)
挂在阶段:render函数(也不可以setState)
挂在后执行的生命周期:componentDidMount 也可以用于接口的请求,因为react中会实时更新变更的内容(第一次render后调用)
(3)更新阶段:(由于父组件传的props变更或者自己组件的状态state变更引起)
props变更后:
componentWillReceiveProps(一般用于监听props的变化),当时state变化引起时没有此声明周期函数(直接下一个开始)
shouldComponentUpdate(这个生命周期函数返回布尔值,表示要不要更新组件,一般用于做性能优化,因为每次更新都会频繁调用render生成新的虚拟dom,比较耗时,而这个方法在render前执行,返回布尔要不要执行后面的生命周期过程)
componentWillUpdate(这个阶段不可以setState,会导致循环调用)
render
componentDidUpdate(更新后调用的声明周期函数,可以拿到更新前的值)
(4)卸载阶段:componentWillUnmount(组件卸载前的调用,一般执行清理定时器等的操作)
componentWillUnmount() {
clearInterval(this.timer);
}
补充ref转发知识(允许组件接受ref并向下转发)
何时使用refs:管理焦点(文本选择、媒体播放等)、触发强制动画、集成第三方dom库
⚠️ 不能在函数组件上直接使用ref,因为其没有实例
二、数据流Mobx:React 和 MobX 是一对强力组合。React 通过提供机制把应用状态转换为可渲染组件树并对其进行渲染。而MobX提供机制来存储和更新应用状态供 React 使用(不用所有的数据都需要setState来更改),一般用mobx结合使用,而不用redux
== 学习网址:https://cn.mobx.js.org/ 为了解决通信问题 ==
(1)@observer 给类组件增加可观察模式
(2)@observable loading = false; 用于定义动态变更的数据
(3)@computed get searchJS() { // 类似计算属性,一般用于动态拿复杂的数据,即转换成js数据
return toJS(this. loading);
}
(4)@action.bound 给方法进行绑定
(5)toJS() 将数据转位js数据
⚠️ 还有别的数据流方案,例如Redux等
常用的方案:1)Mobx 2) Redux 3) DvaJS 将路由和数据结合
三、路由:保持 UI 与 URL 同步
https://react-guide.github.io/react-router-cn/ (React Router中文文档)
React中使用 React-Router
React中使用 react-router-dom路由
react-router和react-router-dom两个包都可以实现单页面应用的页面间的跳转
React中使用React-router-redux:一般React-Redux和React-Router 都单独使用,除非想通过触发action来变更url
react-router-redux 将react-router 和 redux 集成到一起,用redux的方式去操作react-router(用dispatch触发的方式)
例如,react-router 中跳转需要调用 router.push(path),集成了react-router-redux 就可以通过dispatch的方式使用router,例如跳转可以这样做 store.dispatch(push(url))。本质上,是把react-router自己维护的状态,例如location、history、path等等,也交给redux管理。
import { push } from ‘react-router-redux’
// http://w1.opc.dev.wormpex.com/hr?#/algorithmSchedulingManagement/baseWorkitemManagement
// 例如:store.dispatch(push(‘/algorithmSchedulingManagement/baseWorkitemManagement’));
四、Redux:状态管理(有些项目不使用和mobx的结合,使用Redux进行集中数据的管理)
学习网址:https://www.redux.org.cn/docs/basics/UsageWithReact.html 为了解决组件通信问题
1、知识点:3大原则 单一数据源(唯一一个store中)、state只读(改变state只能触发action)、使用纯函数修改state
触发action(对象或函数,一般用于接口数据的请求),执行对应的reducer更新state, 将容器组件与展示组件相关联(从而在容器组件中使用redux)
(1)action 与 action 创建函数
(2)Reducer 函数
(3)Store,Redux 应用只有一个单一的 store
五、DvaJS
数据流DvaJS:https://dvajs.com/api/
介绍:dva = React-Router (路由)+ Redux(数据流) + Redux-saga(异步操作)
State:一个对象,保存整个应用状态
View:React 组件构成的视图层
Action:一个对象,描述事件
connect 方法:一个函数,绑定 State 到 View
dispatch 方法:一个函数,发送 Action 到 State
拓展常使用的js库或组件库:
1、react生成二维码的插件
2、同vue项目一样 也会引入事件处理库mament 处理url的库 qs等
3、组件库 Ant ( https://3x.ant.design/components/select-cn/)
react版本更新及学习(工作中react项目使用的16.2.0) 15.6-18.2.0
一、例如15 VS 16(生命周期变更、架构更新、hooks钩子)
文章参考资料
react官网:https://zh-hans.reactjs.org/
react技术揭秘:https://react.iamkasong.com/preparation/idea.html#react%E7%90%86%E5%BF%B5
1、生命周期对比
react 15
react 16
总结:
(1)react16去掉了componentWillMount、componentWillUpdate、componentWillReveiveprops,增加了静态方法 getDerivedStateFromProps、getSnapshotBeforeUpdate这两个方法
1)getSnapshotBrforeUpdate:在render方法之后,componentDidUpdate之前被执行,即真实DOM更新之前(获取更新前的真实DOM和更新前后的State&props信息)。该方法需要一个返回值,作为componentDidUpdate的第三个参数
2)getDerivedStateFromProps:替代componentWillReveiveprops与componentWillMount(实质是替代componentWillReveiveprops)。该方法是根据父组件更新props时触发的,它是静态方法,防止在该方法中调用this实例,不合理使用this.state等导致 死循环等
(2)官方在react16虽然去掉了componentWillMount、componentWillUpdate、componentWillReveiveprops这三个生命周期,但是在react16还是能用,只不过可能会在新版本中产生bug,尤其对于新增的生命周期。
(3)生命周期迭代
16.3:为不安全的生命周期引入别名,UNSAFE_componentWillMount、UNSAFE_componentWillReceiveProps 和 UNSAFE_componentWillUpdate。(旧的生命周期名称和新的别名都可以在此版本中使用。)
16.9:为 componentWillMount、componentWillReceiveProps 和 componentWillUpdate 启用废弃告警。(旧的生命周期名称和新的别名都将在这个版本中工作,但是旧的名称在开发模式下会产生一个警告。)
17.0:删除 componentWillMount、componentWillReceiveProps 和 componentWillUpdate。(在此版本之后,只有新的 “UNSAFE_” 生命周期名称可以使用。)
2、架构:会使原始的同步渲染变成异步(对React核心算法做一次重写)
(1)react15可分为两层:交替同步执行
Reconciler协调器:通过reconcile(diff算法)递归计算哪些组件需要更新,并通知Renderer。他是递归处理的
Renderer渲染器:将更新的组件渲染到真实dom上(渲染到页面 )。不同平台有不同的Renderer
React15问题:CPU和IO问题(网络延迟)
CPU问题(遇到大计算量的操作或设备性能不足使页面掉帧,导致卡顿):
每16.6ms浏览器会刷新一次,而渲染到屏幕上浏览器要进行JS的执行-样式布局-样式绘制,如果在这一帧内这三个过程不能全部完成,就会出现页面掉帧,也就是页面卡顿的情况(JS脚本执行和浏览器布局、绘制不能同时执行.16.6ms内需完成 js脚本执行–样式布局–样式绘制) (是因为它们都需要主线程来执行。浏览器的主线程只有一个,而且是单线程的,也就是说同一时间只能做一件事情)
IO问题:
网络延迟是前端开发无法解决的情况,但如何在网络延迟的情况下,减少用户对网络延迟的感知
解决:将同步的更新变为异步的、可中断的更新
(2)react16:架构可以分为3层
Scheduler调度器:调度任务的优先级,高优任务优先进入Reconciler(协调器)
Reconciler协调器:负责找出变化的组件
Renderer渲染器:负责将变化的组件渲染到页面上(Renderer根据Reconciler为虚拟DOM打的标记,同步执行对应的DOM操作)
(3)变化:
新增Scheduler调度器
Reconciler变化:内部采用Filber架构,更新过程是可中断的循环过程,根据浏览器是否有剩余时间来判断,它不再是交替执行,而是在内存中执行只有所有组件完成Reconciler才算完成
React16整个Scheduler与Reconciler的工作都在内存中进行。只有当所有组件都完成Reconciler的工作,才会统一交给Renderer
其中红框中的步骤随时可能由于以下原因被中断:
有其他更高优任务需要先更新
当前帧没有剩余时间
3、更新机制
react15更新流程:协调器和渲染器依次执行工作,整个过程都是同步的(带来cpu及io问题)
react16更新流程:如果协调器中有任务正在 diff,但是调度器有更高优的任务进来,那刚才的任务就会中断执行,反而先执行高优的任务,但由于调度器和协调器都是在内存中工作的,所以即使有中断发生,用户也不会看到更新不完全的视图(减少用户卡顿等的感知)
16各版本迭代
React16.0:新的架构Fiber发布
React16.3:新的生命周期发布,为不安全的生命周期引入别名
React16.8:hook发布
React16.9:为不安全的生命周期启用废弃告警
React16.13.0 新的警告(Render期间更新的警告、冲突样式规则警告、废弃字符串ref的警告)
4、react hooks(钩子) 组件尽量写成纯函数
版本:react >= 16.8, React Native >= 0.59 版本后开始支持hooks,目前项目中升级RN后React Native为0.63,react版本为16.13.1
hooks的作用:在不编写class的情况下使用state及其他react特性(因为真实的React APP由多个类安装层级构成,复杂度高,引入Redux后更难拆分、重构、测试,所以希望react还是只是简单的数据管道而不是复杂的容器,而函数组件又是无状态无生命周期解决不了)
hooks优点:
1,函数组件可以拥有自己的状态、并且可以监听生命周期
2,代码编写、复用及管理变得简单
(1)useState:状态钩子,纯函数不能有状态,把状态放入钩子中让纯函数有状态(定义响应式变量的hooks函数)
功能:定义、读取、修改。useState函数的参数是第一个解构出的值,第二个解构出的值是用来修改第一个参数变量值
(2)useContext:共享状态钩子,用于在组件之间共享状态(在hooks前使用class组件并通过props传参,通过类组件的constructor构造函数接收,使用hooks函数useContext实现组件数据共享)父子组件还可以利用props传参进行
注意: useContext 的参数必须是 context 对象本身
(3)useReducer():用来存储和更新state,一般情况下使用useState就够用了。当状态处理逻辑复杂,多组件共享、需要连续更新多个state时使用。
const [state, dispatch] = useReducer(reducer, initialState);//它接受 Reducer 函数和状态的初始值作为参数,返回一个数组。数组的第一个成员是状态的当前值,第二个成员是发送 action 的dispatch函数
(4)useEffect():副作用钩子,用于向服务器请求数据(以前放在componentDidMount中代码)
它合成了 calss 组件中的componentDidMount、componentDidUpdate、 componentWillUnmount
(5)useRef()
(6)React Hook 性能优化之 useCallback , useMemo , memo
例如一个子组件只是固定内容的渲染,我们希望只有子组件挂载时渲染一次即可,但使用react hooks开发时,父组件触发更新子组件也会重新render,导致没必要的组件一直重复渲染。
二、react16 Vs react17(重点17版本更新了什么)事件委托、全新JSX、渐进式升级
1、全新的JSX:react7前使用jsx必须引入,JSX 转换会把 JSX 转换为 React.createElement(…) 调用
2、事件委托变更:document 切换为 root、onScroll不再冒泡、去除事件池):不会将事件处理器添加到document上而是添加到渲染react树的根dom容器中
3、渐进式升级:不用一次性升级整个应用(可以同时使用react17|18)
三、react17Vs react18(重点18版本更新了什么。17到18升级会遇到的问题及新的功能,解决并发问题,但策略是渐进升级,直接升级也不会有任何破坏性影响)
⚠️:并发渲染是底层的一次 架构设计升级,React18关注点在于更快的性能以及用户交互响应效率,其实设计理念处处包含了中断和抢占的概念
概述:渐进式(过渡,紧急非紧急更新)、setState同步|异步(自动批处理)、并发特性(并发渲染机制,多个版本react)(使用concurrent mode开启并发特性)
1、react18废弃会IE浏览器的支持
2、createRoot:ReactDOM.render会触发警告,使用New root api:createRoot
3、setState 同步/异步
react18将将多个状态更新合并为一次重新渲染,以获得更好的性能,在18之前React 只能在组件的生命周期函数或者合成事件函数中进行批处理,Promise、setTimeout异步函数以及原生事件中是不会对其进行批处理的。但18后所有的更新都将自动批处理,除非自己设置await等让多次执行render
4、新api
总结:
React18.0:开启concurrent Mode
(1)使用concurrent mode,开启并发特性(不同版本react)
(2)自动批处理(setState)
(3)新功能:Transition(用于区分紧急和非紧急更新),由此带来新的钩子startTransition和useTransition