效果圖展示
showmobx.gif
第一步,react-native init RN 創(chuàng)建一個新的項目。
第二步,導入mobx 和 mobx-react 。
npm install mobx --save
npm install mobx-react --save
第三步,導入babel組件,實現(xiàn)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 。
準備工作完成。現(xiàn)在寫入代碼。
import { observable, action, computed } from 'mobx';
import { observer } from 'mobx-react/native';
import StarRating from 'react-native-star-rating';
把剛剛引入的組件導入進來,這里注意mobx-react/native需要加上/native,否則無法識別。
定義mobx結(jié)構(gòu)。
class CartItem {
name="",
price = 0; //這里name 和 price 假設是從數(shù)據(jù)庫中取出
@observable
count=0 ; //數(shù)目。 這里的數(shù)目是被觀察者,也就是每次觀察者需要監(jiān)視我的每個item 的count是否被改變。
@observable
isSelected = false; //是否被選擇,同樣需要觀察者查看,當前的item是否被選擇,如果選擇,做什么操作,如果不選擇做什么操作。
@action
//這里的action,可以通過action來改變state,從而重新觸發(fā)渲染視圖的效果。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。如果不被選擇,那么當前的商品則數(shù)量是0。
select = ()=>{
this.isSelected = !this.isSelected;
if(this.isSelected){
++this.count;
}else{
this.count = 0;
}
}
}
定義Cart 加入數(shù)據(jù)。
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這個類,在構(gòu)造函數(shù)里,初始化我們的數(shù)據(jù)。
同時,我們不難發(fā)現(xiàn)。這里的定義了一個被觀察者的items的數(shù)組,這個是數(shù)據(jù)源。也是用來觀察的。computed是通過計算得到值,在mobx里還有autorun,套用官方文檔的話來說:
如果你想響應式的產(chǎn)生一個可以被其它 observer 使用的值,請使用 @computed,如果你不想產(chǎn)生一個新值,而想要達到一個效果,請使用 autorun。 舉例來說,效果是像打印日志、發(fā)起網(wǎng)絡請求等這樣命令式的副作用。
以上都是被觀察者。我們不難發(fā)現(xiàn)。在mobx 的結(jié)構(gòu)中,定義的是被觀察者,在定義的數(shù)據(jù)源中,定義的也是被觀察者。接下來,我們做觀察者應該做的事,
渲染組件。
我們定義個Item類。
Class Item extends Component{
//這里我們用到了小星星組件。在state定義小星星。
constructor(props){
super(props);
this.state = {
starCount: 0
};
}
//處理小星星的方法。
onStarRatingPress(rating) {
this.setState({
starCount: rating
});
}
//渲染每個Item的內(nèi)容。
render() {
const { data } = this.props;
//定義個data,在之后會調(diào)用這個組件,我們把需要用到的數(shù)據(jù)源放入就好。-->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>
);
});
定義我們需要展現(xiàn)的類。而這個類作為展示者,他是一個觀察者。
@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}>
{/*實現(xiàn)ListView的展示。*/}
<ListView
dataSource={this.ds.cloneWithRows(this.cart.items.slice(0))}
renderRow={this.renderRow}
/>
<Info cart={this.cart}/>
</View>
);
}
}