新增特性/需要关注的点 | 说明 | 使用场景 or 备注 |
---|---|---|
函数组件 | 与类组件是等效的。类组件是有render 方法的,state数据改变就会重新渲染UI。function User(props) {return <h1>Hello, {props.name}</h1>}
|
函数组件是怎么做到数据变化重新渲染UI的?函数组件属于无状态组件 |
事件处理函数 | 不想通过bind 绑定this ,可以在 constructor 中绑定方法、使用箭头函数、继续使用 createReactClass 。 |
回调箭头函数作为 prop 传入子组件时,这些组件可能会进行额外的重新渲染。建议在构造器中绑定或使用 class fields 语法来避免这类性能问题。 |
向事件处理程序传递参数 | 使用箭头函数事件e 需显式传 |
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button> |
列表key 值 |
在列表项目顺序发生变化的情况下不建议使用索引,可能会引起组件状态的问题(原因??)。key 会传递给React 而不会传递给你的组件 |
深入解析为什么 key 是必须的深度解析使用索引作为 key 的负面影响 |
React.lazy |
接受一个函数,这个函数必须动态调用import 。能缩减bundle.js 的体积,并延时加载在初次渲染时未用到的组件 |
lazy 组件应在Suspense 组件中渲染,在等待lazy 组件渲染时做优雅降级。Suspense 组件的fallback 属性能接受任何在组件加载过程中你想展示的元素。 |
异常捕获边界 | 在模块加载失败时,用异常捕获边界来处理,能有更好的用户体验 | |
context |
React.createContext() 使用context 可以避免中间元素传递props
|
context 主要用于很多不同层级的组件需要访问同样的数据。需谨慎使用,会使组件的复用性变差 |
React.Fragment |
包裹一组子节点,但不返回本身的节点。减少不必要嵌套的组件。简写<> </> ,简写形式不支持key 或属性。 |
在写组件时,习惯用div 将作为最外层将所有的节点包起来,但这样会渲染出一些没必要的节点 |
ref |
该属性可以作为组件的标识,值可以通过 React.createRef() 创建,也可以是回调函数,回调函数它的参数是当前的DOM 元素,这个回调函数一般干的事情就是存储指向该DOM 元素的引用。回调函数会在组件挂载/卸载/ref 属性本身发生变化时调用。 |
也可以在实例组件中使用ref ,但实例组件的类型只能是class 组件。 |
refs 转发 |
可以将子组件的DOM 节点暴露给父组件。子组件需要用React.forwardRef() 来获取传递给它的ref ,然后转发到它渲染的DOM 节点上 |
可以获取到DOM 节点。直接传递值为React.createRef() 的ref只能取到实例组件 |
高阶函数HOC
|
是参数为组件,返回值为新组件的函数,不会改变传入的参数。被包装的组件最好透传props
|
HOC 是纯函数,没有副作用。可以参考React官方给出的例子:高阶函数;不要在render 组件中使用HOC ,会有性能问题,也会导致该组件及其所有子组件的状态丢失。这与React diff 算法有关 |
性能优化 | 1.生产环境使用React 2.明确什么时候需要更新组件时,使用shouldComponentUpdate 3.使用React.PureComponent 进行浅比较 |
React.PureComponent 中以浅层对比 prop 和 state 的方式来实现了shouldComponentUpdate
|
受控组件 | 需要value 属性和onChange 回调函数,需要通过state 来维护用户的输入 |
在表单有默认值或需要编辑的时候使用。 |
非受控组件 | 就像传统的HTML form ,用ref 来获取用户的输入 |
只需要用户输入,比如创建表单时使用。 |
ReactDOMServer |
提供了两个在node端和浏览器端均可使用的方法:renderToString 、renderToStaticMarkUp ;两个只能在node 端使用的方法renderToNodeStream 、renderToStaticNodeStream
|
后两种方法需要依赖只能在服务端使用的stream package
|
renderToString() |
可以使用此方法在服务端生成 HTML ,并在首次请求时将标记下发,以加快页面加载速度,并允许搜索引擎爬取你的页面以达到 SEO 优化的目的。 |
renderToStaticMarkup 与 renderToString 相似,但前者不会在 React 内部创建的额外DOM 属性,例如 data-reactroot 。如果你希望把 React 当作静态页面生成器来使用,此方法会非常有用,因为去除额外的属性可以节省一些字节。 |
dangerouslySetInnerHTML |
是 React 为浏览器 DOM 提供 innerHTML 的替换方案 |
|
Hook |
在不用编写class 组件的情况下使用state 和React 的一些其他特性 |
只能在函数组件中使用 。常用的Hooks 有useState 、UseEffect
|
如何实现一个纯函数??
1.通过自定义Hook实现组件之间重用状态逻辑。自定义Hook
更像是一种约定而不是功能。
还可以通过高阶组件和
render props
来实现组件之间重用状态逻辑
// 自定义Hook
import React, { useState, useEffect } from 'react';
function useFriendStatus(id){
const [isOnline, setIsOnline] = useState(null);
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(id, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(id, handleStatusChange);
}
})
return isOnline;
}
// 函数组件使用自定义``Hook``
function FriendStatus(props) {
const isOnline = useFriendStatus(props.friend.id);
if (isOnline === null) {
return 'Loading...';
}
return isOnline ? 'Online' : 'Offline';
}
2.使用Hook
实现倒计时
function CountDown() {
const [count, setCount] = useState(100);
useEffect(() => {
let timer;
if(count > 0) {
timer = setInterval(() => {
setCount(count - 1)
}, 1000);
}
return () => {
clearInterval(timer);
}
}, [count])
return (<div>
{count}
</div>)
}
3.用useState
初始化一个数据结构复杂的state
,在更新该数据中某个属性时,需要整体更新吗?当state
是对象时从,采用合并更新来更新state
对象,以防旧的属性丢失:
function UpdateState() {
const [ info, setInfo ] = useState({ name: '', age: 0 });
updateInfo(e) {
setInfo({
...info,
[e.target.name]: e.target.value,
})
}
....
}
4.生命周期方法如何对应到Hook
先回顾下最新的生命周期函数

生命周期函数 | Hook |
---|---|
constructor |
函数组件不需要构造函数。通过useState 来初始化state 。 |
getDerivedStateFromProps |
在渲染时安排一次更新。可以将上一轮的prop 存入state 以便比较 |
shouldComponentUpdate |
用React.memo 包裹一个组件来对它的props 进行浅比较,函数返回true 就会跳过更新 |
render |
就是函数组件本身 |
componentDidMount 、componentDidUpdate 、componentWillMount
|
利用useEffect Hook 可以做到 |
componentDidCatch 、componentDerviedFormError
|
暂无这些方法的Hook 等价写法 |
网友评论