进入购物车,演练项目

By admin in 4858美高梅 on 2019年4月22日

  前天好不轻松把商品页和购物车功用弄出来了,在这些开拓进度中相遇有些小坑,举例购物车和商品页是分手多少个零部件的,没有运用到vue的双向数据绑定的表征,导致在操作加减商品数量时多个零部件的数量未有共同,后来本身就重写了二遍,好好的采用了vuex的景况保持,这一个事物确实很好用。先秀1段小编写的vuex代码吧!

  后天算是把商品页和购物车作用弄出来了,在那些开采进度中碰着一些小坑,举例购物车和商品页是分别五个零件的,未有运用到vue的双向数据绑定的特点,导致在操作加减商品数量时八个零件的数码尚未同步,后来自己就重写了一回,好好的使用了vuex的事态保持,那几个东西确实很好用。先秀一段小编写的vuex代码吧!

前言

4858美高梅 1

 1 //状态管理
 2 export default (Vuex) => {
 3     return new Vuex.Store({
 4         state: {
 5             totalMoney: 0, //已选购商品总价格
 6             productArray: [] //已选购商品数组
 7         },
 8         mutations: {
 9             setTotalMoney(state, num) { //设置商品总价格
10                 state.totalMoney = num;
11             },
12             mathTotalMoney(state) { //计算已选购商品总价格
13                 let total = 0;
14                 for (let i = 0; i < state.productArray.length; i++) {
15                     let item = state.productArray[i];
16                     total += (item.count * item.price);
17                 }
18                 state.totalMoney = total;
19             },
20             setProductArray(state, obj) { //商品放入或拿出购物车
21                 let index = -1;
22                 for (let i = 0; i < state.productArray.length; i++) {
23                     var item = state.productArray[i];
24                     if (obj.id == item.id) {
25                         index = i;
26                         break;
27                     }
28                 }
29                 if (index >= 0) {
30                     if (obj.count <= 0) {
31                         state.productArray.splice(index, 1);
32                     } else {
33                         state.productArray[index] = obj;
34                     }
35                 } else {
36                     state.productArray.push(obj);
37                 }
38             },
39             clearProduct(state) { //清空购物车
40                 state.productArray = [];
41             }
42         },
43         getters: {
44             getTotalMoney(state) { //获取商品总价格
45                 return state.totalMoney;
46             },
47             getProductArray(state) { //获取已选购商品
48                 return state.productArray;
49             },
50             getProductById: (state, getters) => (id) => { //根据ID获取已选商品
51                 for (let i = 0; i < state.productArray.length; i++) {
52                     var item = state.productArray[i];
53                     if (item.id == id) {
54                         return item;
55                     }
56                 }
57                 return false;
58             }
59         }
60     });
61 }
 1 //状态管理
 2 export default (Vuex) => {
 3     return new Vuex.Store({
 4         state: {
 5             totalMoney: 0, //已选购商品总价格
 6             productArray: [] //已选购商品数组
 7         },
 8         mutations: {
 9             setTotalMoney(state, num) { //设置商品总价格
10                 state.totalMoney = num;
11             },
12             mathTotalMoney(state) { //计算已选购商品总价格
13                 let total = 0;
14                 for (let i = 0; i < state.productArray.length; i++) {
15                     let item = state.productArray[i];
16                     total += (item.count * item.price);
17                 }
18                 state.totalMoney = total;
19             },
20             setProductArray(state, obj) { //商品放入或拿出购物车
21                 let index = -1;
22                 for (let i = 0; i < state.productArray.length; i++) {
23                     var item = state.productArray[i];
24                     if (obj.id == item.id) {
25                         index = i;
26                         break;
27                     }
28                 }
29                 if (index >= 0) {
30                     if (obj.count <= 0) {
31                         state.productArray.splice(index, 1);
32                     } else {
33                         state.productArray[index] = obj;
34                     }
35                 } else {
36                     state.productArray.push(obj);
37                 }
38             },
39             clearProduct(state) { //清空购物车
40                 state.productArray = [];
41             }
42         },
43         getters: {
44             getTotalMoney(state) { //获取商品总价格
45                 return state.totalMoney;
46             },
47             getProductArray(state) { //获取已选购商品
48                 return state.productArray;
49             },
50             getProductById: (state, getters) => (id) => { //根据ID获取已选商品
51                 for (let i = 0; i < state.productArray.length; i++) {
52                     var item = state.productArray[i];
53                     if (item.id == id) {
54                         return item;
55                     }
56                 }
57                 return false;
58             }
59         }
60     });
61 }

方今直接在念书微信小程序,在读书进程中,看到了 wxapp-mall
那些微信小程序的品类,感觉很不错,UI挺小清新的,便clone下来商讨切磋,在看源码进度中,发现并不复杂,用不多的代码来贯彻拉长的效率实在令自个儿万分欢快,于是,小编就想,假诺用react-native来做三个近乎那种小项目难简单呢,何况,写一套代码还是能够同时跑android和ios(小程序也是。。。),要不写3个来娱乐?有了那个主见,笔者便径直
react-native init 一个project来写一下吧(๑•̀ㅂ•́)و✧

显示器快速照相 201捌-0二-2八 早上十.2柒.3五.png

  可是本身总认为,小编这么的用法有点不太对的。贴个代码,希望有权威指引下,笔者那样使用vuex可取不。

  不过本人总以为,作者这么的用法有点不太对的。贴个代码,希望有高手辅导下,作者那样使用vuex可取不。

先来张动图,dengdengdeng~~

进程分析

1.首先购物车弹窗是三个组件,因为会现身在区别的页面中。
二.因为不少零部件会用到购物车数据,所以集合置于vuex中。

 1 import Vue from 'vue';
 2 import App from './App';
 3 import router from './router';
 4 import VueResource from 'vue-resource';
 5 import Vuex from 'vuex';
 6 import vuex_store from './store';
 7 
 8 Vue.use(VueResource);
 9 Vue.use(Vuex);
10 
11 new Vue({
12     el: '#app',
13     router,
14     template: '<App/>',
15     components: { App },
16     store: vuex_store(Vuex)
17 });
 1 import Vue from 'vue';
 2 import App from './App';
 3 import router from './router';
 4 import VueResource from 'vue-resource';
 5 import Vuex from 'vuex';
 6 import vuex_store from './store';
 7 
 8 Vue.use(VueResource);
 9 Vue.use(Vuex);
10 
11 new Vue({
12     el: '#app',
13     router,
14     template: '<App/>',
15     components: { App },
16     store: vuex_store(Vuex)
17 });

4858美高梅 2 

落到实处步骤解析

  上面代码正是进口文件,笔者前几日 vuex
对象再传播本身要好写的不胜store模块中。接着继续说自家的商品页和购物车吧,贴个动图给大看看效果如何。

  上边代码正是进口文件,小编前天 vuex
对象再传播自个儿要好写的可怜store模块中。接着继续说自个儿的商品页和购物车呢,贴个动图给大看看效果怎么着。

技艺框架以及组件

壹、参加购物车

  1. 将购物车数量统壹放在vuex中:
    state里放置三个数组:carPanelData,里面放置购物车数量。

// 购物车商品数据
state: {
    carPanelData: []
}
  1. 往购物车里push数据:在mutation里面改造state数据。
    思路进入购物车,演练项目。:首先需求将点击进入购物车的每一条数据加陆特性质:count,计数,然后将那条点击的商品数量push到state中,当然,首先是急需先用商品ID和state里的物品ID比对,如若没有就push,如若有了,就计数。
    以下是代码思路

mutations:
    addCarPanelData(state,加入购物车的数据data){
        //循环carPanelData购物车数据
        //如果商品ID存在(购物车的id和传进来的ID比对),就设置count++
        //设置开关false
===================================================================
        **注意** : 如果上面的条件成立,以下是不执行的,所以可以设置一个开关bOff
        //如果开关值为true
        //否则就是商品ID不存在,设置一个新的变量goodsData = 传进来的data;
        //Vue.set(goodsData,'count',1):为这个变量设置count属性,值为1;
        //将这个goodsData,push到carPanelData中;              
}
--------------------------------------------------------------
 mutations: {
    addCarPanelData (state,data) {
      let bOff = true
      state.carPanelData.forEach((goods) => {
        if (goods.sku_id === data.sku_id) {
          goods.count++
          bOff = false
        }
      })
      if (bOff) {
        let goodsData = data
        Vue.set(goodsData,'count',1)
        state.carPanelData.push(goodsData)
      }
      console.log(state.carPanelData)
    }
  }
  1. 在商品页选择了商品,点击进入购物车按键:那时,将那条数据传给vuex,记录到state中(mutation里面早已对该逻辑举行了管理)
    要点 : 记住vuex的思索,要想更动state,必须交给mutation。

 methods:{
       addCarPanelHandel(data){
        //改变state,必须提交mutation,并将此条数据传给vuex
          this.$store.commit('addCarPanelData',data)
        }
}
  1. 此刻已经主导造成了购物车的逻辑,上面,我们把购物车单独出来做成组件:car-panel。
    以此时候就足以把有关数据绑定在购物车了。
    要点 :怎么着赚取在购物车组件内拿到vuex数据?
    用computed即可。

//相应的绑定代码=示例
<a href="#/item/100027401">{{item.title}})</a>
//获取vuex数据
computed : {
        carPanelData(){
            return this.$store.state.carPanelData
        },
        count(){
            return this.$store.getters.totleCount
        },
        totle(){
             return this.$store.getters.totlePrice
        }
}
  1. 终极,对购物车中的商品数量和商品总价总括。
    在vue中,大家供给对变量进行进一步管理,能够献身computed里,不建议坐落模板中,同样,vuex中,state中的状态纵然急需进一步处理,我们可以放入getters.

getters:{
    // 购物车商品数量计算
    totleCount (state) {
      let count = 0
      state.carPanelData.forEach((goods) => {
        count += goods.count
      })
      return count
    },
    // 总价格
    totlePrice (state) {
      let price = 0
      state.carPanelData.forEach((goods) => {
        price += goods.price * goods.count
      })
      return price
    }
  }

============================================================

4858美高梅 3

4858美高梅 4

  • 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”

迄今,已经完成了加购物车,并且总计数据和金额。

  商品也和购物车效率,目前就那个了。注重还是在布局上,js上的逻辑都简单。能够上本人的github获取源码看看咯。

  商品也和购物车功用,目前就这么些了。着重照旧在布局上,js上的逻辑都轻便。能够上自身的github获取源码看看咯。

怎么要用Mobx?

二、购物车删除

一同始小编的笔触是
1、删除数据一定是要改成state,改动state确定是急需提交mutation,所以删除的连锁逻辑形式应该写在mutation;
2、当时本人的标题是何许晓得删除的是哪一条数据?
4858美高梅 ,由此学习,弄精晓了,今后此类须求,都和投入购物和思路是一致的,都以经过对照删除的此时此刻的ID和数量里的具备ID进行比对,就知晓是剔除具体哪条数据了。
三、那么本人需求记住,当前甄选的是哪条数据,都以经过在剔除的点击方法对应的轩然大波里,参数中传递当前数据(商品ID)就能够。那是三个思路,要求记住
切切实实落到实处步骤总结
点击购物车页面的删减商品开关,绑定三个删减方法,参数字传送入当前被点击的货品ID,在这几个法子里调用mutation里面的去除商品方法:

  1. 首先必要循环state的购物车数量;
  2. 比对每1项的货品ID是还是不是和近日传出的ID同样,如若是壹模同样的那么就return,不再接续循环了;
  3. 在state的购物车数量里删除那项ID一样的数额。

//mutation 
delCarPanelData (state,id) {
      state.carPanelData.forEach((goods,index) => {
        if (goods.sku_id === id) {
          state.carPanelData.splice(index,1)
          return
        }
      })
}
//购物车组件中
methods: {
        delCarPanelHandel(id){
            this.$store.commit('delCarPanelData',id)
        }
}
<div class="del-btn"  @click="delCarPanelHandel(item.sku_id)"> 删除 </div>

  源码地址:

  源码地址:

Mobx是可增加的意况管理工科具,比react-redux要轻巧,上手也比不慢。在那么些小品种中,因为尚未后台服务接口,用的都以地面包车型地铁假数据,为了模仿实现浏览商品 =>参与购物车=>买单=>清空购物车=>还原商品原始状态
这么三个流程,便用Mobx来治本全数的数量以及商品的景况(有未有入选,有未有进入购物车),那样,全部的页面都足以共享数据以及更改商品的意况,页面之间的数额和商品状态都是联合签名更新的。具体用Mobx怎么来贯彻那流程,在底下会分享应用感受和蒙受的片段小坑。

三、购物车商品数量限制

思路 : 那类展现隐藏的案例,都以安装变量属性的ture/false
第3是有3个弹窗组件,当商品数量超越最大值得时候,那几个组件必要弹出。
多少中早就有了最大值 : limit_num。
在state中定义3个变量:maxOff :false
,默许不显得,当购物车中物品增添的时候,比对当前货色的多寡是还是不是已经高于了limit_num,倘若是,就让那几个弹窗出来,也正是在mutation中装置该属性为true。

  • 商品数量超越后展现弹窗

 // 加入购物车
    addCarPanelData (state,data) {
      state.carPanelData.forEach((goods) => {
        if (goods.sku_id === data.sku_id) {
          goods.count++
          bOff = false
          //比较当前商品的数量和数据中的商品最大购买数量
          if (goods.count > goods.limit_num) {
            goods.count--
            state.maxOff = true
          }
        }
      })
 }
//组件中
<div id="prompt" v-if="maxOff">

 computed: {
        maxOff(){
            return this.$store.state.maxOff
        }
  }
  • 闭馆弹窗

//mutations
   closePrompt (state) {
     state.maxOff = false
   }
//组件中
  methods : {
       closePrompt(){
           this.$store.commit('closePrompt')
       }
   }

开始

肆、购物车彰显隐藏

思路: 一样的,那类显示隐藏,供给安装一个按键,去切换按键就可以。

 state: {
    carPanelData: [],
    maxOff : false, // 弹窗开关
    carShow : false, // 购物车开关
    carTimer : null // 购物车定时器
  },
 // 购物车显示
    showCar (state) {
      clearTimeout(state.carTimer)
      state.carShow = true
    },
    // 购物车隐藏
    hideCar (state) {
      state.carTimer = setTimeout(() => {
        state.carShow = false
      },1000)
    }
===================
//组件中
 methods: {
        // 显示购物车
        showCar(){
           this.$store.commit('showCar')
        },
        // 隐藏购物车
        hideCar(){
          this.$store.commit('hideCar')
        }
 }

先react-native
init三个project,然后用yarn只怕npm装好全体的借助和零部件。因为运用Mobx会用到ES柒中装饰器,所以还要设置
babel-plugin-transform-decorators-legacy
这几个插件,然后在.babelrc文件下增加一下剧情就可以。

肆、购物车小球效果

思路:用的vue的transtion钩子函数,原理正是先把小球写死到购物车,点击的时候瞬间移入到必要的地方,然后做一个过渡动画就能够,到场贝塞尔曲线。

state: {
    ball: { // 购物车小球
      show: false,
      el: null, // 点击的是哪个购物车按钮
      img: ''
}
mutations: {
    // 加入购物车
    addCarPanelData (state,data) {
      // 加上这个条件,确保小球飞完再添加
      if (!state.ball.show) {
        // 显示购物车
        state.carShow = true
        let bOff = true
        state.carPanelData.forEach((goods) => {
          // 比对ID,相同就说明购物车已存在此商品,数量增加
          if (goods.sku_id === data.sku_id) {
            goods.count++
            bOff = false
            if (goods.count > goods.limit_num) {
              goods.count--
              state.maxOff = true
              return
            }
            // 加入购物车,小球显示
            state.ball.show = true
            state.ball.img = data.ali_image
            // 通过event对象获取到当前点击的按钮
            state.ball.el = event.path[0]
          }
        })
        // 商品不存在,就往数组里新增商品数据
        if (bOff) {
          let goodsData = data
          Vue.set(goodsData,'count',1)
          state.carPanelData.push(goodsData)
          // 加入购物车,小球显示
          state.ball.show = true
          state.ball.img = data.ali_image
          // 通过event对象获取到当前点击的按钮
          state.ball.el = event.path[0]
        }
        console.log(event)
      }
    }
============
//组件内
 // 小球进入前,初始化
      beforeEnter(el){
        // 获取按钮的位置
        let rect = this.ball.el.getBoundingClientRect()
        // 获取购物车
        let rectEl = document.getElementsByClassName('ball-rect')[0].getBoundingClientRect()
        // 获取小球
        let ball = document.getElementsByClassName('mask-item')[0]
        //计算按钮和购物车的差值 : 购物车的中心点到左侧的距离 - 按钮中心点到左侧的距离
        let x = (rectEl.left + 16) - (rect.left + rect.width/2)
        let y = rect.top + rect.height/2 - rectEl.top + 5 - 16
        //计算小球和包着小球的父级的位置
        ball.style.transform = 'translate3d(-'+x+'px,0,0)'
        el.style.transform = 'translate3d(0,'+y+'px,0)'

        ball.src = this.ball.img
        console.log(this.ball.img)
      },
      //开始运动
      enter (el){
        let a = el.offsetHeight
        // 获取小球
        let ball = document.getElementsByClassName('mask-item')[0]
        el.a = a //避免变量没有使用,eslint报错
        el.style.transform = "translate3d(0,0,0)"
        ball.style.transform = "translate3d(0,0,0)"
      },
      // 结束,让小球隐藏
      afterEnter (el){
        this.ball.show = false
      }
    }
===========
    <transition 
      name="ball" 
      v-on:before-enter="beforeEnter" 
      v-on:enter="enter" 
      v-on:after-enter="afterEnter" 
      v-bind:css="true"
    >
      <div class="addcart-mask" v-show="ball.show">
        <img class="mask-item" src="" alt="4858美高梅 5">
      </div>
    </transition>
 ==========
 .ball-enter-active{
    transition: 1s cubic-bezier(.18,1,.94,1)
  }
  .ball-enter-active .mask-item{
    transition: 1s cubic-bezier(0,0,0,0)
  }
{ 
 "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的疑难小编都在那二篇小说中找到答案,在那边相关react-navigation配置,使用格局和花色里面页面布局,组件写法,在此地不筹算细说,因为都相比较简单,越来越多的是商量Mobx落成效益的一部分逻辑和情势,
screen 文件夹下的组件都写有注释的(°ー°〃)

器重依然来聊聊Mobx吧

先来探望用Mobx达成的具体流程,看下面包车型客车动图(⊙﹏⊙)

ps: 恐怕图片太大,加载有点慢,请稍等……

4858美高梅 6 

一.数量存款和储蓄和获得

那几个都以用假数据来模拟达成的,在最开始,先写好假数据的数据结构,比方:

"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 ( 
 <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
来得到我们想要的数量啦^_^
,相同,在商品信息,分类页,购物车页面js下,也要求使用
@inject(‘rootStore’)
来贯彻多少的获得,然后再一步步地把数据传到它们的子组件中。

二. 参预购物车的兑现

在首页和归类页中,都得以点击跳转到商品音讯页,然后再加入到购物车里

4858美高梅 7 

兑现形式 :

在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中追扩展少,切换成购物车页面时,视图会同步刷新,看到已加盟购物车的水果。

叁.转移商品状态同步立异视图

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

举个例子说,商品的加码多少,缩小数额,选中状态,商品全选和商品删除,总价格都会趁机商品的数据变化而调换。

4858美高梅 8 

图又来了~~

落到实处地方的效能,重要利用了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的估测计算属性。

四.付钱商品

物品买单和清空购物车的逻辑都写在 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.遭逢的小坑

壹.自身写了2个数组的乱序方法,里面有用到 Array.isArray()
那几个点子来判别是还是不是为数组,可是,作者用那一个乱序函数时,想用来搞乱store里面包车型大巴数组时,开采间接从未实践,感觉很想获得。然后作者一贯用
Array.isArray()
这几个格局来判定store里面包车型地铁数组,再次回到的直接都以false。。。于是作者就懵了。。。后来,笔者去看了Mobx官方文档,终于找到了答案。原来,store里面存放的数组,并不是确实的数组,而是
obverableArray ,借使要让 Array.isArray()
决断为true,就要在取到store的数组时,加个. slice() 方法,只怕Array.from() 都得以。

二.平等,也是obverableArray的难题。在购物车页面时,小编用了FlatList来渲染购物车的item,开头,当自己增添商品到购物车,开掘购物车页面并不曾刷新。有了上边的踩坑经验,作者以为是obverableArray引起的,因为FlatList的data接收的是real
Array,于是,笔者用这么的艺术:

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

于是乎,购物车视图就能够自行地刷新了,在合法文书档案上也有写到。

三.还有三个正是自身疏忽变成的。作者写完那些类型后,和情人出去玩时,顺便发给朋友看看,他在剔除商品时开采,从上往下删删不了,从下往上删就足以。后来自身用模拟器测试也是那样,于是就去看望删除商品的逻辑,开采并未有毛病,再去看store的多寡,发掘也是足以协同立异的,只是视图未有立异,很巧妙,于是自身又在FlatList去找原因,终于,原因找到了,首借使在keyExtractor里面,用index是不能的,要用name来作为key,因为小编删除商品方法其实是基于name来删的,而不是index,所以用index来作为FlatList的Item的key时是会晤世bug的。

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

沾满github项目地址: 
github.com/shooterRao/…

总结

以上所述是我给大家介绍的用React-Native+Mobx做一个精制水果商铺应用程式(附源码),希望对我们有着协理,就算咱们有其余疑问请给自个儿留言,笔者会及时还原大家的。在此也万分感激大家对台本之家网址的援助!

您恐怕感兴趣的小说:

  • React-Native使用Mobx完毕购物车功效

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图
Copyright @ 2010-2019 美高梅手机版4858 版权所有