• vuex实现简易购物车加购效果


    一、加购效果动图

    在这里插入图片描述

    二、前提条件

    创建了vue项目,安装了vuex

    三、开始操作

    目录结构如下:

    在这里插入图片描述

    main.js文件中引入store:

    import Vue from 'vue'
    import App from './App.vue'
    import store from './store'
    
    Vue.config.productionTip = false
    
    
    
    new Vue({
      render: h => h(App),
      store,
    }).$mount('#app')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    page-index.vue页面组件代码如下:

    <template>
        <div>
            <div class="item">
                <h1>我的购物车:h1>
                <ul>
                    <li v-for="(item, index) in this.$store.state.cartGoods" :key="index">
                        商品名称:{{item.name}}<br>
                        <button @click="numRed(index)">-button>
                        <span class="num">{{item.num}}span>
                        <button @click="numAdd(index)">+button>
                        <span>单价:¥{{item.price}}span>
                    li>
                ul>
            div>
    
            <div class="item">
                <h1>商品列表:h1>
                <ul class="prod-list">
                    <li v-for="(item, index) in prodList" :key="index">
                        <span class="pro">名称:{{item.name}}span>
                        <span class="pro">单价:{{item.price}}span>
                        <span class="pro">
                            <button @click="addCart(item)">加入购物车button>
                        span>
                    li>
                ul>
    
    
            div>
        div>
    template>
    
    <script>
        export default {
           
            data(){
               return{
                   prodList:[
                       {
                           name:"CPU",
                           price:999.99
                       },
                       {
                           name:"显示器",
                           price:199.99
                       },
                       {
                           name:"显卡",
                           price:1000
                       },
                       {
                           name:"内存",
                           price:500
                       },
                       {
                           name:"硬盘",
                           price:500
                       }
                   ]
               }
    
            },
          
            methods: {
                numRed(index){
                    this.$store.dispatch('red',index)
                },
                numAdd(index){
                    this.$store.dispatch('add', index)
                },
                addCart(item){
                    this.$store.commit('ADD_CART',item)
                }
    
            }
        }
    script>
    
    <style scoped>
        .item{
            margin-bottom: 50px;
        }
     .prod-list{ line-height: 22px;}
     .prod-list li{ border-bottom: #ddd solid 1px; padding: 10px;}
     .prod-list li .pro{ min-width: 150px; display: inline-block; vertical-align: middle;}
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86

    state.js文件内容如下:

    export default {
        cartGoods: []
    }
    
    • 1
    • 2
    • 3

    getters.js文件内容如下:

    export default {
      countGoods:(state)=>{
        var count={
          allNum:0,
          allPrice:0
        }
        state.cartGoods.forEach((item)=>{
          function ConvertAdd(arg1, arg2) {//加法精确运算
            var r1, r2, m;
            try { r1 = arg1.toString().split(".")[1].length; } catch (e) { r1 = 0; }
            try { r2 = arg2.toString().split(".")[1].length; } catch (e) { r2 = 0; }
            m = Math.pow(10, Math.max(r1, r2));
            var result = (arg1 * m + arg2 * m) / m;
            //return (arg1 * m + arg2 * m) / m;
            var ws = 1, ln = 0,
                lnArr1 = arg1.toString().split("."),
                lnArr2 = arg2.toString().split("."),
                ln1 = (lnArr1.length < 2) ? 0 : lnArr1[1].length,
                ln2 = (lnArr2.length < 2) ? 0 : lnArr2[1].length;
        
            if ((ln1 - ln2) >= 0) {
                ln = ln1;
            } else {
                ln = ln2;
            }
            if (ln > 0) {
                switch (ln) {
                    case 0: { break; }
                    case 1: { ws = 10; break; }
                    case 2: { ws = 100; break; }
                    case 3: { ws = 1000; break; }
                    case 4: { ws = 10000; break; }
                    case 5: { ws = 100000; break; }
                    case 6: { ws = 1000000; break; }
                    case 7: { ws = 10000000; break; }
                    case 8: { ws = 100000000; break; }
                    default: { break; }
                }
            }
            return Math.round(result * ws) / ws;
          }
          if(item.num>0){
            count.allNum +=item.num;
            count.allPrice =ConvertAdd(count.allPrice,Math.round(item.num*item.price * Math.pow(10, 3)) / Math.pow(10, 3));
          }
        })
        return count;
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    mutations.js文件内容如下:

    import { ADD,RED,ADD_CART } from './mutationTypes'
    export default {
    	// 我们可以使用 ES2015 风格的计算属性命名功能
        // 来使用一个常量作为函数名
        // 这样可以使 linter 之类的工具发挥作用,同时把这些常量放在单独的文件中可以让你的代码合作者对整个 app 包含的 mutation 一目了然
      [ADD](state,req){
        console.log(state.cartGoods,req);
        state.cartGoods[req].num++;
      },
      [RED](state,req){
        if(state.cartGoods[req].num>0){
          state.cartGoods[req].num--;
        }
      },
      [ADD_CART](state,req){
        var newFlag=true;
        for(var i=0; i<state.cartGoods.length; i++){
          if(state.cartGoods[i].name==req.name){
            newFlag=false;
            state.cartGoods[i].num++;
            break
          }
        }
        if(newFlag){
          let item={
            name:req.name,
            price:req.price,
            num:1
          }
          state.cartGoods.push(item);
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    mutationTypes.js内容如下:

    export const ADD = 'ADD';
    export const RED = 'RED';
    export const ADD_CART = 'ADD_CART';
    
    
    • 1
    • 2
    • 3
    • 4

    actions.js文件内容如下:

    export default {
        red({commit},req){
            commit('RED',req);
        },
        add({commit}, req){
            commit('ADD', req)
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    index.js文件内容如下:

    import Vue from 'vue'
    import Vuex from 'vuex'
    Vue.use(Vuex)
    
    import state from '@/store/state.js';
    import getters from "@/store/getters";
    import mutations from "@/store/mutations";
    import actions from "@/store/actions"
    
    const store = new Vuex.Store({
        // 用来存入状态
        state: state,
        // 计算属性(对state中的属性进行计算)
        getters: getters,
        mutations: mutations,
        actions: actions
    })
    
    export default store
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    到此,已经能实现基本的加购操作了。

    但是,有一个问题就是页面刷新的时候vuex里面的数据会丢失,购物车就会被清空。显然这是不符合实际购物的。要把数据存进本地才能避免这种情况。

    四、解决vuex刷新数据丢失问题

    修改state.js文件:

    export default {
        //  从本地获取购物车商品数据,如果没有初始化为空数组
        cartGoods: JSON.parse(window.localStorage.getItem('cart-products')) || []
    }
    
    • 1
    • 2
    • 3
    • 4

    在mutations.js的ADD_CART方法中每次更改过的数据,都需要记录到本地存储中。增加一句:window.localStorage.setItem('cart-products', JSON.stringify(state.cartGoods))

    最终文件内容如下:

    import { ADD, RED, ADD_CART } from './mutationTypes'
    
    export default {
        [RED](state,req){
            // console.log(state, req)
            if(state.cartGoods[req].num > 0){
                state.cartGoods[req].num--;
            }
        },
        [ADD](state, req){
            state.cartGoods[req].num++;
        },
        [ADD_CART](state, req){
            var newFlag = true;
            for(var i = 0; i < state.cartGoods.length; i++){
                if(state.cartGoods[i].name == req.name){
                    newFlag = false;
                    state.cartGoods[i].num ++;
                    break
    
                }
            }
            if(newFlag){
                let item = {
                    name: req.name,
                    price: req.price,
                    num: 1
                }
                state.cartGoods.push(item)
            }
            window.localStorage.setItem('cart-products', JSON.stringify(state.cartGoods))
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    五、最终效果

    在这里插入图片描述
    可见,现在刷新不会再清空购物车数据了。

  • 相关阅读:
    BFS 之Flood Fill 算法(二)
    基于FPGA的会议发言限时器
    来自大厂 10+ 前端面试题附答案(整理版)
    基于 Laravel 封装参数校验
    用HTML+CSS仿网易云音乐网站(6个页面)
    大数据方向面试问题
    基于ChatGPT的视频智能摘要实战
    【C语言】输入一个正整数,判断其是否为素数
    钉钉stream机器人-实操详细教程
    开源治理:安全的关键
  • 原文地址:https://blog.csdn.net/Amouzy/article/details/133130033