React学习笔记
| 2023-2-24
0  |  阅读时长 0 分钟
日期
Oct 20, 2022 → Feb 24, 2023
Tags
React
框架
前端
JavaScript
由于实验室的项目需要,上学期开始学习React,通过教程实例编程、读文档、看视频教程等方式对React相关的知识进行了系统性的了解,学习笔记内容如下,结构较为松散,仅作为个人学习的笔记记录。

MDN-Getting started with React

按照该教程入门,尝试编写了一个使用React实现的ToDo列表,熟悉了一下React中的JSX写法,组件概念(这里和Vue感觉是一致的),子组件和父组件的信息传递等内容,通过一步步的优化和改动,逐步加深理解。
一点点笔记
useState:返回一个 state,以及更新 state 的函数
useRef:useRef 返回一个可变的 ref 对象
useEffect:让函数型组件拥有处理副作用的能力,类似生命周期函数。
usePrevious写法:

React基础学习

副效应

函数式编程将那些跟数据计算无关的操作,都称为 "副效应" (side effect)。如果函数内部直接包含产生副效应的操作,就不再是纯函数了,我们称之为不纯的函数。

React Hooks

React函数式编程
React Hooks 的意思是,组件尽量写成纯函数,如果需要外部功能和副作用,就用钩子把外部代码"钩"进来。React Hooks 就是那些钩子。
钩子(hook)就是 React 函数组件的副效应解决方案,用来为函数组件引入副效应。函数组件的主体只应该用来返回组件的 HTML 代码,所有的其他操作(副效应)都必须通过钩子引入。

React 默认提供的四个最常用的钩子

  • useState():状态钩子。
    • useState()接受状态的初始值,作为参数,
    • 该函数返回一个数组,数组的第一个成员是一个变量,指向状态的当前值。第二个成员是一个函数,用来更新状态,约定是set前缀加上状态的变量名。
  • useContext():共享状态钩子
    • useContext()钩子函数用来引入 Context 对象
    • 可以深层组件传值,父组件传给子孙组件。接收一个 context 对象(React.createContext的返回值)并返回该 context 的当前值。
    • 使用方法:使用 Context ,首先顶层先声明 Provier 组件,并声明 value属性,接着在后代组件中声明 Consumer 组件,这个 Consumer子组件,只能是唯一的一个函数,函数参数即是 Context 的负载。如果有多个 Context ,ProviderConsumer任意的顺序嵌套即可。
  • useReducer():action 钩子
    • useReducer()的基本用法,接受 Reducer 函数和状态的初始值作为参数,返回一个数组。数组的第一个成员是状态的当前值,第二个成员是发送 action 的dispatch函数。
  • useEffect():副作用钩子
    • useEffect()用来引入具有副作用的操作,最常见的就是向服务器请求数据
    • 传给 useEffect的函数会在浏览器完成布局与绘制之后,在一个延迟事件中被调用。
    • useEffect传递第二个参数时,该值改动才重新渲染
    • 想执行只运行一次的 effect(仅在组件挂载和卸载时执行),可以传递一个空数组([] )作为第二个参数。
Hooks 代码还可以封装起来,变成自定义的 Hook
其他的钩子函数:
  • useRef():获取组件实例对象或者是DOM对象
    • useRef(initialValue)接受一个参数(引用的初始值)并返回一个可变的引用对象(也称为ref)。
    • 引用只是一个具有特殊属性current的对象:ref.current
      • .current属性被初始化为传入的参数(initialValue),返回的ref对象在组件的整个生命周期内持续存在
    • reference.current访问引用,并且 reference.current = newValue更新引用值:
useState()和useRef()的区别:
  1. 更新 state 会触发组件重新呈现,而更新 ref 则不会。
  1. state 更新是异步的(state变量在重新呈现后更新),而ref则同步更新(更新后的值立即可用)
 

Ref转发:

Ref 转发是一项将 ref 自动地通过组件传递到其一子组件的技巧
  • React.forwardRef接受一个渲染函数,其接收 props和 ref参数并返回一个 React 节点。

React中的函数

组件实例被创建并插入DOM中时的生命周期调用顺序:
  1. constructor()
  1. static getDerivedStateFromProps()
  1. render()
  1. componentDidMount():在组件挂载后(插入 DOM 树中)立即调用
当组件的 props 或 state 发生变化时会触发更新。组件更新的生命周期调用顺序如下:
  1. static getDerivedStateFromProps()
  1. shouldComponentUpdate()
  1. render()
  1. getSnapshotBeforeUpdate()
  1. componentDidUpdate()
当组件从 DOM 中移除时会调用如下方法:
  1. componentWillUnmount():在组件卸载及销毁之前直接调用
当渲染过程,生命周期,或子组件的构造函数中抛出错误时,会调用如下方法:
  1. static getDerivedStateFromError()
  1. componentDidCatch()
记忆化函数:
  • useCallback():返回一个记忆化的回调函数。 将记忆化视为缓存一个值,以便不需要重新计算。 这使我们能够隔离资源密集型函数,以便它们不会在每次渲染时自动运行。
    • 防止组件重新渲染,除非其 props 已更改。
  • useMemo():传递一个创建函数和依赖项,创建函数会需要返回一个值,只有在依赖项发生改变的时候,才会重新调用此函数,返回一个新的值。
 
useReducer:useReducer 是 useState 的替代方案,用法:const [state, dispatch] = useReducer(reducer, initialArg, init);
使用dispatch的参数是reducer的action,解耦了操作逻辑(action)和后续的行为(一般是 UI 的更新), reducer 函数根据传入的 action 执行某些逻辑,最后返回的就是新状态。
 

Context

为组件提供上下文,传递参数
Context - React
Context 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法。 在一个典型的 React 应用中,数据是通过 props 属性自上而下(由父及子)进行传递的,但此种用法对于某些类型的属性而言是极其繁琐的(例如:地区偏好,UI 主题),这些属性是应用程序中许多组件都需要的。Context 提供了一种在组件之间共享此类值的方式,而不必显式地通过组件树的逐层传递 props。 Context 设计目的是为了共享那些对于一个组件树而言是"全局"的数据,例如当前认证的用户、主题或首选语言。举个例子,在下面的代码中,我们通过一个 "theme" 属性手动调整一个按钮组件的样式: 使用 context, 我们可以避免通过中间元素传递 props: Context 主要应用场景在于 很多 不同层级的组件需要访问同样一些的数据。请谨慎使用,因为这会使得组件的复用性变差。 如果你只是想避免层层传递一些属性,组件组合(component composition)有时候是一个比 context 更好的解决方案。 比如,考虑这样一个 Page 组件,它层层向下传递 user 和 avatarSize 属性,从而让深度嵌套的 Link 和 Avatar 组件可以读取到这些属性: 如果在最后只有 Avatar 组件真的需要 user 和 avatarSize,那么层层传递这两个 props 就显得非常冗余。而且一旦 Avatar 组件需要更多从来自顶层组件的 props,你还得在中间层级一个一个加上去,这将会变得非常麻烦。 一种
Context - React
context.provider:Provider 接收一个 value属性,传递给消费组件。一个 Provider 可以和多个消费组件有对应关系。多个 Provider 也可以嵌套使用,里层的会覆盖外层的数据。
  • 当 Provider 的 value 值发生变化时,它内部的所有消费组件都会重新渲染。
context.consumer:一个 React 组件可以订阅 context 的变更,此组件可以让你在函数式组件 中可以订阅 context。
 
 
  • useImperativeHandle可以让你在使用 ref时自定义暴露给父组件的实例值。在大多数情况下,应当避免使用 ref 这样的命令式代码。useImperativeHandle(ref, createHandle, [deps])

React教程

React只关注界面

React相关知识

为什么学React?
  1. 原生JavaScript操作DOM繁琐、效率低(DOM-API操作UI)
  1. 使用JavaScript直接操作DOM,浏览器会进行大量的重绘重排
  1. 原生JavaScript没有组件化编码方案,代码复用率低
React的特点
  1. 采用组件化模式、声明式编码,提高开发效率及组件复用率
  1. 在React Native中可以使用React语法进行移动端开发
  1. 使用虚拟DOM+优秀的Diffing算法,尽量减少与真实DOM的交互
    1. DOM Diffing:渲染时进行虚拟DOM的比较,之前存储下来的DOM内容不重新生成
为什么使用JSX?+语法规则
JS生成虚拟DOM的时候十分繁琐,需要使用React.CreateElement()创建
JSX可以看做是JS的语法糖。
JSX的语法规则:
  1. 定义虚拟DOM时,不要写引号
  1. 标签中混入JS表达式时要用{}
  1. 样式的类名指定不要用class,要用className
  1. 内联样式,要用style={key:value}的形式去写
  1. 虚拟DOM必须只有一个根标签
  1. 标签必须闭合
  1. 标签首字母
    1. 若小写字母开头,则将该标签转为html中同名元素,若html中无标签对应的同名元素,则报错
    2. 若大写字母开头,react就去渲染对应的组件,若组件没有定义,则报错。
 
虚拟DOM:
  1. 本质是Object类型的对象(一般对象)
  1. 虚拟DOM比较“轻”,真实DOM比较“重”,因为虚拟DOM是React内部在用,无需真实DOM上那么多属性
  1. 虚拟DOM最终会被React转化为真实DOM,呈现在页面上
区分js语句和js表达式
  1. 表达式:一个表达式产生一个值,可以放在任何一个需要值的地方
  1. 语句:js代码,for语句,switch语句,if语句
模块与组件
模块:向外提供特定功能的js程序,一般就是一个js文件
  • 为什么要拆为模块:随着业务逻辑增加,代码越来越多且复杂
  • 作用:复用js,提高js的编写,提高js的运行效率
组件:用来实现局部功能想过的代码和资源(html/css/js/image)的集合
  • 为什么需要组件:一个界面的内容更复杂
  • 作用:复用编码,简化项目编码,提高运行效率
组件(函数式组件和类式组件)
函数式组件:函数名即为组件名
类式组件:
  1. 必须继承React.Component,必须使用render()
  • 类中的方法默认开启局部的严格模式
constructor(构造器)和render()方法的this都是当前类的实例对象
  • 其他类中的this,若要使用为实例对象可以在构造器中添加如下代码
  • 可以进行状态初始化
组件实例【类式组件才能谈实例】的三大核心属性:
1. State
  • 是组件对象最重要的属性,必须为一个对象
  • 状态不可直接更改,必须要使用内置API进行更改
    • state的更新是一种合并,不是替换
    • 组件被称为“状态机”,通过更新组件的state来更新对应的页面显示(重新渲染)
      • 每一次调用setState进行的state更新,都会触发组件执行render()函数
    • state的初始化
      • 在类的构造器中初始化,代码比较繁琐
      • 直接在类中初始化即可
      • 组件自定义方法中的this为undefined,如何解决?
        • 强制绑定this到自定义方法,使用函数对象的bind()
        • 自定义方法要用赋值语句的形式+箭头函数
          • 箭头函数的this会取离得最近的this
        2. Props
        • 可以从组件外部传递值到组件内部
        • 对标签属性进行类型、必要性的限制
          • 在属性propTypes中进行相应的设置
        • 指定默认标签属性值
          • 函数式组件使用props
          3. Refs
          1. String类型的Refs被弃用了:效率不高
          • 通过在组件中使用字符串指明refs,React自动收集ref到this.refs中
          1. 回调函数形式的ref
          • 若使用箭头函数,每次渲染时,回调函数形式的ref都会执行两次
            • 修改方法:将ref的回调函数定义成class的绑定函数
            1. createRef API实现(最为推荐的一种方式)
                • React.creatRef调用后可以返回一个容器,该容器可以存储被ref所标识的节点,该容器是专人专用的
            React中的事件处理
            1. 事件处理名的格式:onXxxx
              1. React使用的是自定义(合成)事件,而不是使用的原生DOM事件 —— 为了更好的兼容性
              2. React中的事件是通过事件委托方式处理的(委托给组件最外层的元素)—— 为了更高效
            1. 通过event.target得到发生事件的DOM元素对象 —— 不要过度使用ref
             
            React中收集表单数据
            阻止表单提交(阻止默认函数的调用)event.preventDefault
            非受控组件:现用现取
            受控组件:所有的属性维护在状态中,使用onChange
            高阶函数_函数柯里化
            高阶函数:如果一个函数符合下面2个规范中的任何一个,该函数就是高阶函数
            1. 若A函数,接收的参数是一个函数,那么A级就可以称之为高阶函数
            1. 若A函数,调用的返回值依然是一个函数,那么A就可以称之为高阶函数
            常见的高阶函数有:Promise,setTimeout,arr.map()等等
            函数柯里化:通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码形式
            保存表单数据到状态中
            为什么使用[]
            [xxx]可以看成是从对象中取出xxx属性
            不使用函数柯里化的写法
            组件的生命周期
            旧生命周期
            notion image
            • shouldComponentUpdate():控制组件更新的“阀门”
              • 默认返回true,自定义必须返回bool值
            • 注意两条路线:setState()、forceUpdate()
            • componentWillReceiveProps():第一次调用的时候不执行(不算)
            • 生命周期总结:
              • 初始化阶段:由ReactDOM.render()触发——初次渲染
                  1. constructor()
                  1. componentWillMount()
                  1. render()
                  1. componentDidMount()
                    1. 一般在这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息
              • 更新阶段:由组件内部this.setState()或父组件render触发
                  1. shouldComponentUpdate()
                  1. componentWillUpdate()
                  1. render()
                  1. componentDidUpdate()
              • 卸载组件:由ReactDOM.unmountComponentAtNode()触发
                  1. componentWillUnmount()
                    1. 一般在这个钩子中做一些收尾的事,例如:关闭定时器,取消订阅消息
            即将废弃的钩子,下一个大版本使用需要加上UNSAFE_前缀
            componentWillMount()
            componentWillReceiveProps()
            componentWillUpdate()
            新生命周期
            notion image
            • getDerivedStateFromProps():
              • getDerivedStateFromProps返回的值会改变state的值,且被修改后的值不能再被setState()修改
              • 特殊用例,state的值取决于props
              • getSnapshotBeforeUpdate():
                • 在最近一次渲染输出之前调用,是的组件能在更新之前从DOM中捕获一些信息
                • 在更新之前获取快照,返回值会作为参数传给componentDidUpate()方法
                • 用法:以特殊方式处理滚动条位置
              DOM的diffing算法
              diffing算法的最小粒度是标签。
              经典面试题:
              1. react/vue中的key有什么用?(key的内部原理是什么)
              1. 为什么遍历列表时,key最好不要用index?
              • 虚拟DOM中key的作用
                  1. 简单来说:key是虚拟DOM对象的标识,在更新显示时key起极重要的作用
                  1. 详细来说:当状态中的数据发生变化时,react会根据【新数据】生成【新的虚拟DOM】,随后React进行【新虚拟DOM】与【旧虚拟DOM】的diff比较,比较规则如下:
                    1. 旧虚拟DOM中找到了与新虚拟DOM相同的key:
                      1. 若虚拟DOM中内容没变,直接使用之前的真实DOM
                      2. 若虚拟DOM中内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM
                    2. 旧虚拟DOM中未找到与新虚拟DOM相同的key
                      1. 根据数据创建新的真实DOM,随后渲染到页面
                  ⇒ 不推荐使用index(索引值)作为key
                  • 使用index作为key可能会引发的问题:
                      1. 若对数据进行:逆序添加、逆序删除等破坏顺序操作:
                        1. 会产生没有必要的真实DOM更新 ⇒ 界面效果没有影响,但会降低运行效率
                      1. 如果结构中还包含输入类的DOM:
                        1. 会产生错误DOM更新 ⇒ 界面有问题,导致子DOM不重新渲染,信息发生错乱
                      1. 注意!如果不存在对数据的逆序添加、逆序删除等破坏顺序的操作,仅用于渲染列表,用于展示,使用index作为key是没有问题的
              • 开发中如何选择key?
                • 最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等唯一值
                • 如果确定只是简单的展示数据,用index也是可以的
               
              React脚手架:用于帮助程序员快速创建一个基于React库的模板项目
              • 基于webpack
              • React在页面中引入的为App组件,其他自定义的组件都应该在App中
              • 脚手架中包裹<App/>的<React.StrictMode>可以检查子组件中 不合理的内容
              • 组件文件后缀推荐使用.jsx
              • 组件中文件夹中使用index.css,index.jsx,引用时可以只写到文件夹目录
              • 样式的模块化:使用index.module.css(加上module)
              React实例:ToDoList
              1. 拆分组件、实现静态组件,注意:className、style的写法
              1. 动态初始化列表,如何确定将数据放在哪个组件的state中
                1. 某个组件使用:放在自身的state中
                2. 某些组件使用:放在他们共同的父组件state中(官方称呼:状态提升)
              1. 关于父子组件之间的通信
                1. 父组件给子组件传递数据:通过props传递
                2. 子组件给父组件传递数据:通过props传递,要求父提前给子传递一个函数
              1. 注意defaultChecked和checked的区别,类似的还有:defaultValue和value
              1. 状态在哪里,操作状态的方法就在哪里
              React ajax
              • 常用的ajax请求库
                • axios(推荐使用):轻量级
                  • 封装XmlHttpRequest对象的ajax
                  • promise风格
                  • 可以用在浏览器端和node服务器端
                • jQuery:比较重
               
              连续解构赋值
              兄弟组件之间沟通:消息订阅+发布机制
              • 订阅+发布机制实际上适用任何组件之间的消息传递
              工具库:PubSubJS
              订阅消息:
              1. 消息名(确定)
              1. 发布消息
               
              Fetch发送请求
              • Fetch关注分离的设计思想
              React路由 【p127 为最新版本】
              • SPA应用(Single Page Web Application)单页面应用
                • 局部更新
                • 数据通过ajax请求,在前端异步展现
              • 路由
                • 前端路由的实现:基于history(BOM [浏览器对象] 的history,前端路由的基石)实现
                  • 浏览器的历史记录是一个栈
              • react-router-dom库(react-router的web实现)
                • BrowserRouter
                • HashRouter:多一个#号,#号后的都不会作为资源传给服务器
              • 路由组件和一般组件的不同
                  1. 写法不同
                    1. 一般组件:<Demo/>
                    2. 路由组件:<Route path='demo' component={Demo}/>
                  1. 存储位置不同
                    1. 一般组件:components
                    2. 路由组件:pages
                  1. 接收到的props不同
                    1. 一般组件:写组件标签时传递了什么,就能收什么
                    2. 路由组件:接收到三个固定的属性
                      1. history:
                        • go()
                        • goBack()
                        • goForward()
                        • push()
                        • replace()
                        location:
                        • pathname
                        • search
                        • state
                        match:
                        • params
                        • path
                        • url
              <NavLink>
              • 区别于<Link>会给组件添加activeClassName类名,默认active
              • 标签体内容是一个特殊的标签体属性
                • 即this.props.children
              <Switch>
              • 路由在匹配的时候,会一直往下匹配
              • 使用<Switch>包裹路由,可以实现匹配上就不再往下匹配,代码效率更高
              解决多级路径刷新页面样式丢失的问题
              1. 路由多层级结构,刷新后导致css的路径错误
              1. 解决方案:
                1. <BrowserRouter>改用<HashRouter>
                2. 资源路径使用%PUBLIC_URL%
                3. 资源路径的开头去掉.
              路由的模糊匹配:默认使用,输入的路径必须包含匹配的路径,且顺序要一致
              1. 路由的路径匹配:最左前缀匹配
              1. 使用exact关键字,表示严格匹配:<Route exact path=’/home’ component={Home}/>或者<Route exact=true path=’/home’ component={Home}/>
                1. exact严格匹配使用原则:只有不使用会影响页面正常展示时才使用
              Redirect的使用
              1. 一般写在所有路由注册的下方,当所有路由都没有匹配的时候,跳转到Redirect指定的路由
                嵌套路由(二级路由)
                1. 在父组件(被嵌套)中继续注册路由
                1. 注册子路由(嵌套组件)的路径需要带上父路由的路径值
                1. 路由的匹配是按照注册路由的顺序进行的
                向路由组件传递参数
                params参数:
                search参数:获取到的search是urlencoded编码字符串,需要借助querystring解析
                state参数:刷新也可以保留住参数,不会在地址栏显示
                路由跳转的两种模式
                1. push模式(默认模式,类似于压栈,留下痕迹)
                1. replace模式(替换栈顶,不留下痕迹)
                  编程式路由导航:借助this.props.history上的API对路由进行操作
                  一般组件中操作路由:使用withRouter
                  • withRouter可以加工一般组件,让一般组件具备路由组件所特有的API
                  • withRouter的返回值是一个新组件
                  BrowserRouter和HashRouter的区别
                  1. 底层原理不一样:
                    1. BrowserRouter使用的是H5的history API,不兼容IE9及以下版本
                    2. HashRouter使用的是URL的哈希值
                  1. path表现形式不一样
                    1. BrowserRouter的路径中没有#,例如:localhost:3000/demo/test
                    2. HashRouter的路径包含#,例如:localhost:3000/#/demo/test
                  1. 刷新后对路由state参数的影响不一样
                    1. BrowserRouter没有任何影响,因为state保存在history中
                    2. HashRouter刷新后会导致路由state参数的丢失
                  1. 备注:HashRouter可以用于解决一些路径错误相关的问题
                   

                  AntDesign的使用:

                  1. 基本使用
                  1. 按需引入+自定义主题

                  Redux:

                  React 的状态管理工具,不一定必须,Redux 的适用场景:多交互、多数据源
                  Redux
                  • 专门用于状态管理的JS库
                  • 可以用在react、angular、vue等
                  • 作用:集中式管理React应用中多个组件共享的状态
                  • 使用情况:
                    • 某个组件的状态需要让其他组件可以随时拿到(共享)
                    • 一个组件需要改变另一个组件的状态(通信)
                    • 使用原则:能不用就不用,如果不用比较吃力才考虑使用
                  • 原理图
                  notion image
                  • 三个核心概念
                    • action
                      • type
                      • data
                    • reducer
                    • store
                  • 同步action&异步action
                    • 同步action指action的值为Object类型的一般对象
                    • 异步action指action的值为函数
                      • 默认action类型为Object,若要使用函数类型的action需要使用中间件(redux-thunk)
                      • 函数中执行异步任务,异步流程结束后会分发一个同步的action去真正操作数据
                    • 异步action不是必须要写的,完全可以自己等待异步任务的结果再去分发同步action
                  react-redux
                  • facebook的插件库
                  • react-redux模型图
                    • notion image
                    • 容器组件:使用connect连接
                      • 备注:容器组件中的store是靠props传进去的,而不是在容器组件中直接引入
                      • mapDispatchToProps可以传递的参数
                        • 函数
                        • 对象
                      • connect中隐含监测逻辑,使用后不再需要使用store.subscribe()自行监测+重新渲染
                  • 数据共享
                    • combineReducers
                   

                  React的扩展知识

                  setState()
                  • setState()的更新是异步的,不能够直接获取,若要使用最新的状态值,有两种更新状态的写法
                      1. 对象式的setState
                        1. stateChange为状态改变对象
                        2. callback是可选的回调函数,在状态更新完毕,页面也更新后(render调用后)才被调用
                      1. 函数式的setState
                        1. updater为返回stateChange对象的函数
                        2. updater可以接收到state和props
                        3. callback是可选的回调函数,在状态更新,页面也更新后(render调用后)才被调用
                      1. 对象式的setState是函数式setState的简写方式(语法糖)
                      1. 使用原则:
                        1. 如果新状态不依赖于原状态 ⇒ 使用对象方式
                        2. 如果新状态依赖于原状态 ⇒ 使用函数方式
                        3. 如果需要在setState()执行后获取最新的状态数据,要在第二个callback函数中读取
                  lazyLoad
                  • 懒加载,使用时才加载组件,有助于提升性能
                  1. 组件调用Lazy
                    1. 注册路由使用Suspense包裹
                      state Hook
                      1. useState:状态钩子。
                          • useState()接受状态的初始值,作为参数,
                          • 该函数返回一个数组,数组的第一个成员是一个变量,指向状态的当前值。第二个成员是一个函数,用来更新状态,约定是set前缀加上状态的变量名。
                          • React底层进行了缓存,第一次调用的后,useState不会改变状态值
                      Effect Hook
                      1. useEffect:副作用钩子,监测作用,可以在函数组件中执行副作用操作(用于模拟类组件中的生命周期钩子)
                        1. React中的副作用操作:
                          1. 发ajax请求数据获取
                          2. 设置订阅/启动定时器
                          3. 手动更改真实DOM
                        2. 语法和说明
                          1. useEffect()可以类比成componentDidMount、componentDidUpdate、componentWillUnmount三个函数的组合
                        Ref Hook
                        1. useRef():可以在函数组件中存储/查找组件内的标签或任意其他数据
                          1. 语法:
                            1. 作用:保存标签对象,功能与React.createRef()一样
                          Fragment
                          • 文档碎片,在解析时会被去除,只能传key这个参数
                          Context
                          • 一种组件间的通信方式,常用于【祖组件】和【后代组件】间通信
                          • 使用:在应用开发中一般不用context,一般都用它的封装react插件
                            Component相关优化
                            • Component的两个问题
                                1. 只要执行setState(),即便不改变状态数据,组件也会重新render() ⇒ 效率低
                                1. 只要当前组件重新render(),自动重新render()子组件,纵使子组件没有用到父组件的任何数据 ⇒ 效率低
                                ⇒ 提高效率的方法:只有当组件的state或props数据发生改变时才render()
                              • 原因:Component中的shouldComponentUpdate()总是返回true
                              • 解决方法:
                                • 方法一:重写shouldComponentUpdate()方法,比较新旧state或props数据,有变化才返回true,没有变化返回false
                                • 方法二:使用PureComponent
                                  • PureComponent重写了shouldComponentUpdate(),只有state或props数据有变化才返回true
                                  • 注意:
                                    • 只是进行state和props数据的浅比较,如果只是数据对象内部数据变了,返回false
                                    • 不要直接修改state数据,而是要产生新数据
                                • 项目中一般使用Purecomponent来优化
                            Render Props
                            • 如何向组件内部动态传入带内容的结构(标签)
                                1. 使用children props:通过组件标签传入结构
                                1. 使用render props:通过组件标签属性传入结构,一般用render函数属性
                            • chidren props“:件之间的内容为特殊的props属性——children
                              • render props:
                                Error Boundary(错误边界)
                                用来捕获后代组件错误,渲染出备用页面
                                • 控制错误在一定范围内,不让子组件的错误影响到其他组件
                                • 错误边界仅适用于开发环境
                                • 特点:只能捕获后代组件生命周期产生的错误,不能捕获自己组件产生的错误和其他组件在合成事件、定时器中产生的错误
                                • 使用方法:getDerivedStateFromError配合componentDidCatch
                                  组件间通信方式总结
                                  • 组件间的关系:
                                    • 父子组件
                                    • 兄弟组件
                                    • 祖孙组件
                                  • 几种通信方式:()中是推荐的搭配方式
                                      1. props:(父子组件)
                                        1. children props
                                        2. render props
                                      1. 消息订阅-发布:(兄弟、祖孙组件)
                                        1. pubs-sub,event等等
                                      1. 集中式管理:(兄弟、祖孙组件)
                                        1. redux、dva等等
                                      1. conText:(祖孙组件)
                                        1. 生产者-消费者模式
                                   

                                  React Router 6

                                  • 变化
                                    • Switch被Routes取代,Route中的component变为element
                                      NavLink的高亮方法,className使用函数
                                      useRoutes,路由表的新写法
                                      嵌套路由
                                      • <Outlet>指定路由组件展示的位置
                                       
                                      路由参数(Props、Search、State)
                                      • Props参数:useParams
                                      • Search参数:useSearchParams
                                      • State参数:useLocation
                                      编程式路由导航:useNavigate
                                      useInRouterContext():判断当前是否在路由组件中
                                      useNavigationType():返回当前导航类型
                                      useOutlet():当<Route>产生嵌套时,渲染其对应的后续子路由,用来呈现当前组件中渲染的嵌套路由
                                      • 可以用来判断当前组件有无挂载嵌套路由
                                      useResolvePath():解析路由path
                                  Loading...
                                  目录