php react-native,React-Native+Mobx实现商城APP

这次给大家带来React-Native+Mobx实现商城APP,React-Native+Mobx实现商城APP的注意事项有哪些,下面就是实战案例,一起来看一下。

最近一直在学习微信小程序,在学习过程中,看到了 wxapp-mall

这个微信小程序的项目,觉得很不错,UI挺小清新的,便clone下来研究研究,在看源码过程中,发现并不复杂,用不多的代码来实现丰富的功能确实令我十分惊喜,于是,我就想,如果用react-native来做一个类似这种小项目难不难呢,何况,写一套代码还能同时跑android和ios(小程序也是。。。),要不写一个来玩玩?有了这个想法,我便直接

react-native init 一个project来写一下吧(๑•̀ㅂ•́)و✧

技术框架以及组件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是可扩展的状态管理工具,比react-redux要简单,上手也比较快。在这个小项目中,因为没有后台服务接口,用的都是本地的假数据,为了模拟实现

浏览商品 =>加入购物车=>结账=>清空购物车=>还原商品原始状态

这么一个流程,便用Mobx来管理所有的数据以及商品的状态(有没有选中,有没有加入购物车),这样,所有的页面都可以共享数据以及改变商品的状态,页面之间的数据和商品状态都是同步更新的。具体用Mobx怎么来实现这流程,在下面会分享使用感受和遇到的一些小坑。

开始

先react-native

init一个project,然后用yarn或者npm装好所有的依赖和组件。因为使用Mobx会用到ES7中装饰器,所以还要安装

babel-plugin-transform-decorators-legacy 这个插件,然后在.babelrc文件下添加一下内容即可。{

"presets": ["react-native"],

"plugins": ["transform-decorators-legacy"]

}

项目结构|-- 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 // 主入口

在Root.js文件中,有关react-navigation的配置和使用方法可以参考下官方文档和这篇博客,里面都写得十分详细,有关react-navigation的疑问我都在这2篇文章中找到答案,在这里相关react-navigation配置,使用方法和项目里面页面布局,组件写法,在这里不打算细说,因为都比较简单,更多的是讨论Mobx实现功能的一些逻辑和方法,

screen 文件夹下的组件都写有注释的(°ー°〃)

主要还是来聊聊Mobx吧

1.数据存储和获取

这些都是用假数据来模拟实现的,在最开始,先写好假数据的数据结构,例如:"data":

[{

"name": '那么大西瓜',

"price": '2.0',

"image": require('../img/a11.png'),

"count": 0,

"isSelected": true

},...]

在 Mobx 文件夹下的 store.js, 在这里主要是存储和管理app用到的所有商品的数据,将 逻辑 和 状态 从组件中移至一个独立的,可测试的单元,这个单元在每个页面下都可以用到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 来实例化所有了stores(购物车,首页,分类页分别拥有各自的store),

这样,可以通过RootStore 来管理和操作stores,从而实现它们之间的相互通信,共享引用。

其次,存储数据用了Mobx的@observable方法,就是把数据成为观察者,当用户操作视图,导致数据发生变化时,配合react-mobx提供的@observer可以自动更新视图,非常方便。

此外,为了把Mobx 的Rootstore注入到react-native的组件中,要通过 mobx-react 提供的 Provider 实现,在 Root.js 下,我是这么写的:// 全局注册并注入mobx的Rootstore实例,首页新品,分类页,商品详情页,购物车页面都要用到store

import {Provider} from 'mobx-react'

// 获取store实例

import store from './mobx/store'

const Navigation = () => {

return (

)}

把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

来拿到我们想要的数据啦^_^ ,同样,在商品信息,分类页,购物车页面js下,也需要使用 @inject('rootStore')

来实现数据的获取,然后再一步步地把数据传到它们的子组件中。

2. 加入购物车的实现

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

be6b32f1f1.gif

实现方法 :

在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 <=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

}}

所有修改商品状态的逻辑都在上面代码里面,其中,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();

}

...

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

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

// 千万别用index,不然在删购物车数据时,如果从第一个item开始删会产生节点渲染错乱的bug

return item.name

}

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

推荐阅读:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/525852.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

matlab axis 用法,MATLAB中regionprops的用法

Matlab图像处理函数&#xff1a;regionprops这里给出在Matlab图像处理工具箱中非常重要的一个图像分析函数&#xff1a;regionprops。顾名思义&#xff1a;它的用途是get the properties of region&#xff0c;即用来度量图像区域属性的函数。语法STATS regionprops(L,propert…

emlog_toolkit.php,emlog 4.0版本IIS6下伪静态划定规矩

emlog默许不能生成静态文件&#xff0c;不过彷佛有生成静态页面的相干插件&#xff0c;该插件博客吧先不研讨&#xff0c;本日博客簿要引见的是emlog 4.0版本在IIS6环境下的伪静态划定规矩&#xff0c;人人都晓得&#xff0c;经由过程伪静态能够让博客文章网址变得对搜索引擎越…

api.php phpcms,phpcms程序api怎么写接口

易站通&#xff0c;带你玩转PHPCMS建站程序&#xff0c;让你更快的熟悉该程序下面让我们来学习吧phpcms api怎么写接口&#xff1f;最近自己开发了一套crm系统&#xff0c;想着如果将来能卖出去&#xff0c;能不能再界面动态调用自己网站的推荐信息&#xff0c;算是一种广告吧&…

oracle 删除表 索引也会删除吗,Oracle 删除当前用户下所有的表、索引、序列

通过下面语句可以得到要删除Oracle的所有表、索引、序列... 的语句select drop table || table_name ||;||chr(13)||chr(10) from user_tables; --delete tablesselect drop view || view_name||;||chr(13)||chr(10) from user_views; --delete viewsselect drop sequence …

基于Java、Kafka、ElasticSearch的搜索框架的设计与实现

Jkes是一个基于Java、Kafka、ElasticSearch的搜索框架。Jkes提供了注解驱动的JPA风格的对象/文档映射&#xff0c;使用rest api用于文档搜索。项目主页&#xff1a;https://github.com/chaokunyang/jkes安装可以参考jkes-integration-test项目快速掌握jkes框架的使用方法。jkes…

Docker是传统的应用发布管理的终结者么?

译者注&#xff1a;使用Docker能真正改善传统的应用发布管理中遇到的问题么&#xff1f;以下是译文&#xff1a;自从2013年发布以来&#xff0c;Docker已经成为每一个操作管理者眼中的最爱。如果你一直与世隔绝&#xff0c;这里恰恰是你错过的部分。Docker是在一个操作环境地址…

基于Mesos/Docker构建数据处理平台

本文深入介绍了去哪儿网利用Mesos和Docker构建私有云服务的全过程&#xff0c;分享了从无状态应用向有状态应用逐步过度的经验与心得。平台概览2014年下半年左右&#xff0c;去哪儿完成了有关构建私有云服务的技术调研&#xff0c;并最终拍定了Docker/Mesos这一方案。下图1展示…

Mesos容器引擎的架构设计和实现解析

引言&#xff1a;提到容器&#xff0c;大家第一时间都会想到Docker&#xff0c;毕竟Docker是目前最为流行的容器开源项目&#xff0c;它实现了一个容器引擎&#xff08;Docker engine&#xff09;&#xff0c;并且为容器的创建和管理、容器镜像的生成、分发和下载提供一套非常便…

阿里的盔甲、未来20年发展的动力以及对未来的洞察

刚刚变身迈克尔杰克逊&#xff0c;用“经济体”、“理想主义”等词刷屏的马云又在教师节那天&#xff0c;赶到2017世界物联网博览会&#xff0c;为阿里的物联网站台。过去18年以来&#xff0c;淘宝网、天猫、聚划算、全球速卖通、阿里巴巴国际交易市场、1688、阿里妈妈、蚂蚁金…

MySQL InnoDB Memcached Plugin在Oray公司的实践

1、应用背景介绍我所在职的Oray是一家提供各种互联网服务且具有海量用户的企业&#xff0c;我们也一直在实践各种新技术新架构&#xff1b;缓存方面&#xff0c;我们从memcached、ttserver、redis等都有较多应用&#xff0c;其中redis在我们的dns体系中有着很深度的集成使用&am…

网易数据运河系统NDC设计与应用

【导语】 NDC是网易近一年新诞生的结构化数据传输服务&#xff0c;它整合了网易过去在数据传输领域的各种工具和经验&#xff0c;将单机数据库、分布式数据库、OLAP系统以及下游应用通过数据链路串在一起。除了保障高效的数据传输外&#xff0c;NDC的设计遵循了单元化和平台化的…

想学区块链技术?来这!

2017年&#xff0c;区块链技术可谓是最热的宠儿。在国务院日前印发《“十三五”国家信息化规划》中&#xff0c;区块链技术和人工智能、虚拟现实、大数据、无人驾驶交通工具、基因编辑等新多项高新技术创新被定义为战略性前沿技术超前布局&#xff0c;在政府大方向认同的情况下…

oracle管理员登录报错,关于Oracle使用管理员账号登录失败的问题

我在本地建的Oracle数据库在调试自己写的存储过程的时候提示缺少 debug connect session 权限&#xff0c;一般情况下根据这个提示直接用管理员账号登录进去&#xff0c;执行grant debug connect session to 你的用户名这样的sql就行了&#xff0c;但是问题来了&#xff0c;当我…

万字长文|深度剖析Service Mesh服务网格新生代Istio

Service Mesh新秀&#xff0c;初出茅庐便声势浩荡&#xff0c;前有Google&#xff0c;IBM和Lyft倾情奉献&#xff0c;后有业界大佬俯首膜拜&#xff0c;这就是今天将要介绍的主角&#xff0c;扛起Service Mesh大旗&#xff0c;掀起新一轮微服务开发浪潮的Istio&#xff01; 今天…

避免大规模故障的微服务架构设计之道

作者&#xff1a;Pter Mrton 译者&#xff1a;Jackyrong 本文首先介绍微服务架构存在的风险&#xff0c;然后针对如何避免微服务架构的故障&#xff0c;提出了多种有效的微服务架构中的方法和技术&#xff0c;其中例如服务降级、变更管理、健康检查和修复、断路器、限流器等。…

AI 线上峰会 | 人工智能技术解析与实战

10月28日&#xff0c; SDCC 2017“人工智能技术实战线上峰会”将在CSDN学院以直播互动的方式举行。 如今人工智能已不单单是发表学术论文、刷新正确率的竞赛&#xff0c;抑或全民参与的新闻事件&#xff0c;它早在为各行各业的先行者们创造着实实在在的利润和商业价值。而且&am…

五阿哥钢铁电商资深运维工程师手把手教你这样玩企业组网

虽说干的是信息化智能化的行当&#xff0c;但每个IT工程师都必定踩过“IT系统不智能”的坑。就拿企业组建局域网来说&#xff0c;为了对网络接入用户身份进行确认&#xff0c;确保用户权限不受办公地点变更的影响&#xff0c;许多IT工程师都习惯开启 “手动模式”和苦逼的“加班…

预告:Intel、Hulu、阿里、京东、携程等大数据实战直播

前言&#xff1a;由CSDN主办的SDCC 2017之大数据技术实战线上峰会将在CSDN学院举行。作为SD系列技术峰会的一部分&#xff0c;本次线上峰会秉承干货实料&#xff08;案例&#xff09;的内容原则&#xff0c;将邀请圈内顶尖的布道师、技术专家和技术引领者&#xff0c;共话大数据…

微服务应用容器化场景中常见问题总结

简介&#xff1a;云原生技术栈是下一代应用转型的必然选择&#xff0c;它包含了微服务架构&#xff0c;DevOps和容器技术。对于微服务架构来说&#xff0c;应用是“第一公民”&#xff0c;他逐渐蚕食原来底层软件或者硬件的功能&#xff0c;例如服务注册与发现以及负载均衡&…

Swarm的进化和大规模应用

目前在容器编排领域&#xff0c;Kubernetes、Mesos以及Swarm呈现“三分天下”的格局&#xff0c;各自都有着不同的应用场景。短期内&#xff0c;很难看到“一统天下”的局面&#xff0c;本文&#xff0c;来自阿里云高级专家陈萌辉将带你了解阿里内部在推行容器化过程中的一些着…