1、React 生命周期
-
挂载过程 - constructor() 完成 react 数据初始化 - componentWillMount() 组件已经初始化数据完成执行的逻辑,还未渲染 DOM ,常用于服务端渲染 - commponentDidMount() 组件第一次渲染完成执行的逻辑,DOM 节点已经生成 -
更新过程 - componentWillReceiveProps(nextProps) 接收父组件新的 props 重新渲染组件时执行的逻辑 - shouleComponentUpdate(nextProps, nextState) setState 以后 state 发生变化,组件进入重新渲染流程时执行的逻辑。在此生命周期中 return false 可以阻止组件的更新,主要用于性能优化 - componentWillUpdate(nextProps, nextState) shouleComponentUpdate 返回 true 以后,组件进入重新渲染流程时执行的逻辑 - render() 页面渲染时执行的逻辑, render 函数会将 jsx 贬义词函数并生成虚拟dom ,然后通过diff算法 比较更新前后的新旧 DOM 树,并渲染更改后的节点 -componentDidMount(prevProps, prevState) 重新渲染后执行的逻辑 -
卸载过程 - componentWillUnmount() 组件卸载钱的逻辑,例如 清楚组件的 setTimeout setinterval 等,或移除监听器 removeEventListener
更新
-
getDerviceStateFromProps(nextProps, prevState) 替代 componentWillReceiverProps() 老版本更新 state 和回调函数都在 componentWillReceiverProps 新版 将 更新 state 触发回调分布分配到了 getDervicesStateFromProps() 和 componentDidUpdate()中,是逻辑更加清晰 -
getSnapshotBeforeUpdate(prevProps, PrevState) 代替 componentWillUpdate() 在 React 开启渲染模式后,render 读取到的 DOM 元素状态并不是总和 commit 阶段相同,导致 componentDidUpdate 中使用 componentWillUpdate 中独到 DOM 元素不安全,因为值有可能被职位失效了 getSnaapsBeforeUpdate 会在最终的 render 前调用,保证 getSnaapsBeforeUpdate 读取到的 DOM 元素 和 componentDidUpdate 中的一直,此声明周期返回的任何值都将作为参数 传递给 componentDidUpdate()
2、聊一聊 hooks 如何处理生命周期
- 函数组件的本质是函数,没有state 的概念,隐藏不存在声明周期一说,仅仅是一个 render 函数而已
- 引入Hooks 嫩个让组件在不适用 class 的情况下拥有state,所以有了声明周期的概念,其实就是 useState useEffect 和 useLayoutEffect
-
useLayoutEffect 在处理DOM 的时候使用,否则会出现闪屏 能解决的原因是:useLayoutEffect 的callback 函数 会在 DOM 更新完之后立即执行,会在浏览器进行任何绘制之前进行,阻塞浏览器绘制
- class 和 hooks 对应
-
constructor -> useState -
getDerivedStateFromProps -> useState 里的update 函数 -
shouldComponentUpdate -> useMomo -
render -> 函数本身 -
componentDidMount -> useEffect -
componentDidUpdate -> useEffect -
componentWillUnmount -> useEffect 里的返回函数 -
componentDidCatch -> 无 -
getDerivedStateFromError -> 无
3、虚拟dom
虚拟 DOM 本质是 javascript 对象,是轻量级的 dom 描述,包含 tag props children 三个属性
- 虚拟dom 和 真实 DOM 性能比较
-
虚拟dom 和 diff 算法是为了解决 由命令式变成转变为声明式编程,数据驱动后所带来的性能问题。(直接操作dom的性能不一定会低于虚拟dom和diff算法) -
React 优点是无论怎么变换,借用 diff 算法,以最小代价更新 DOM, 方法是 在内存里,借用新的数据,刷新一个新的 虚拟 do m 树,然后新旧dom 比较,只更新差异部分
- 虚拟 dom 优点
-
牺牲了部分性能,增加了可维护性, -
实现 DOM 集中化操作,数据改变时,先对虚拟dom修改,在反映到真实dom -
使用函数式UI编程 -
能够跨端 -
组件抽离
4、虚拟 dom 原理
-
把树形结构按照层级分解,只比较同级元素 -
给列表结构的每个单元提那家唯一key,方便比较 -
React 职匹配相同 class 的 component 方便比较 -
合并操作,调用 component 的 setState 方法的时候,react 会将标记为 dirty 到没一个时间循环结束,React 检查所有标记 dirty 的component 重回完成 -
选择性子树渲染,可以通过 shouldCOmponentUpdate 提升 diff 性能, useMemo
缺点
-
首屏渲染大量dDOM 由于多一层虚拟 dom 计算,会比 innerHTML 慢 -
需要真用内存,多维护一套dom 的副本 -
如果是大量dom改变,会比较快,如果一直是 单一dom 变化,会重复大量计算,反而可能会慢
5、React 高阶组件
只是一个包装了 另外一个 React 组件的 React 组件
-
解决了有状态组件的复用性 -
共享组件建的行为 -
常用的 redux 的connect 函数
5、什么建议传递给 setState 的参数是一个 callback 而不是一个对象
-
因为 props 和 state 的更新是异步的,不能依赖他得知去计算下一个 state
6、React 中 refs 作用是什么
-
refs 是react 允许我们 访问 某个 DOM 元素或者某个组件实例的api -
可以为 元素添加 ref 然后在回调函数中接受钙元素在 dom 中的句柄,该值会作为回调函数的第一个参数返回
7、展示组件(Presentational component) 和容器组件(Container component) 之间不同
-
展示组件只关心展示内容,专门通过 props 接受数据和回调,本身无状态 -
容器组件则关心组件内部逻辑,会为展示组件或其他容器组件提供数据,行为,或调用 redux action 并将其作为回调提供给展示组件,容器组件一般是有状态的
8、类组件(class componet) 和函数组件(function component) 之间的不同
-
类组件不允许使用额外功能,如组件自身状态和声明周期,也能是组件直接访问store 并维持状态 -
组件仅仅接受props 并将组件渲染倒页面时候,就是无状态组件,就可以使用 纯函数 创建这样的组件
9、组件的状态(state)和属性(props)有何不同
-
state 是数据结构,用于组件挂在所需数据的默认值,state 可能会发生图标,比如用户操作等 -
props 则是组件的配置,有父组件传递给子组件,对于子组件来说 props 不可变, 组件不能给钱自身的props 但是可以吧子组件的props 统一管理 回调函数也可以通过props 传递
10、为何建议传递给 setState 的参数是一个 callback 而不是一个对象
因为 state props 的更新可能是异步的,不能作为依赖进行去计算下一个state
11、简述 flux 思想
FLux 最大的特显就是,单项数据流
- 用户访问View
- View 触发 action
- Dispatch 接收到 action 对 Store 进行相应的更新
- Store 更新之后,发出一个 onchange 事件
- View 接收到 onchange ,更新视图
12、简述 redux
redux 是应用数据流框架,解决了组件间状态共享问题
-
三个核心方法 action store render -
四个组成部分 action dispatch view store -
工作流程是,view 触发 action -> 派发器触发 action,让store 进行数据更新 -> 更新完成之后 store 发出 onchange -> view 接受 onchange 触发视图更新
新增 state 对状态管理更加明确
和 flux 区别
-
flux 有个多可以改变应用状态的store flux 中 dispatch 也被用来传递数据到注册的回调时间, -
但是 redux 只能定义一个 可更新的 store redux 吧store 和dispatch 合并,结构更加简单清晰
redux 有什么缺点
-
一个组件所需要的数据 必须有父组件专递,不能聪 store 中获取 -
有数据更新时,及时父组件不需要用的这个组件,父组件还是会重新render (可以通过 shouleComponentUpdate 判断,但是会复杂)