React 组件生命周期
在本章节中我们将讨论 React 组件的生命周期。
组件的生命周期可分成三个状态:
- Mounting:已插入真实 DOM
- Updating:正在被重新渲染
- Unmounting:已移出真实 DOM
生命周期的方法有:
- componentWillMount 在渲染前调用,在客户端也在服务端。
- componentDidMount : 在第一次渲染后调用,只在客户端。之后组件已经生成了对应的DOM结构,可以通过this.getDOMNode()来进行访问。 如果你想和其他JavaScript框架一起使用,可以在这个方法中调用setTimeout, setInterval或者发送AJAX请求等操作(防止异步操作阻塞UI)。
- componentWillReceiveProps 在组件接收到一个新的 prop (更新后)时被调用。这个方法在初始化render时不会被调用。
- shouldComponentUpdate 返回一个布尔值。在组件接收到新的props或者state时被调用。在初始化时或者使用forceUpdate时不被调用。
可以在你确认不需要更新组件时使用。 - componentWillUpdate在组件接收到新的props或者state但还没有render时被调用。在初始化时不会被调用。
- componentDidUpdate 在组件完成更新后立即调用。在初始化时不会被调用。
- componentWillUnmount在组件从 DOM 中移除之前立刻被调用。
在生命周期中的哪一步你应该发起 AJAX 请求
我们应当将AJAX 请求放到 componentDidMount 函数中执行,主要原因有下
- React 下一代调和算法 Fiber 会通过开始或停止渲染的方式优化应用性能,其会影响到 componentWillMount 的触发次数。对于 componentWillMount 这个生命周期函数的调用次数会变得不确定,React 可能会多次频繁调用 componentWillMount。如果我们将 AJAX 请求放到 componentWillMount 函数中,那么显而易见其会被触发多次,自然也就不是好的选择。
- 如果我们将AJAX 请求放置在生命周期的其他函数中,我们并不能保证请求仅在组件挂载完毕后才会要求响应。如果我们的数据请求在组件挂载之前就完成,并且调用了setState函数将数据添加到组件状态中,对于未挂载的组件则会报错。而在 componentDidMount 函数中进行 AJAX 请求则能有效避免这个问题
如何告诉 React 它应该编译生产环境版
通常情况下我们会使用 Webpack 的 DefinePlugin 方法来将 NODE_ENV 变量值设置为 production。编译版本中 React会忽略 propType 验证以及其他的告警信息,同时还会降低代码库的大小,React 使用了 Uglify 插件来移除生产环境下不必要的注释等信息
概述下 React 中的事件处理逻辑
为了解决跨浏览器兼容性问题,React 会将浏览器原生事件(Browser Native Event)封装为合成事件(SyntheticEvent)传入设置的事件处理器中。这里的合成事件提供了与原生事件相同的接口,不过它们屏蔽了底层浏览器的细节差异,保证了行为的一致性。另外有意思的是,React 并没有直接将事件附着到子元素上,而是以单一事件监听器的方式将所有的事件发送到顶层进行处理。这样 React 在更新 DOM 的时候就不需要考虑如何去处理附着在 DOM 上的事件监听器,最终达到优化性能的目的
React 中 keys 的作用是什么?
Keys是 React 用于追踪哪些列表中元素被修改、被添加或者被移除的辅助标识
- 在开发过程中,我们需要保证某个元素的 key 在其同级元素中具有唯一性。在 React Diff 算法中React 会借助元素的 Key 值来判断该元素是新近创建的还是被移动而来的元素,从而减少不必要的元素重渲染。此外,React 还需要借助 Key 值来判断元素与本地状态的关联关系,因此我们绝不可忽视转换函数中 Key 的重要性
hooks 怎么用
redux有什么缺点
- 一个组件所需要的数据,必须由父组件传过来,而不能像flux中直接从store取。
- 当一个组件相关数据更新时,即使父组件不需要用到这个组件,父组件还是会重新render,可能会有效率影响,或者需要写复杂的shouldComponentUpdate进行判断
2.React中setState的执行机制,如何有效的管理状态
React 中有三种构建组件的方式
React.createClass()、ES6 class 和无状态函数。
以前(在构造函数中)调用 super(props) 的目的是什么
在 super() 被调用之前,子类是不能使用 this 的,在 ES2015 中,子类必须在 constructor 中调用 super()。传递 props 给 super() 的原因则是便于(在子类中)能在 constructor 访问 this.props。
什么是 Virtual DOM?
Virtual DOM (VDOM) 是 Real DOM 的内存表示形式。UI 的展示形式被保存在内存中并与真实的 DOM 同步。这是在调用的渲染函数和在屏幕上显示元素之间发生的一个步骤。整个过程被称为 reconciliation。
Real DOM vs Virtual DOM
Real DOM |
Virtual DOM |
更新较慢 |
更新较快 |
可以直接更新 HTML |
无法直接更新 HTML |
如果元素更新,则创建新的 DOM |
如果元素更新,则更新 JSX |
DOM 操作非常昂贵 |
DOM 操作非常简单 |
较多的内存浪费 |
|
为什么虚拟 dom 会提高性能?(必考)
虚拟 dom 相当于在 js 和真实 dom 中间加了一个缓存,利用 dom diff 算法避免了没有必要的 dom 操作,从而提高性能。
用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档当中当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树差异把 2 所记录的差异应用到步骤 1 所构建的真正的 DOM 树上,视图就更新了。
状态和属性有什么区别?
state 和 props 都是普通的 JavaScript 对象。虽然它们都保存着影响渲染输出的信息,但它们在组件方面的功能不同。Props 以类似于函数参数的方式传递给组件,而状态则类似于在函数内声明变量并对它进行管理。
States vs Props
2. Conditions |
3. States |
4. Props |
5. 可从父组件接收初始值 |
6. 是 |
7. 是 |
8. 可在父组件中改变其值 |
9. 否 |
10. 是 |
11. 在组件内设置默认值 |
12. 是 |
13. 是 |
14. 在组件内可改变 |
15. 是 |
16. 否 |
17. 可作为子组件的初始值 |
18. 是 |
19. 是 |
- 20.⬆ 返回顶部
我们为什么不能直接更新状态?
如果你尝试直接改变状态,那么组件将不会重新渲染。
//Wrong
this.state.message = 'Hello world'
正确方法应该是使用 setState() 方法。它调度组件状态对象的更新。当状态更改时,组件通将会重新渲染。
//Correct
this.setState({ message: 'Hello World' })
注意: 你可以在 constructor 中或使用最新的 JavaScript 类属性声明语法直接设置状态对象。
回调函数作为 setState() 参数的目的是什么?
当 setState 完成和组件渲染后,回调函数将会被调用。由于 setState() 是异步的,回调函数用于任何后续的操作。
注意: 建议使用生命周期方法而不是此回调函数。
setState({ name: 'John' }, () => console.log('The name has updated and component re-rendered'))
Hooks 的 useState 相对于有状态组件 state 区别是什么?
class State
-
class State 必须是对象,而 useState 可以是基本类型、对象(任意类型的对象)
-
class 组件通过使用 this.setState.useState直接在函数组件内部使用
-
class State 会直接进行 merge 操作
useState
-
useState 创建的 state 会被 React 保管
-
当调用 set 方法修改 state 后,React 负责重新调用函数组件重新渲染组件
-
新的 state 会直接替换旧 state,不会直接发生 merge 操作
-
只有当 state 发生变更时,才会触发 re-render。React 通过 Object.is 方法判断 state 是否发生变更
-
函数组件多次调用 useState 表示会使用多个 state,每个 state 发生变更都会触发 re-render
-