原创文章转载请注明出处
想知道React Native是什么?先移步官网。另外,本文部分内容参考了搞定immutable.js。
熟悉React.js的都应该知道,React.js是一个UI = f(states)的框架,为了解决更新的问题,React.js使用了virtual dom,virtual dom通过diff修改dom,来实现高效的dom更新。听起来很完美吧,但是有一个问题。当state更新时,如果数据没变,你也会去做virtual dom的diff,这就产生了浪费,可以参考flummox这篇文章。
React Native的视图刷新机制和React一脉相承,官方文档中抛出了PureRenderMixin,因为PureRenderMixin只是简单的浅比较,不适用于多层比较,所以对于一些特殊情况解决不了问题,而react-immutable-render-mixin则可以直接比较immutable对象的hashcode,既可以进行深层次比较,又大大的提高了比较速度。另外,关于immutable.js的使用方法,这里不赘述,可以自行查阅官方文档。
直接上代码了。
package.json引入两个包
"immutable": "^3.8.1",
"react-immutable-render-mixin": "^0.9.7",
创建3个组件,ViewOne、ViewTwo、ViewThree。
/**
* ViewOne
* @flow
*/
import React, {Component} from 'react';
import {Text, View} from 'react-native';
import { shallowEqualImmutable } from 'react-immutable-render-mixin';
import * as StyleSheet from 'MallStyleSheet';
export default class ViewOne extends Component {
// 构造
constructor(props) {
super(props);
}
shouldComponentUpdate(nextProps, nextState) {
return !shallowEqualImmutable(this.props, nextProps)
|| !shallowEqualImmutable(this.state, nextState);
}
render() {
console.log('render in ViewOne');
return (
{this.props.content}
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#F5FCFF',
justifyContent: 'center',
alignItems: 'center'
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10
}
});
/**
* ViewTwo
* @flow
*/
import React, {Component} from 'react';
import {Text, View} from 'react-native';
import { shallowEqualImmutable } from 'react-immutable-render-mixin';
import * as StyleSheet from 'MallStyleSheet';
export default class ViewTwo extends Component {
// 构造
constructor(props) {
super(props);
}
shouldComponentUpdate(nextProps, nextState) {
return !shallowEqualImmutable(this.props, nextProps)
|| !shallowEqualImmutable(this.state, nextState);
}
render() {
console.log('render in ViewTwo');
return (
{this.props.content.name}
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#F5FCFF',
justifyContent: 'center',
alignItems: 'center'
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10
}
});
/**
* ViewThree
* @flow
*/
import React, {Component} from 'react';
import {Text, View} from 'react-native';
import { shallowEqualImmutable } from 'react-immutable-render-mixin';
import * as StyleSheet from 'MallStyleSheet';
export default class ViewThree extends Component {
// 构造
constructor(props) {
super(props);
}
shouldComponentUpdate(nextProps, nextState) {
return !shallowEqualImmutable(this.props, nextProps)
|| !shallowEqualImmutable(this.state, nextState);
}
render() {
console.log('render in ViewThree');
return (
{this.props.content.get('name')}
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#F5FCFF',
justifyContent: 'center',
alignItems: 'center'
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10
}
});
在render()函数打印了log,组件只是渲染了文本。
把组件插入到主界面。
/**
* NextScreen
* @flow
*/
import React, {Component} from 'react';
import {View} from 'react-native';
import Button from 'react-native-button';
import {Map} from 'immutable';
import * as StyleSheet from 'MallStyleSheet';
import {BlueNavBar} from 'MallNavBar';
import ViewOne from './ViewOne';
import ViewTwo from './ViewTwo';
import ViewThree from './ViewThree';
export default class NextScreen extends Component {
// 构造
constructor(props) {
super(props);
this.state = {
buttonTitle: '修改',
viewOne: 'ViewOne',
viewTwo: {name: 'ViewTwo'},
viewThree: Map({name: 'ViewThree'})
};
this._changState = this._changState.bind(this);
this._resetState = this._resetState.bind(this);
}
_changState() {
// 由于 immutable 内部使用了 Trie 数据结构来存储,只要两个对象的 `hashCode` 相等,值就是一样的。这样的算法避免了深度遍历比较,性能非常好。
this.setState({
buttonTitle: '再次修改',
viewOne: 'ViewOne changed!',
viewTwo: {name: 'ViewTwo changed'},
viewThree: this.state.viewThree.set('name', 'ViewThree changed')
});
}
_resetState() {
this.setState({
viewOne: 'ViewOne',
viewTwo: {name: 'ViewTwo'},
viewThree: this.state.viewThree.set('name', 'ViewThree')
});
}
render() {
return (
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#F5FCFF'
},
content: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
touch: {
width: 90,
height:32,
marginTop: 10,
alignItems: 'center',
justifyContent: 'center',
borderRadius:3,
backgroundColor:'purple'
},
textEnter: {
fontSize: 16,
color: 'white'
}
});
运行结果
初次渲染的时候,三个子组件都渲染了。
点击修改按钮,因为三个子组件的props都变了,一样重新做了渲染。
点击再次修改按钮,通过比较只有组件2的props发生了变化,故而只渲染了ViewTwo,就算点击n次再次修改,也只会重新渲染ViewTwo。
从代码中我们可以看到,
ViewOne
的props是字符串,因此浅比较可以对比出再次修改以后内容没有发生改变。
ViewTwo
的props是对象,浅比较只会比较到content的内容指向的对象,因为对象发生了改变,所以
ViewTwo
会重新渲染,尽管新对象的key和value值都没有变化。
ViewThree
使用了immutable对象作为props,基于hashcode的对比可以从深层次比较两个对象内容是否一致,从而快速准确的判断是否需要重新渲染。
我是咕咕鸡,一个还在不停学习的全栈工程师。
热爱生活,喜欢跑步,家庭是我不断向前进步的动力。