Maison  >  Article  >  interface Web  >  React-Native+Mobx implémente l'application du centre commercial

React-Native+Mobx implémente l'application du centre commercial

php中世界最好的语言
php中世界最好的语言original
2018-04-13 15:04:253014parcourir

Cette fois, je vais vous proposer React-Native+Mobx pour implémenter l'application du centre commercial. Quelles sont les précautions pour implémenter l'application du centre commercial avec React-Native+Mobx. cas. Jetons un coup d'oeil.

J'ai récemment appris les mini-programmes WeChat. Au cours du processus d'apprentissage, j'ai vu wxapp-mall. J'ai trouvé ce projet d'applet WeChat très bon et l'interface utilisateur était assez petite et fraîche, alors je l'ai cloné pour l'étudier. En regardant le code source, j'ai trouvé que ce n'était pas compliqué de réaliser des fonctions riches. avec pas beaucoup de code. Alors, j'ai pensé, serait-il difficile d'utiliser React-Native pour créer un petit projet comme celui-ci. De plus, écrire un ensemble de code peut exécuter Android et iOS en même temps (il en va de même pour les petits projets) ? programmes...), que diriez-vous d'en écrire un ? Venez vous amuser ? Avec cette idée en tête, j'ai directement Écrivons un projet d'initialisation natif de réaction (๑•̀ㅂ•́)و✧

Cadre technique et composants

  • réagir "16.0.0"

  • réagir natif "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"

Pourquoi utiliser Mobx ?

Mobx est un outil de gestion d'état évolutif, plus simple que React-Redux et plus rapide à démarrer. Dans ce petit projet, comme il n'y a pas d'interface de service en arrière-plan, toutes les fausses données locales sont utilisées afin de simuler l'implémentation. Parcourir les articles =>Ajouter au panier=>Checkout=>Effacer le panier=>Restaurer les articles à leur état d'origine Dans un tel processus, Mobx est utilisé pour gérer toutes les données et l'état du produit (qu'il soit sélectionné, qu'il soit ajouté au panier), afin que toutes les pages puissent partager des données et modifier l'état du produit, et les données et les produits entre les pages peuvent être partagés. Le statut est mis à jour de manière synchrone. Plus précisément, comment utiliser Mobx pour mettre en œuvre ce processus, je partagerai ci-dessous mon expérience d'utilisation et quelques pièges rencontrés.

Démarrer

Premier natif de réaction Lancez un projet, puis utilisez fil ou npm pour installer toutes les dépendances et composants. Parce que l'utilisation de Mobx utilisera le décorateur dans ES7, vous devez l'installer babel-plugin-transform-decorators-legacy, puis ajoutez du contenu sous le fichier .babelrc.

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

Structure du projet

|-- android 
|-- ios
|-- node_modules
|-- src
 |-- common // 公用组件
 |-- img // 静态图片
 |-- mobx // mobx store
 |-- newGoods.js // 首页新品数据
 |-- cartGoods.js // 购物车数据
 |-- categoryGoods.js // 分类页数据
 |-- store.js // store仓库,管理数据状态 
 |-- scene 
 |-- Cart // 购物车页面
 |-- Category // 分类页
 |-- Home // 首页
 |-- ItemDetail // 商品信息页
 |-- Mine // 我的页面 
 |-- Root.js // root.js主要内容是配置react-navigation(导航器)
|-- index.js // 主入口

Dans le fichier Root.js, concernant la configuration et l'utilisation de React-Navigation, vous pouvez vous référer à la documentation officielle et à ce blog, qui sont écrits de manière très détaillée. J'ai trouvé des réponses aux questions sur React-Navigation dans ces deux articles. La configuration de navigation de réaction, les méthodes d'utilisation et la mise en page du projet et l'écriture des composants ne seront pas développées ici car elles sont relativement simples. Il s'agit plutôt de discuter de certaines logiques et méthodes des fonctions d'implémentation de Mobx. Les composants sous le dossier screen sont tous commentés (°ー°〃)

Parlons principalement de Mobx

1. Stockage et acquisition de données

Celles-ci sont simulées et implémentées à l'aide de fausses données. Au tout début, écrivez la structure des données fausses, par exemple :

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

. store.js dans le dossier Mobx, ici il stocke et gère principalement les données de tous les produits utilisés par l'application, et déplace la logique et l'état du composant vers une unité indépendante et testable. Cette unité est sur chaque page. ci-dessous

import { observable, computed, action } from 'mobx'
import cartGoods from './cartGoods'
import newGoods from './newGoods'import categoryGoods from './catetgoryGoods'
/** 
* 根store 
* @class RootStore 
* CartStore 为购物车页面的数据 
* NewGoodsStore 为首页的数据 
* categoryGoodsStore 为分类页的数据 
*/
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 est utilisé ici pour instancier tous les magasins (le panier, la page d'accueil et les pages de catégories ont leurs propres magasins),

De cette manière, les magasins peuvent être gérés et exploités via RootStore, leur permettant de communiquer entre eux et de partager des références.

Deuxièmement, la méthode @observable de Mobx est utilisée pour stocker les données, ce qui transforme les données en observateur. Lorsque l'utilisateur exploite la vue et provoque la modification des données, la vue peut être automatiquement mise à jour avec le @observer fourni par React-mobx. , ce qui est très pratique.

De plus, afin d'injecter le Rootstore de Mobx dans les composants natifs de React, il doit être implémenté via le fournisseur fourni par mobx-react sous Root.js, j'ai écrit ceci :

// 全局注册并注入mobx的Rootstore实例,首页新品,分类页,商品详情页,购物车页面都要用到store
import {Provider} from 'mobx-react'
// 获取store实例
import store from './mobx/store' 
const Navigation = () => { 
 return ( 
 <provider> 
 <navigator></navigator> 
 </provider> 
)}

. Après avoir injecté l'instance Rootstore dans l'arborescence des composants, peut-elle être obtenue directement en utilisant this.props.rootStore dans le composant ?

‘'不是的”,我们还需要在要用到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 来拿到我们想要的数据啦^_^ ,同样,在商品信息,分类页,购物车页面js下,也需要使用 @inject('rootStore') 来实现数据的获取,然后再一步步地把数据传到它们的子组件中。

2. 加入购物车的实现

在首页和分类页中,都可以点击跳转到商品信息页,然后再加入到购物车里

React-Native+Mobx implémente lapplication du centre commercial 

实现方法 :

在itemDetail.js下,也就是商品信息页面下,加入购物车的逻辑是这样子的:

addCart(value) {
 if(this.state.num == 0) { 
 this.refs.toast.show('添加数量不能为0哦~')
 return; 
} 
// 加入购物车页面的列表上 
// 点一次,购物车数据同步刷新 
this.updateCartScreen(value)
this.refs.toast.show('添加成功^_^请前往购物车页面查看')
}
// 同步更新购物车页面的数据
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的数量count,如果没有,就往CartStore中增加数据,切换到购物车页面时,视图会同步刷新,看到已加入购物车的水果。

3.改变商品状态同步更新视图

当用户在购物车页面操作商品状态时,数据改变时,视图会跟着同步刷新。

例如,商品的增加数量,减少数据,选中状态,商品全选和商品删除,总价格都会随着商品的数量变化而变化。

 

图又来了~~

实现上面的功能,主要用到了Mobx提供的action方法,action是用来修改状态的,也就是用action来修改商品的各种状态(数量,选中状态...),这些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  {
 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
}}

所有修改商品状态的逻辑都在上面代码里面,其中,totalMoney是用了Mobx的@computed方法,totalMoney是依赖于CartStore的data数据,也就是商品数据,但data的值发生改变时,它会重新计算返回。如果了解vue的话,这个就相当于vue的计算属性。

4.结算商品

商品结算和清空购物车的逻辑都写在 CartCheckOut.js 里面,实现过程很简单,贴上代码吧:

// 付款
 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都变为0 
 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和一些方法来模拟实现 支付中 => 支付完成 => 清空购物车 => 还原商品状态。

好了,这个流程就搞定了,哈哈。

5.遇到的小坑

1.我写了一个数组的乱序方法,里面有用到 Array.isArray() 这个方法来判断是否为数组,但是,我用这个乱序函数时,想用来搞乱store里面的数组时,发现一直没有执行,觉得很奇怪。然后我直接用 Array.isArray() 这个方法来判断store里面的数组,返回的一直都是false。。。于是我就懵了。。。后来,我去看了Mobx官方文档,终于找到了答案。原来,store里面存放的数组,并不是真正的数组,而是 obverableArray ,如果要让 Array.isArray() 判断为true,就要在取到store的数组时,加个. slice() 方法,或者 Array.from() 都可以。

2.同样,也是obverableArray的问题。在购物车页面时,我用了FlatList来渲染购物车的item,起初,当我增加商品到购物车,发现购物车页面并没有刷新。有了上面的踩坑经验,我认为是obverableArray引起的,因为FlatList的data接收的是real Array,于是,我用这样的方法:

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

于是,购物车视图就可以自动地刷新了,在官方文档上也有写到。

3.还有一个就是自己粗心造成的。我写完这个项目后,和朋友出去玩时,顺便发给朋友看看,他在删除商品时发现,从上往下删删不了,从下往上删就可以。后来我用模拟器测试也是如此,于是就去看看删除商品的逻辑,发现没有问题,再去看store的数据,发现也是可以同步更新的,只是视图没有更新,很神奇,于是我又在FlatList去找原因,终于,原因找到了,主要是在keyExtractor里面,用index是不可以的,要用name来作为key,因为我删除商品方法其实是根据name来删的,而不是index,所以用index来作为FlatList的Item的key时是会出现bug的。

_keyExtractor = (item,index)=> { 
 // 千万别用index,不然在删购物车数据时,如果从第一个item开始删会产生节点渲染错乱的bug 
 return item.name
}

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

Angular实现可添加删除与计算总金额效果插件

AngularJS实现猜数字小游戏

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn