Fragment
react 组件中只能有一个根组件.
之前使用 div 包裹的方式会给 html 结构增加很多无用的层级
为了解决这个问题,可以使用 React.Fragment
javascript
function Hello() {
return (
// 渲染到页面之后,这个div就是一个多余的
<div>
<h1>fragment</h1>
<p>hello react</p>
</div>
);
}
// 将上面的写法,修改为下面的写法
function Hello() {
return (
// 这样就只会渲染h1和p
<React.Fragment>
<h1>fragment</h1>
<p>hello react</p>
</React.Fragment>
);
}
// 简写形式
function Hello() {
return (
// 这是React.Fragment的简写形式
<>
<h1>fragment</h1>
<p>hello react</p>
</>
);
}
React 性能优化
减轻 state 跟页面渲染无关的数据,不要放在 state 中(比如定时器的 id.不要放在 state 中)
- 可以有效减少页面重新渲染次数
shouldComponentUpdate (减轻不必要的重新渲染)
**组件更新的机制: **父组件重新渲染时,也会重新渲染子组件
如何避免不必要的重新渲染呢?
解决方式:使用钩子函数 shouldComponentUpdate(nextProps, nextState)
作用:通过返回值决定该组件是否重新渲染,返回 true 表示重新渲染,false 表示不重新渲染
触发时机:更新阶段的钩子函数,组件重新渲染前执行 (shouldComponentUpdate => render)
javascript// 父组件 class Far extends Component { state = { num: 0, }; // 返回min~max之间的随机整数(包含min和max) getRandomIntInclusive(min, max) { min = Math.ceil(min); max = Math.floor(max); return Math.floor(Math.random() * (max - min + 1)) + min; //含最大值,含最小值 } handle = () => { let num = this.getRandomIntInclusive(1, 3); this.setState({ num, }); }; //有效减少组件渲染次数 shouldComponentUpdate(props, state) { // this.state 原来的state // state 最新的state return this.state.num !== state.num; } render() { console.log("父组件渲染了"); return ( <div> <h1 onClick={this.handle}>Far组件</h1> <p>{this.state.num}</p> <Son num={this.state.num}></Son> </div> ); } } // 不管子组件有没有用到父组件的数据,只要父组件重新渲染了,子组件就会跟着渲染 // 子组件 class Son extends Component { //有效减少组件渲染次数 shouldComponentUpdate(props, state) { // this.props 原来的props // props 最新的props return props.num !== this.props.num; } render() { console.log("Son组件渲染了"); return ( <div> <h1>Son组件</h1> <p>{this.props.num}</p> </div> ); } }
纯组件 pureComponent
PureComponent 与 React.Component 功能相似,直接替换即可
区别:PureComponent 内部自动实现了 shouldComponentUpdate 钩子,不需要手动比较
原理:纯组件内部通过分别 对比 前后两次 props 和 state 的值,来决定是否重新渲染组件
**注意: **纯组件内部的对比是 shallow compare(浅层对比)
- 对于引用类型来说:只比较对象的引用(地址)是否相同
- 所以,state 或 props 中属性值为引用类型时,应该创建新数据,不要直接修改原数据
javascriptclass Far extends PureComponent { state = { obj: { num: 0, }, }; getRandomIntInclusive(min, max) { min = Math.ceil(min); max = Math.floor(max); return Math.floor(Math.random() * (max - min + 1)) + min; //含最大值,含最小值 } handle = () => { // 错误的写法 // 重新设置的obj和上一次的obj是同一个. // 组件不会重新渲染了 // let num = this.getRandomIntInclusive(1, 3) // let obj = this.state.obj 或者 let {obj} = this.state // obj.num = num // 正确的写法: let num = this.getRandomIntInclusive(1, 3); // 创建一个新的对象 let obj = { num }; console.log(num); this.setState({ obj, }); }; render() { console.log("父组件渲染了"); return ( <div> <h1 onClick={this.handle}>Far组件</h1> <p>{this.state.obj.num}</p> <Son num={this.state.obj.num}></Son> </div> ); } }