- 初始化阶段:
- getDefaultProps:获取实例的默认属性
- getInitialState:获取每个实例的初始化状态
- componentWillMount:组件即将被装载、渲染到页面上
- render:组件在这里生成虚拟的 DOM 节点
- componentDidMount:组件真正在被装载之后
- 运行中状态:
- componentWillReceiveProps:组件将要接收到属性的时候调用
- shouldComponentUpdate:组件接受到新属性或者新状态的时候(可以返回 false,接收数据后不更新,阻止 render 调用,后面的函数不会被继续执行了)
- componentWillUpdate:组件即将更新不能修改属性和状态
- render:组件重新描绘
- componentDidUpdate:组件已经更新
- 销毁阶段:
- componentWillUnmount:组件即将销毁
- 类组件不仅允许使用更多额外的功能,如组件自身的状态和生命周期钩子,也能使组件直接访问 store 并维持状态
- 当组件仅是接收 props,并将组件自身渲染到页面时,该组件就是一个 ‘无状态组件’,可以使用一个纯函数来创建这样的组件。这种组件也被称为哑组件或展示组件
- State 是一种数据结构,用于组件挂载时所需数据的默认值。State 可能会随着时间的推移而发生突变,但多数时候是作为用户事件行为的结果。
- Props则是组件的配置。props 由父组件传递给子组件,并且就子组件而言,props 是不可变的。组件不能改变自身的 props,但是可以把其子组件的 props 放在一起(统一管理)。Props 也不仅仅是数据–回调函数也可以通过 props 传递。
高阶组件是一个以组件为参数并返回一个新组件的函数。最常见的就是是 Redux 的 connect 函数。除了简单分享工具库和简单的组合,HOC 最好的方式是共享 React 组件之间的行为。如果发现在不同的地方写了大量代码来做同一件事时,就可以用 HOC
因为 this.props 和 this.state 的更新可能是异步的,不能依赖它们的值去计算下一个 state
在 super() 被调用之前,子类是不能使用 this 的,在 ES2015 中,子类必须在 constructor 中调用 super()。传递 props 给 super() 的原因则是便(在子类中能在 constructor 访问 this.props。
React中的事件处理程序将传递SyntheticEvent实例,该实例是React跨浏览器本机事件的跨浏览器包装器。这些综合事件具有与您惯用的本机事件相同的界面,除了它们在所有浏览器中的工作方式相同.
React实际上并未将事件附加到子节点本身。React将使用单个事件侦听器在顶层侦听所有事件
Refs 是使用 React.createRef() 方法创建的,并通过
ref
属性添加到 React 元素上
JSX即JavaScript XML。一种在React组件内部构建标签的类XML语法。JSX为react.js开发的一套语法糖,也是react.js的使用基础。React在不使用JSX的情况下一样可以工作,然而使用JSX可以提高组件的可读性,因此推荐使用JSX
如果直接更新state状态,那么它将不会重新渲染组件,而是使用
setState()
方法。它计划对组件状态对象的更新。状态改变时,组件通过重新渲染做出响应
扩展传值符号,是把对象或数组里的每一项展开,是属于ES6的语法
hooks是针对在使用react时存在以下问题而产生的:
组件之间复用状态逻辑很难,在hooks之前,实现组件复用,一般采用高阶组件和 Render Props,它们本质是将复用逻辑提升到父组件中,很容易产生很多包装组件,带来嵌套地域。
组件逻辑变得越来越复杂,尤其是生命周期函数中常常包含一些不相关的逻辑,完全不相关的代码却在同一个方法中组合在一起。如此很容易产生 bug,并且导致逻辑不一致。
复杂的class组件,使用class组件,需要理解 JavaScript 中 this 的工作方式,不能忘记绑定事件处理器等操作,代码复杂且冗余。除此之外,class组件也会让一些react优化措施失效。
针对上面提到的问题,react团队研发了hooks,它主要有两方面作用:
用于在函数组件中引入状态管理和生命周期方法
取代高阶组件和render props来实现抽象和可重用性
优点也很明显:
避免在被广泛使用的函数组件在后期迭代过程中,需要承担一些副作用,而必须重构成类组件,它帮助函数组件引入状态管理和生命周期方法。
Hooks 出现之后,我们将复用逻辑提取到组件顶层,而不是强行提升到父组件中。这样就能够避免 HOC 和 Render Props 带来的「嵌套地域」
避免上面陈述的class组件带来的那些问题
1、模拟componentDidMount
useEffect(()=>{console.log(‘第一次渲染时调用’)},[])
2、模拟componentDidUpdate
没有第二个参数代表监听所有的属性更新
useEffect(()=>{console.log(‘任意属性该改变’)})
同时监听多个属性的变化需要将属性作为数组传入第二个参数。
useEffect(()=>{console.log(‘n变了’)},[n,m])
3、模拟componentWillUnmount
useEffect(()=>{
const timer = setTimeout(()=>{
...
},1000)
return()=>{
console.log('组件销毁')
clearTimerout(timer)
}
})
useState()
是什么?useState是react hooks中最常用且用法最简单的一个hook。useState(0)
返回一个元组,其中第一个参数count
是计数器的当前状态,setCounter
提供更新计数器状态的方法。
虚拟 DOM 渲染:当render方法被调用时,它返回一个新的组件的虚拟 DOM 结构。当调用setState()时,render会被再次调用,因为默认情况下shouldComponentUpdate总是返回true,所以默认情况下 React 是没有优化的。
原生 DOM 渲染:React 只会在虚拟DOM中修改真实DOM节点,而且修改的次数非常少——这是很棒的React特性,它优化了真实DOM的变化,使React变得更快。
key 用于识别唯一的 Virtual DOM 元素及其驱动 UI 的相应数据。它们通过回收 DOM 中当前所有的元素来帮助 React 优化渲染。这些 key 必须是唯一的数字或字符串,React 只是重新排序元素而不是重新渲染它们。这可以提高应用程序的性能
Redux 是当今最热门的前端开发库之一。它是 JavaScript 程序的可预测状态容器,用于整个应用的状态管理。使用 Redux 开发的应用易于测试,可以在不同环境中运行,并显示一致的行为
Redux 的优点如下:
结果的可预测性 - 由于总是存在一个真实来源,即 store ,因此不存在如何将当前状态与动作和应用的其他部分同步的问题。
可维护性 - 代码变得更容易维护,具有可预测的结果和严格的结构。
服务器端渲染 - 你只需将服务器上创建的 store 传到客户端即可。这对初始渲染非常有用,并且可以优化应用性能,从而提供更好的用户体验。
开发人员工具 - 从操作到状态更改,开发人员可以实时跟踪应用中发生的所有事情。
社区和生态系统 - Redux 背后有一个巨大的社区,这使得它更加迷人。一个由才华横溢的人组成的大型社区为库的改进做出了贡献,并开发了各种应用。
易于测试 - Redux 的代码主要是小巧、纯粹和独立的功能。这使代码可测试且独立。
组织 - Redux 准确地说明了代码的组织方式,这使得代码在团队使用时更加一致和简单
useState:定义state的数据,参数是初始化的数据,返回值两个值1. 初始化值,2. 修改的方法
useEffect:副作用函数,顾名思义,副作用即只有使用过后才会产生副作用
当作生命周期来使用: 第二个参数如果没写的话,页面一更新触发,compoentDidMount compoentDidUpdate
第二个参数如果空数组的话,只执行一次,compoentDidMount
数组中跟某些变量,当作监听器来使用,监听数据的变化,
useEffect是一个副作用函数,组件更新完成后触发的函数
如果我们在useEffect 返回一个函数的,组件被销毁的时候触发
useMemo:用来计算数据,返回一个结果,监听数据的变化,第二个参数就是监听的数据,具有缓存性
useMemo和useEffect 相比较来说,useMemo 是组件更新的时候触发生命周期
useMemo是怎么做性能优化的?
当父组件向子组件组件通信的时候,父组件中数据发生改变,更新父组件导致子组件的更新渲染,但是如果修改的数据跟子组件无关的话,更新子组件会导致子组件不必要的DOM渲染,是比较消耗性能的,这个时候我们可以使用useMemo或者memo做组件的缓存,减少子组件不必要的DOM渲染
useCallback:当父组件向子组件传递函数的时候,父组件的改变会导致函数的重新调用产生新的作用域,所以还是会导致子组件的更新渲染,这个时候我们可以使用useCallback来缓存组件
useRef:相当于createRef的使用,创建组件的属性信息
useContext:相当在函数组件中获取context状态数的内容信息
useReducer:useReducer是用来弥补useState的补不足, 可以把数据进行集中式的管理,单独处理数据的逻辑信息
浏览器只能读取JavaScript对象,而不能读取普通JavaScript对象中的JSX。因此,要使浏览器能够读取JSX,首先,我们需要使用Babel之类的JSX转换器将JSX文件转换为JavaScript对象,然后将其传递给浏览器。
高阶组件是重用组件逻辑的高级方法。基本上,这是从React的组成性质衍生的模式。HOC是自定义组件,在其中包裹了另一个组件。他们可以接受任何动态提供的子组件,但不会修改或复制其输入组件中的任何行为。您可以说HOC是“纯”组件。
StrictMode
是一个用来突出显示应用程序中潜在问题的工具。与 Fragment
一样,StrictMode
不会渲染任何可见的 UI。它为其后代元素触发额外的检查和警告。
(1)受控组件 在使用表单来收集用户输入时,例如等元素都要绑定一个change事件,当表单的状态发生变化,就会触发onChange事件,更新组件的state。这种组件在React中被称为受控组件,在受控组件中,组件渲染出的状态与它的value或checked属性相对应,react通过这种方式消除了组件的局部状态,使整个状态可控。react官方推荐使用受控表单组件。
受控组件更新state的流程:
可以通过初始state中设置表单的默认值
每当表单的值发生变化时,调用onChange事件处理器
事件处理器通过事件对象e拿到改变后的状态,并更新组件的state
一旦通过setState方法更新state,就会触发视图的重新渲染,完成表单组件的更新
受控组件缺陷: 表单元素的值都是由React组件进行管理,当有多个输入框,或者多个这种组件时,如果想同时获取到全部的值就必须每个都要编写事件处理函数,这会让代码看着很臃肿,所以为了解决这种情况,出现了非受控组件。
(2)非受控组件 如果一个表单组件没有value props(单选和复选按钮对应的是checked props)时,就可以称为非受控组件。在非受控组件中,可以使用一个ref来从DOM获得表单值。而不是为每个状态更新编写一个事件处理程序。
相似性如下。
(1)都是用于创建UI的 JavaScript库。
(2)都是快速和轻量级的代码库(这里指 React核心库)。
(3)都有基于组件的架构。
(4)都使用虚拟DOM。
(5)都可以放在单独的HTML文件中,或者放在 Webpack设置的一个更复杂的模块中。
(6)都有独立但常用的路由器和状态管理库。
它们最大的区别在于 Vue. js通常使用HTML模板文件,而 React完全使用 JavaScript创建虚拟DOM。 Vue. js还具有对于“可变状态”的“ reactivity”的重新渲染的自动化检测系统。
React组件的生命周期分为三个不同的阶段:
初始呈现阶段:这是组件即将开始其生命旅程并到达DOM的阶段。
更新阶段:一旦将组件添加到DOM中,它可能只在发生道具或状态更改时才更新和重新呈现。
这只发生在这个阶段。
卸载阶段:这是组件生命周期的最后一个阶段,在这个阶段组件被销毁并从DOM中删除。
一些最重要的生命周期方法是:
componentWillMount()——在呈现之前在客户端和服务器端执行。
componentDidMount()——仅在第一次呈现之后在客户端执行。
componentWillReceiveProps()——在从父类接收到道具并调用另一个呈现之前调用。
shouldComponentUpdate()——根据某些条件返回真值或假值。
如果希望组件更新,则返回true,否则返回false。
默认情况下,它返回false。
componentWillUpdate()——在DOM中进行呈现之前调用。
componentDidUpdate()——在呈现发生后立即调用。
componentWillUnmount()——在从DOM卸载组件后调用
合成事件是充当浏览器原生事件的跨浏览器包装器的对象。
它们将不同浏览器的行为合并到一个API中。
这样做是为了确保事件在不同的浏览器之间显示一致的属性。
作用域安全:在箭头函数之前,每一个新创建的函数都有定义自身的 this 值(在构造函数中是
新对象;在严格模式下,函数调用中的 this 是未定义的;如果函数被称为“对象方法”,则为基
础对象等),但箭头函数不会,它会使用封闭执行上下文的 this 值。
简单:箭头函数易于阅读和书写
清晰:当一切都是一个箭头函数,任何常规函数都可以立即用于定义作用域。开发者总是可以查找
next-higher 函数语句,以查看 this 的值
因为 this.props 和 this.state 的更新可能是异步的,不能依赖它们的值去计算下一个 state。
在 super() 被调用之前,子类是不能使用 this 的,在 ES2015 中,子类必须在 constructor 中调
用 super() 。传递 props 给 super() 的原因则是便于(在子类中)能在 constructor 访问
this.props 。
React 会创建一个虚拟 DOM(virtual DOM)。当一个组件中的状态改变时,React 首先会通过 “diffing”
算法来标记虚拟 DOM 中的改变,第二步是调节(reconciliation),会用 diff 的结果来更新 DOM。
你可以使用属性初始值设定项(property initializers)来正确绑定回调,create-react-app 也是默认支持
的。在回调中你可以使用箭头函数,但问题是每次组件渲染时都会创建一个新的回调。
在JSX表达式中,一个开始标签(比如 )和一个关闭标签(比如 )之间的内容会作为一个特殊的属性
props.children 被自动传递给包含着它的组件。
属性代理组件继承自React.Component,通过传递给被包装的组件props得名
diff 的结果来更新 DOM。