亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

用React-Native+Mobx做一個迷你水果商城APP(附源碼)

 更新時間:2017年12月25日 12:01:16   投稿:mrr  
這篇文章主要介紹了用React-Native+Mobx做一個迷你水果商城APP,功能需要的朋友可以參考下

前言

最近一直在學習微信小程序,在學習過程中,看到了 wxapp-mall 這個微信小程序的項目,覺得很不錯,UI挺小清新的,便clone下來研究研究,在看源碼過程中,發(fā)現(xiàn)并不復雜,用不多的代碼來實現(xiàn)豐富的功能確實令我十分驚喜,于是,我就想,如果用react-native來做一個類似這種小項目難不難呢,何況,寫一套代碼還能同時跑android和ios(小程序也是。。。),要不寫一個來玩玩?有了這個想法,我便直接 react-native init 一個project來寫一下吧(๑•̀ㅂ•́)و✧

先來張動圖,dengdengdeng~~

 

技術框架以及組件

  • react "16.0.0"
  • react-native "0.51.0"
  • mobx: "3.4.1"
  • mobx-react: "4.3.5"
  • react-navigation: "1.0.0-beta.21"
  • react-native-scrollable-tab-view: "0.8.0"
  • react-native-easy-toast: "1.0.9"
  • react-native-loading-spinner-overlay: "0.5.2"

為什么要用Mobx?

Mobx是可擴展的狀態(tài)管理工具,比react-redux要簡單,上手也比較快。在這個小項目中,因為沒有后臺服務接口,用的都是本地的假數(shù)據(jù),為了模擬實現(xiàn) 瀏覽商品 =>加入購物車=>結賬=>清空購物車=>還原商品原始狀態(tài) 這么一個流程,便用Mobx來管理所有的數(shù)據(jù)以及商品的狀態(tài)(有沒有選中,有沒有加入購物車),這樣,所有的頁面都可以共享數(shù)據(jù)以及改變商品的狀態(tài),頁面之間的數(shù)據(jù)和商品狀態(tài)都是同步更新的。具體用Mobx怎么來實現(xiàn)這流程,在下面會分享使用感受和遇到的一些小坑。

開始

先react-native init一個project,然后用yarn或者npm裝好所有的依賴和組件。因為使用Mobx會用到ES7中裝飾器,所以還要安裝 babel-plugin-transform-decorators-legacy 這個插件,然后在.babelrc文件下添加一下內(nèi)容即可。

{ 
 "presets": ["react-native"], 
 "plugins": ["transform-decorators-legacy"]
}

項目結構

|-- android 
|-- ios
|-- node_modules
|-- src
 |-- common // 公用組件
 |-- img // 靜態(tài)圖片
 |-- mobx // mobx store
 |-- newGoods.js // 首頁新品數(shù)據(jù)
 |-- cartGoods.js // 購物車數(shù)據(jù)
 |-- categoryGoods.js // 分類頁數(shù)據(jù)
 |-- store.js // store倉庫,管理數(shù)據(jù)狀態(tài) 
 |-- scene 
 |-- Cart // 購物車頁面
 |-- Category // 分類頁
 |-- Home // 首頁
 |-- ItemDetail // 商品信息頁
 |-- Mine // 我的頁面 
 |-- Root.js // root.js主要內(nèi)容是配置react-navigation(導航器)
|-- index.js // 主入口

在Root.js文件中,有關react-navigation的配置和使用方法可以參考下官方文檔和這篇博客,里面都寫得十分詳細,有關react-navigation的疑問我都在這2篇文章中找到答案,在這里相關react-navigation配置,使用方法和項目里面頁面布局,組件寫法,在這里不打算細說,因為都比較簡單,更多的是討論Mobx實現(xiàn)功能的一些邏輯和方法, screen 文件夾下的組件都寫有注釋的(°ー°〃)

主要還是來聊聊Mobx吧

先來看看用Mobx實現(xiàn)的具體流程,看下面的動圖(⊙﹏⊙)

ps: 可能圖片太大,加載有點慢,請稍等......

 

1.數(shù)據(jù)存儲和獲取

這些都是用假數(shù)據(jù)來模擬實現(xiàn)的,在最開始,先寫好假數(shù)據(jù)的數(shù)據(jù)結構,例如:

"data":
 [{ 
 "name": '那么大西瓜',
 "price": '2.0', 
 "image": require('../img/a11.png'), 
 "count": 0, 
 "isSelected": true
 },...]

在 Mobx 文件夾下的 store.js, 在這里主要是存儲和管理app用到的所有商品的數(shù)據(jù),將 邏輯 和 狀態(tài) 從組件中移至一個獨立的,可測試的單元,這個單元在每個頁面下都可以用到

import { observable, computed, action } from 'mobx'
import cartGoods from './cartGoods'
import newGoods from './newGoods'import categoryGoods from './catetgoryGoods'
/** 
* 根store 
* @class RootStore 
* CartStore 為購物車頁面的數(shù)據(jù) 
* NewGoodsStore 為首頁的數(shù)據(jù) 
* categoryGoodsStore 為分類頁的數(shù)據(jù) 
*/
class RootStore { 
 constructor() { 
 this.CartStore = new CartStore(cartGoods,this) 
 this.NewGoodsStore = new NewGoodsStore(newGoods,this) 
 this.categoryGoodsStore = new categoryGoodsStore(categoryGoods,this) 
}}
Class CartStore{
 @observable allDatas = {} 
 constructor(data,rootStore) { 
 this.allDatas = data 
 this.rootStore = rootStore 
 }
}
Class NewGoodsStore{
 ...跟上面一樣
}
Class categoryGoodsStore{
 ...跟上面一樣
}
// 返回RootStore實例 
export default new RootStore()

這里用了 RootStore 來實例化所有了stores(購物車,首頁,分類頁分別擁有各自的store),

這樣,可以通過RootStore 來管理和操作stores,從而實現(xiàn)它們之間的相互通信,共享引用。

其次,存儲數(shù)據(jù)用了Mobx的@observable方法,就是把數(shù)據(jù)成為觀察者,當用戶操作視圖,導致數(shù)據(jù)發(fā)生變化時,配合react-mobx提供的@observer可以自動更新視圖,非常方便。

此外,為了把Mobx 的Rootstore注入到react-native的組件中,要通過 mobx-react 提供的 Provider 實現(xiàn),在 Root.js 下,我是這么寫的:

// 全局注冊并注入mobx的Rootstore實例,首頁新品,分類頁,商品詳情頁,購物車頁面都要用到store
import {Provider} from 'mobx-react'
// 獲取store實例
import store from './mobx/store' 
const Navigation = () => { 
 return ( 
 <Provider rootStore={store}> 
 <Navigator/> 
 </Provider> 
)}

把Rootstore實例注入到組件樹中后,那么,是不是在組件中直接使用 this.props.rootStore 就可以取到了呢?

‘'不是的”,我們還需要在要用到Rootstore的組件里,要加點小玩意,在 HomeScreen.js (首頁)中這么寫:

import { inject, observer } from 'mobx-react'
@inject('rootStore') // 緩存rootStore,也就是在Root.js注入的
@observerexport default class HomeScreen extends Component {
 ......
}

加上了 @inject('rootStore') ,我們就可以愉快地使用 this.props.rootStore 來拿到我們想要的數(shù)據(jù)啦^_^ ,同樣,在商品信息,分類頁,購物車頁面js下,也需要使用 @inject('rootStore') 來實現(xiàn)數(shù)據(jù)的獲取,然后再一步步地把數(shù)據(jù)傳到它們的子組件中。

2. 加入購物車的實現(xiàn)

在首頁和分類頁中,都可以點擊跳轉到商品信息頁,然后再加入到購物車里

 

實現(xiàn)方法 :

在itemDetail.js下,也就是商品信息頁面下,加入購物車的邏輯是這樣子的:

addCart(value) {
 if(this.state.num == 0) { 
 this.refs.toast.show('添加數(shù)量不能為0哦~')
 return; 
} 
// 加入購物車頁面的列表上 
// 點一次,購物車數(shù)據(jù)同步刷新 
this.updateCartScreen(value)
this.refs.toast.show('添加成功^_^請前往購物車頁面查看')
}
// 同步更新購物車頁面的數(shù)據(jù)
updateCartScreen (value) { 
 let name = this.props.navigation.state.params.value.name;
 // 判斷購物車頁面是否存在同樣名字的物品 
 let index;
 if(this.props.rootStore.CartStore)
 index = this.props.rootStore.CartStore.allDatas.data.findIndex(e => (e.name === name))
 // 不存在
 if(index == -1) {
 this.props.rootStore.CartStore.allDatas.data.push(value) 
 // 加入CartStore里
 // 并讓購物車icon更新
 let length = this.props.rootStore.CartStore.allDatas.data.length 
 this.props.rootStore.CartStore.allDatas.data[length - 1].count += this.state.num}
 else { 
 // 增加對應name的count
 this.props.rootStore.CartStore.allDatas.data[index].count += this.state.num 
 }}

簡單的說,先獲取水果的名稱name,然后再去判斷Mobx的CartStore里面是否存在同樣的名稱的水果,如果有就增加對應name的數(shù)量count,如果沒有,就往CartStore中增加數(shù)據(jù),切換到購物車頁面時,視圖會同步刷新,看到已加入購物車的水果。

3.改變商品狀態(tài)同步更新視圖

當用戶在購物車頁面操作商品狀態(tài)時,數(shù)據(jù)改變時,視圖會跟著同步刷新。

例如,商品的增加數(shù)量,減少數(shù)據(jù),選中狀態(tài),商品全選和商品刪除,總價格都會隨著商品的數(shù)量變化而變化。

 

圖又來了~~

實現(xiàn)上面的功能,主要用到了Mobx提供的action方法,action是用來修改狀態(tài)的,也就是用action來修改商品的各種狀態(tài)(數(shù)量,選中狀態(tài)...),這些action,我是寫在 store.js 的 CartStore類 中的,下面貼出代碼

// 購物車store
class CartStore {
 @observable allDatas = {}
 constructor(data,rootStore) { 
 this.allDatas = data
 this.rootStore = rootStore
}
 //加
 @action
 add(money) { 
 this.allDatas.totalMoney += money 
}
 // 減
 @action
 reduce(money) { 
 this.allDatas.totalMoney -= money 
}
 // checkbox true 
 @action
 checkTrue(money) {
 this.allDatas.totalMoney += money
 } 
 // checkbox false
 @action
 checkFalse(money) {
 if(this.allDatas.totalMoney <=0 ) 
 return 
 this.allDatas.totalMoney -= money
}
 // 全選
 @action
 allSelect() {
 if(this.allDatas.isAllSelected) {
 // 重置totalMoney 
 this.allDatas.totalMoney = 0 
 this.allDatas.data.forEach(e=> {
 this.allDatas.totalMoney += e.count * e.price})}
 else { 
 this.allDatas.totalMoney = 0 
}}
 // check全選 
 @action 
 check() { 
 // 所有checkbox為true時全選才為true 
 let allTrue = this.allDatas.data.every(v => ( v.isSelected === true ))
 if(allTrue) { 
 this.allDatas.isAllSelected = true 
 }else { 
 this.allDatas.isAllSelected = false 
}}
 // 刪 
 @action
 delect(name) { 
 this.allDatas.data = this.allDatas.data.filter (e => (e.name !== name ))
}
 // 總價格
 @computed get totalMoney() { 
 let money = 0;
 let arr = this.allDatas.data.filter(e => (e.isSelected === true))
 arr.forEach(e=> (money += e.price * e.count))
 return money
}}

所有修改商品狀態(tài)的邏輯都在上面代碼里面,其中,totalMoney是用了Mobx的@computed方法,totalMoney是依賴于CartStore的data數(shù)據(jù),也就是商品數(shù)據(jù),但data的值發(fā)生改變時,它會重新計算返回。如果了解vue的話,這個就相當于vue的計算屬性。

4.結算商品

商品結算和清空購物車的邏輯都寫在 CartCheckOut.js 里面,實現(xiàn)過程很簡單,貼上代碼吧:

// 付款
 pay() { 
 Alert.alert('您好',`總計:¥ ${this.props.mobx.CartStore.totalMoney}`, 
 {text: '確認支付', onPress: () => this.clear()},
 {text: '下次再買', onPress: () => null}],{ cancelable: false })}
 // 清空購物車 
 clear() { 
 this.setState({visible: !this.state.visible})
 setTimeout(()=>{ 
 this.setState({ loadText: '支付成功!歡迎下次光臨!' }) 
 setTimeout(()=> { this.setState({ visible: false },
 ()=>{ this.props.mobx.CartStore.allDatas.data = []
 // 把所有商品count都變?yōu)? 
 this.props.mobx.NewGoodsStore.allDatas.data.forEach(e=> e.count = 0)
 this.props.mobx.categoryGoodsStore.allDatas.data.forEach( e => { 
 e.detail.forEach(value => { value.count = 0 }) 
 })
 })},1500)},2000)}

這里主要用了setTimeout和一些方法來模擬實現(xiàn) 支付中 => 支付完成 => 清空購物車 => 還原商品狀態(tài)。

好了,這個流程就搞定了,哈哈。

5.遇到的小坑

1.我寫了一個數(shù)組的亂序方法,里面有用到 Array.isArray() 這個方法來判斷是否為數(shù)組,但是,我用這個亂序函數(shù)時,想用來搞亂store里面的數(shù)組時,發(fā)現(xiàn)一直沒有執(zhí)行,覺得很奇怪。然后我直接用 Array.isArray() 這個方法來判斷store里面的數(shù)組,返回的一直都是false。。。于是我就懵了。。。后來,我去看了Mobx官方文檔,終于找到了答案。原來,store里面存放的數(shù)組,并不是真正的數(shù)組,而是 obverableArray ,如果要讓 Array.isArray() 判斷為true,就要在取到store的數(shù)組時,加個. slice() 方法,或者 Array.from() 都可以。

2.同樣,也是obverableArray的問題。在購物車頁面時,我用了FlatList來渲染購物車的item,起初,當我增加商品到購物車,發(fā)現(xiàn)購物車頁面并沒有刷新。有了上面的踩坑經(jīng)驗,我認為是obverableArray引起的,因為FlatList的data接收的是real Array,于是,我用這樣的方法:

@computed get dataSource() { 
 return this.props.rootStore.CartStore.allDatas.data.slice();
}
...
<FlatList data={this.dataSource} .../>

于是,購物車視圖就可以自動地刷新了,在官方文檔上也有寫到。

3.還有一個就是自己粗心造成的。我寫完這個項目后,和朋友出去玩時,順便發(fā)給朋友看看,他在刪除商品時發(fā)現(xiàn),從上往下刪刪不了,從下往上刪就可以。后來我用模擬器測試也是如此,于是就去看看刪除商品的邏輯,發(fā)現(xiàn)沒有問題,再去看store的數(shù)據(jù),發(fā)現(xiàn)也是可以同步更新的,只是視圖沒有更新,很神奇,于是我又在FlatList去找原因,終于,原因找到了,主要是在keyExtractor里面,用index是不可以的,要用name來作為key,因為我刪除商品方法其實是根據(jù)name來刪的,而不是index,所以用index來作為FlatList的Item的key時是會出現(xiàn)bug的。

_keyExtractor = (item,index)=> { 
 // 千萬別用index,不然在刪購物車數(shù)據(jù)時,如果從第一個item開始刪會產(chǎn)生節(jié)點渲染錯亂的bug 
 return item.name
}

附上github項目地址:  github.com/shooterRao/…

總結

以上所述是小編給大家介紹的用React-Native+Mobx做一個迷你水果商城APP(附源碼),希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!

相關文章

  • React事件機制源碼解析

    React事件機制源碼解析

    這篇文章主要介紹了React事件機制源碼解析的相關資料,幫助大家更好的理解和學習使用React框架,感興趣的朋友可以了解下
    2021-04-04
  • react實現(xiàn)自定義拖拽hook

    react實現(xiàn)自定義拖拽hook

    這篇文章主要為大家詳細介紹了react實現(xiàn)自定義拖拽hook,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • react?fiber執(zhí)行原理示例解析

    react?fiber執(zhí)行原理示例解析

    這篇文章主要為大家介紹了react?fiber執(zhí)行原理示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-11-11
  • React路由渲染方式與withRouter高階組件及自定義導航組件應用詳細介紹

    React路由渲染方式與withRouter高階組件及自定義導航組件應用詳細介紹

    這篇文章主要介紹了React路由三種渲染方式、withRouter高階組件、自定義導航組件,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧
    2022-09-09
  • React?Native實現(xiàn)Toast輕提示和loading效果

    React?Native實現(xiàn)Toast輕提示和loading效果

    這篇文章主要介紹了React Native實現(xiàn)Toast輕提示和loading效果,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-09-09
  • React?Refs?的使用forwardRef?源碼示例解析

    React?Refs?的使用forwardRef?源碼示例解析

    這篇文章主要為大家介紹了React?之?Refs?的使用和?forwardRef?的源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-11-11
  • React之虛擬DOM的實現(xiàn)原理

    React之虛擬DOM的實現(xiàn)原理

    這篇文章主要介紹了React之虛擬DOM的實現(xiàn)原理分析,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • React中父子組件通信詳解

    React中父子組件通信詳解

    這篇文章主要介紹了React中父子組件通信詳解,在父組件中,為子組件添加屬性數(shù)據(jù),即可實現(xiàn)父組件向子組件通信,文章通過圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-08-08
  • React實現(xiàn)文件上傳和斷點續(xù)傳功能的示例代碼

    React實現(xiàn)文件上傳和斷點續(xù)傳功能的示例代碼

    這篇文章主要為大家詳細介紹了React實現(xiàn)文件上傳和斷點續(xù)傳功能的相關知識,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2024-02-02
  • 封裝一個最簡單ErrorBoundary組件處理react異常

    封裝一個最簡單ErrorBoundary組件處理react異常

    這篇文章主要介紹了一個處理react異常的ErrorBoundary組件,簡單實用,代碼詳細,對這個組件感興趣的朋友可以參考下
    2021-04-04

最新評論