快速开发
- 表单操作
常规操作:一种是使用ref去得到dom结构,第二种是受控组件,都比较繁琐,写起来慢
推荐这个:让你的React表单操作更优雅(formik+yup),写起来快,唯一缺点就是需要额外引入包,增加项目体积,个人权衡吧
- swiper 组件
使用 react-id-swiper,有个坑,就是每个子项必须放在 div 里,此外用 containerClass 规定轮播大小时,需设置 overflow:hidden
import Swiper from 'react-id-swiper';
import 'react-id-swiper/lib/styles/css/swiper.css';
render() {
return (
<div className={styles.layout} WrapperEl="a">
<Swiper containerClass={styles.top}>
{config.top.map((value, key) => (
<div key={key}>
<TopItem item={value} />
</div>
))}
</Swiper>
<BottomLayout style={{ marginTop: '100px' }} config={config.buttom} />
</div>
);
}
- 图片画廊组件 react-image-gallery
import ImageGallery from 'react-image-gallery';
import 'react-image-gallery/styles/css/image-gallery.css';
<ImageGallery
ref={item => (this.imageGallery = item)}
items={imgs}
infinite={true}
showFullscreenButton={false}
showPlayButton={false}
renderLeftNav={this.renderLeftNav}
renderRightNav={this.renderRightNav}
autoPlay={false}
onThumbnailClick={this.onThumbnailClick}
onSlide={this.onSlide}
/>
// imgs
[
{
original: `${PREFIX_URL}image_set_default.jpg`,
thumbnail: `${PREFIX_URL}image_set_thumb.jpg`
},
{
original: `${PREFIX_URL}1.jpg`,
thumbnail: `${PREFIX_URL}1t.jpg`
},
{
original: `${PREFIX_URL}image_set_default.jpg`,
thumbnail: `${PREFIX_URL}image_set_thumb.jpg`
},
{
original: `${PREFIX_URL}1.jpg`,
thumbnail: `${PREFIX_URL}1t.jpg`
},
{
original: `${PREFIX_URL}image_set_default.jpg`,
thumbnail: `${PREFIX_URL}image_set_thumb.jpg`
},
{
original: `${PREFIX_URL}1.jpg`,
thumbnail: `${PREFIX_URL}1t.jpg`
}
],
https://www.infoq.cn/article/9r1KLbp3cpSBCN2GuEc3
性能优化
1、避免无意义渲染
- 有状态组件
通过 shouldComponentUpdate(nextProps) 控制渲染,也可用 PureComponent
// 只有 xxx 属性变化了才渲染
shouldComponentUpdate(nextProps){
if(this.props.xxx === nextProps.xxx){
return true
}
return false
}
- 无状态组件
React 16.6 以后,可以使用 React.memo 控制无状态组件的渲染
// 不使用 memo,则只要调用方组件重新渲染,该组件一定重新渲染,即使 title 并没有变化
const Title = props => <span>{props.title}</span>
export default Title
// 使用 memo,不管调用方组件是否重新渲染,只要 title 属性不变,则该组件不会重新渲染
const Title = props => <span>{props.title}</span>
export default React.memo(Title)
memo 接受第二个参数,控制组件何时重新渲染,函数返回false时会重新渲染
React.memo(C, (nextProps, prevProps) => {
// 做我们想做的事情,类似shouldComponentUpdate
})
2、reselect
当衍生的状态计算比较复杂时,可考虑使用 reselect 库
import { createSelector } from 'reselect'
fSelector = createSelector(
a => state.a,
b => state.b,
(a, b) => f(a, b)
)
hSelector = createSelector(
b => state.b,
c => state.c,
(b, c) => h(b, c)
)
...
function mapStateToProps(state) {
const { a, b, c } = state
return {
a,
b,
c,
fab: fSelector(state),
hbc: hSelector(state)
}
}
3、immutable
1、shouldComponentUpdate 比较的便利性
当给子组件传递复杂数据类型时,如果不用 immutable,则需要遍历该数据结构,对比前后的value是否一致,若用 immutable 则可以直接用 is 来对比
2、reducer 操作
用 immutable 可以用 state.get; state.set之类的方法设置状态,更加优雅
4、webpack 相关
1、路由级别的代码分割(目前已经可以使用Suspense和React.lazy替代该组件了)
// 1、写一个高阶组件作为包裹组件
// AsyncComponent.tsx
import * as React from 'react';
const asyncComponent = importComponent => {
class AsyncComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
component: null
};
}
async componentDidMount() {
const { default: component } = await importComponent();
this.setState({
component: component
});
}
render() {
const C = this.state.component;
return C ? <C {...this.props} /> : null;
}
}
return AsyncComponent;
};
export default asyncComponent;
// 2、使用 import 引入代替直接引入,特殊注释可以确定该包的名字
import MainLayout from './layouts/MainLayout';
const MainLayout = asyncComponent(() =>
import(/* webpackChunkName: "MainLayout" */ './layouts/MainLayout')
);
注意:需要使用插件 babel-plugin-syntax-dynamic-import
2、公共第三方模块的提取
module.exports = {
splitChunks: {
cacheGroups: {
// 首先: 打包react相关库文件中的文件(通过priority属性确定打包顺序)
reactBaseLib: {
name: 'ReactBaseLib',
test: module => /react|redux|prop-types/.test(module.context),
chunks: 'initial', // 表示从哪些chunks里面抽取代码
priority: 10
},
// 其次: 打包业务中公共代码(通过priority属性确定打包顺序)
common: {
name: 'common',
chunks: 'initial',
minSize: 1,
priority: 0
}
}
}
}
网友评论