效果图展示
第一步,react-native init RN 创建一个新的项目。
第二步,导入mobx 和 mobx-react 。
npm install mobx --save
npm install mobx-react --save
第三步,导入babel组件,实现ES6修饰符的运用。
npm install babel-plugin-syntax-decorators --save
npm install babel-plugin-transform-decorators-legacy --save
第四步,.babelrc文件写入babel
{
"presets": ["react-native"],
"plugins": [
"syntax-decorators",
"transform-decorators-legacy"
]
}
第五补,小星星组件的导入
"react-native-star-rating": "^1.0.7",
"react-native-vector-icons": "^4.2.0",
"react-native-button": "^2.0.0",
小星星组件需要导入这三个必要的组件,其中 react-native-vector-icons需要react-native link react-native-vector-icons 。
准备工作完成。现在写入代码。
import { observable, action, computed } from 'mobx';
import { observer } from 'mobx-react/native';
import StarRating from 'react-native-star-rating';
把刚刚引入的组件导入进来,这里注意mobx-react/native需要加上/native,否则无法识别。
定义mobx结构。
class CartItem {
name="",
price = 0; //这里name 和 price 假设是从数据库中取出
@observable
count=0 ; //数目。 这里的数目是被观察者,也就是每次观察者需要监视我的每个item 的count是否被改变。
@observable
isSelected = false; //是否被选择,同样需要观察者查看,当前的item是否被选择,如果选择,做什么操作,如果不选择做什么操作。
@action
//这里的action,可以通过action来改变state,从而重新触发渲染视图的效果。inc是增加。如果点击增加,那么说明当前item是被选择的
inc = () =>{
++this.count;
this.isSelected = true;
}
@action
//同理这里dec也是减少的操作。
dec = ()=>{
if(this.count >1){
--this.count;
}else {
this.count = 0;
this.isSelected = false;
}
}
@action
//是否被选择的action。如果不被选择,那么当前的商品则数量是0。
select = ()=>{
this.isSelected = !this.isSelected;
if(this.isSelected){
++this.count;
}else{
this.count = 0;
}
}
}
定义Cart 加入数据。
class Cart{
@observable
items = [];
constructor(){
for (let i = 0; i < 150; i++) {
this.items.push(new CartItem(
`商品${i}`,
Math.floor(Math.random() * 100000)/100,
));
}
}
//通过计算得到的值。
@computed
get count(){
return this.items.reduce((a,b)=>a+b.count, 0);
}
@computed
get price(){
return this.items.reduce((a,b)=>a + (b.price * b.count),0);
}
}
这里我们定义Cart这个类,在构造函数里,初始化我们的数据。
同时,我们不难发现。这里的定义了一个被观察者的items的数组,这个是数据源。也是用来观察的。computed是通过计算得到值,在mobx里还有autorun,套用官方文档的话来说:
如果你想响应式的产生一个可以被其它 observer 使用的值,请使用 @computed,如果你不想产生一个新值,而想要达到一个效果,请使用 autorun。 举例来说,效果是像打印日志、发起网络请求等这样命令式的副作用。
以上都是被观察者。我们不难发现。在mobx 的结构中,定义的是被观察者,在定义的数据源中,定义的也是被观察者。接下来,我们做观察者应该做的事,
渲染组件。
我们定义个Item类。
Class Item extends Component{
//这里我们用到了小星星组件。在state定义小星星。
constructor(props){
super(props);
this.state = {
starCount: 0
};
}
//处理小星星的方法。
onStarRatingPress(rating) {
this.setState({
starCount: rating
});
}
//渲染每个Item的内容。
render() {
const { data } = this.props;
//定义个data,在之后会调用这个组件,我们把需要用到的数据源放入就好。-->const data = this.props.data.
return (
{/*给每个Item添加一个点击事件,用来判断是否被选择*/}
<TouchableOpacity onPress = {data.select}>
<View>
<View style={styles.item}>
{/*是否被选择,展示不同的页面效果*/}
<Text style = {data.isSelected ? styles.istrue :styles.isfalse}>{data.name}</Text>
<Text style={styles.price}>${data.price}</Text>
{/*加号的方法*/}
<Text style={styles.btn} onPress={data.inc}>+</Text>
<Text>{data.count}</Text>
{/*减号的方法*/}
<Text style={styles.btn} onPress={data.dec}>-</Text>
</View>
{/*渲染小星星的组件*/}
<View>
<StarRating
disabled={false}
maxStars={5}
rating={this.state.starCount}
selectedStar={(rating) => this.onStarRatingPress(rating)}
/>
</View>
</View>
</TouchableOpacity>
)
}
}
定义一个Info用来观察count和price
const Info = observer(function({cart}) {
return (
<Text>
Count: {`${cart.count}`} {'\n'}
Price: {cart.price.toFixed(2)} {'\n'}
</Text>
);
});
定义我们需要展现的类。而这个类作为展示者,他是一个观察者。
@observer
export default class MobxDemo extends Component {
实例化Cart 。
cart = new Cart();
// CartItem = new CartItem();
//定义ListView.DataSource
ds = new ListView.DataSource({
rowHasChanged: (v1, v2) => v1 !== v2,
});
//渲染组件renderRow
renderRow = (data) => {
return (
<Item data={data}/>
);
};
//返回
render() {
//const { data } = this.props;
return (
<View style={styles.container}>
{/*实现ListView的展示。*/}
<ListView
dataSource={this.ds.cloneWithRows(this.cart.items.slice(0))}
renderRow={this.renderRow}
/>
<Info cart={this.cart}/>
</View>
);
}
}