使用生产版本
在部署应用时,请使用压缩过的生产版本(.min.js)。
<script src="https://unpkg.com/react@15/dist/react.min.js"></script>
<script src="https://unpkg.com/react-dom@15/dist/react-dom.min.js"></script>
对于create react app
正常开发 npm start
打包 npm run build
生产模式
注意:不要在开发环境使用生产环境的插件,因为他们会隐藏掉有用的react警告并使构建更慢。
插件 功能
uglify-js-brunch 创建最高效的Brunch版本
bundle-collapser envify uglify-js 创建最高效的browserify版本
rollup-plugin-commonjs rollup-plugin-replace rollup-plugin-uglify 创建最高效的Rollup生产版本
DefinePlugin,UglifyJsPlugin 创建最高效的webpack生产版本(适用于直接配置webpack)
开发模式
使用Chrome Performance 看性能
使用shouldComponentUpdate避免重新渲染
shouldComponentUpdate(nextProps, nextState) {
return true;
}
2.shouldComponentUpdate应用(后续补充)
3.要求只有在变化时更新
class CounterButton extends React.Component {
constructor(props) {
super(props);
this.state = {count: 1};
}
shouldComponentUpdate(nextProps, nextState) {
if (this.props.color !== nextProps.color) {
return true;
}
if (this.state.count !== nextState.count) {
return true;
}
return false;
}
render() {
return (
<button
color={this.props.color}
onClick={() => this.setState(state => ({count: state.count + 1}))}>
Count: {this.state.count}
</button>
);
}
}
进阶一:React.PureComponent
class CounterButton extends React.PureComponent {
constructor(props) {
super(props);
this.state = {count: 1};
}
render() {
return (
<button
color={this.props.color}
onClick={() => this.setState(state => ({count: state.count + 1}))}>
Count: {this.state.count}
</button>
);
}
}
点评:PureComponent类似于Component的语法糖,相当于自动进行shouldComponentUpdate,只不过仅进行浅比较(只比较值不比较引用,类似浅拷贝深拷贝原理)。因为它仅仅做一个浅比较,会忽略属性、状态的突变。即当属性、状态突变时,不能使用它。
如下:状态突变时,PureComponent没有检测到改变。
class WordAdder extends React.Component {
constructor(props) {
super(props);
this.state = {
words: ['marklar']
};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
// This section is bad style and causes a bug
const words = this.state.words;
words.push('marklar');
this.setState({words: words});
}
render() {
return (
<div>
<button onClick={this.handleClick} />
<ListOfWords words={this.state.words} />
</div>
);
}
}
PureComponent将会在this.props.words的新旧值之间做一个简单的比较。由于代码中words数组在WordAdder的handleClick方法中被改变了,尽管数组中的实际单词已经改变,this.props.words的新旧值还是相等的,因此即便ListOfWords具有应该被渲染的新单词,它还是不会更新。(即WordAdder中状态和ListOfWords绑定的状态指向同一个对象,即同一个引用地址,父子组件的值在同步更新即相等,,不会重新渲染)
解决上面问题思路:
进阶二:使用不会突变的数据
(1)不会突变的数据
重写会突变的状态
- concat重写(或slice),返回副本
handleClick() {
this.setState(prevState => ({
words: prevState.words.concat(['marklar'])
}));
}
- 扩展运算符
handleClick() {
this.setState(prevState => ({
words: [...prevState.words, 'marklar'],
}));
};
重写会突变的对象
function updateColorMap(colormap) {
colormap.right = 'blue';
}
- 不污染源对象的写法object.assign
function updateColorMap(colormap) {
return Object.assign({}, colormap, {right: 'blue'});
}
- 使用…避免对象的突变
function updateColorMap(colormap) {
return {...colormap, right: 'blue'};
}
备注:一般,Object.assign在ES6中,需要polyfill支持。但是creat-react-app生成项目里,默认情况下 Object.assign和spread对象都可以使用。
(2)不会突变的数据结构Immutable.js