React Hooks
所有组件都将是Function组件,这个函数却有自己的状态(count),同时它还可以更新自己的状态(setCount),除了useState这个hook外,还有很多别的hook,比如useEffect提供了类似于componentDidMount等生命周期钩子的功能,useContext提供了上下文(context)的功能等等。
useRef获取DOM元素和保存变量
useMemo优化React Hooks程序性能
import { useState } from 'react';
function Example() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
简单介绍下什么是hooks,hooks产生的背景?hooks的优点?
hooks是针对在使用react时存在以下问题而产生的:
1、组件之间复用状态逻辑很难,在hooks之前,实现组件复用,一般采用高阶组件和 Render Props,它们本质是将复用逻辑提升到父组件中,很容易产生很多包装组件,带来嵌套地域。
2、组件逻辑变得越来越复杂,尤其是生命周期函数中常常包含一些不相关的逻辑,完全不相关的代码却在同一个方法中组合在一起。如此很容易产生 bug,并且导致逻辑不一致。
3、复杂的class组件,使用class组件,需要理解 JavaScript 中 this 的工作方式,不能忘记绑定事件处理器等操作,代码复杂且冗余。除此之外,class组件也会让一些react优化措施失效。
针对上面提到的问题,react团队研发了hooks,它主要有两方面作用:
1、用于在函数组件中引入状态管理和生命周期方法
2、取代高阶组件和render props来实现抽象和可重用性
优点:
1、避免在被广泛使用的函数组件在后期迭代过程中,需要承担一些副作用,而必须重构成类组件,它帮助函数组件引入状态管理和生命周期方法。
2、Hooks 出现之后,我们将复用逻辑提取到组件顶层,而不是强行提升到父组件中。这样就能够避免 HOC 和 Render Props 带来的「嵌套地域」
3、避免上面陈述的class组件带来的那些问题
Hook有哪些优势
- 减少状态逻辑复用的风险
Hook和 Mixin在用法上有一定的相似之处,但是 Mixin引入的逻辑和状态是可以相互覆盖的,而多个 Hook之间互不影响,这让我们不需要在把一部分精力放在防止避免逻辑复用的冲突上。在不遵守约定的情况下使用 HOC也有可能带来一定冲突,比如 props覆盖等> 等,使用 Hook则可以避免这些问题。
- 避免地狱式嵌套
大量使用 HOC的情况下让我们的代码变得嵌套层级非常深,使用 Hook,我们可以实现扁平式的状态逻辑复用,而避免了大量的组件嵌套。
- 让组件更容易理解
在使用 class组件构建我们的程序时,他们各自拥有自己的状态,业务逻辑的复杂使这些组件变得越来越庞大,各个生命周期中会调用越来越多的逻辑,越来越难以维护。使用 Hook,可以让你更大限度的将公用逻辑抽离,将一个组件分割成更小的函数,而不是强制> 基于生命周期方法进行分割。
- 使用函数代替class
相比函数,编写一个 class可能需要掌握更多的知识,需要注意的点也越多,比如 this指向、绑定事件等等。另外,计算机理解一个 class比理解一个函数更快。Hooks让你可以在 classes之外使用更多 React的新特性。
虚拟Dom
虚拟DOM是在DOM的基础上建立了一个抽象层,对数据和状态所做的任何改动,都会被自动且高效的同步到虚拟DOM,最后再批量同步到DOM中。减少对真实Dom的操作,减少性能的消耗,保证非常高效的渲染。
因为改变真实dom,会导致整个dom树的重绘和回流
为什么虚拟 dom 会提高性能?(必考)
虚拟 dom 相当于在 js 和真实 dom 中间加了一个缓存,利用 dom diff 算法避免了没有必要的 dom 操作,从而提高性能。
用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档当中当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树差异把 2 所记录的差异应用到步骤 1 所构建的真正的 DOM 树上,视图就更新了。
react diff 原理(常考,大厂必考)
-
把树形结构按照层级分解,只比较同级元素。
-
给列表结构的每个单元添加唯一的 key 属性,方便比较。
-
React 只会匹配相同 class 的 component(这里面的 class 指的是组件的名字)
-
合并操作,调用 component 的 setState 方法的时候, React 将其标记为 dirty.到每一个事件循环结束, React 检查所有标记 dirty 的 component 重新绘制.
-
选择性子树渲染。开发人员可以重写 shouldComponentUpdate 提高 diff 的性能。
React 中 refs 的作用是什么?
Refs 是 React 提供给我们的安全访问 DOM 元素或者某个组件实例的句柄。我们可以为元素添加 ref 属性然后在回调函数中接受该元素在 DOM 树中的句柄,该值会作为回调函数的第一个参数返回:
React解决长列表方案
react-virtualized
react路由懒加载
react-loadable
简述react、redux、react-redux、redux-saga之间的关系
【react】
-
定位:React 是一个用于构建用户界面的JavaScript库。
-
特点:它采用声明范式来描述应用,建立虚拟dom,支持JSX语法,通过react构建组件,能够很好的去复用代码;
-
缺点:react抽离了dom,使我们构建页面变得简单,但是对于一个大型复杂应用来说,只有dom层的便捷是不够的,如何组织、管理应用的代码,如何在组件件进行有效通信,这些它都没有解决;因此,它还需要一个前端架构才能应对大型应用;
【redux】
-
定位:它是将flux和函数式编程思想结合在一起形成的架构;
-
思想:视图与状态是一一对应的;所有的状态,都保存在一个对象里面;a
-
API:
- store:就是一个数据池,一个应用只有一个;
- state:一个 State 对应一个 View。只要 State 相同,View 就相同。
- action:State 的变化,会导致 View 的变化。但是,用户接触不到 State,只能接触到 View。所以,State 的变化必须是 View 导致的。Action 就是 View 发出的通知,表示 State 应该要发生变化了。Action 是一个对象。其中的type``属性是必须的,表示 Action 的名称。其他属性可以自由设置。
- dispatch:它是view发出action的唯一方法;
- reducer:view发出action后,state要发生变化,reducer就是改变state的处理层,它接收action和state,通过处理action来返回新的state;
- subscribe:监听。监听state,state变化view随之改变;
【react-redux】
-
定位:react-redux是为了让redux更好的适用于react而生的一个库,使用这个库,要遵循一些规范;
-
主要内容
- UI组件:就像一个纯函数,没有state,不做数据处理,只关注view,长什么样子完全取决于接收了什么参数(props)
- 容器组件:关注行为派发和数据梳理,把处理好的数据交给UI组件呈现;React-Redux规定,所有的UI组件都由用户提供,容器组件则是由React-Redux自动生成。也就是说,用户负责视觉层,状态管理则是全部交给它。
- connect:这个方法可以从UI组件生成容器组件;但容器组件的定位是处理数据、响应行为,因此,需要对UI组件添加额外的东西,即mapStateToProps和mapDispatchToProps,也就是在组件外加了一层state;
- mapStateToProps:一个函数, 建立一个从(外部的)state对象到(UI组件的)props对象的映射关系。 它返回了一个拥有键值对的对象;
- mapDispatchToProps:用来建立UI组件的参数到store.dispatch方法的映射。 它定义了哪些用户的操作应该当作动作,它可以是一个函数,也可以是一个对象。
以上,redux的出现已经可以使react建立起一个大型应用,而且能够很好的管理状态、组织代码,但是有个棘手的问题没有很好地解决,那就是异步;
【redux-saga】:
-
定位:react中间件;旨在于更好、更易地解决异步操作(action);redux-saga相当于在Redux原有数据流中多了一层,对Action进行监听,捕获到监听的Action后可以派生一个新的任务对state进行维护;
-
特点:通过 Generator 函数来创建,可以用同步的方式写异步的代码;
-
API:
- Effect: 一个简单的对象,这个对象包含了一些给 middleware 解释执行的信息。所有的Effect 都必须被 yield 才会执行。
- put:触发某个action,作用和dispatch相同;
react中setState为什么是异步的
也可以同步,
如果不是经过react处理的是同步,
定时器,不是合成事件都是同步的
shouldComponentUpdate 是做什么的,(react 性能优化是哪个周期函数?)
shouldComponentUpdate 这个方法用来判断是否需要调用 render 方法重新描绘 dom。因为 dom 的描绘非常消耗性能,如果我们能在 shouldComponentUpdate 方法中能够写出更优化的 dom diff 算法,可以极大的提高性能。
为什么虚拟 dom 会提高性能?(必考)
虚拟 dom 相当于在 js 和真实 dom 中间加了一个缓存,利用 dom diff 算法避免了没有必要的 dom 操作,从而提高性能。
用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档当中当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树差异把 2 所记录的差异应用到步骤 1 所构建的真正的 DOM 树上,视图就更新了。