首页 > 其他分享 >vue vuex 购物车案例

vue vuex 购物车案例

时间:2023-09-16 18:02:11浏览次数:37  
标签:vue name width cart 购物车 item height vuex id


新建vue项目

vue vuex 购物车案例_javascript

 此项目需要用到json-server,模拟后台服务器接口功能,

npm i json-server -g

安装此包,然后再vue项目的全局根目录中新建db文件夹,其中新建index.json文件。

{
  "cart": [
    {
      "id": 1001,
      "name": "低帮城市休闲户外鞋天然牛皮COOLMAX纤维",
      "price": 128,
      "count": 3,
      "thumb": "https://yanxuan-item.nosdn.127.net/3a56a913e687dc2279473e325ea770a9.jpg"
    },
    {
      "id": 1002,
      "name": "网易未央黑猪猪肘330g*1袋",
      "price": 39,
      "count": 3,
      "thumb": "https://yanxuan-item.nosdn.127.net/3a56a913e687dc2279473e325ea770a9.jpg"
    },
    {
      "id": 1003,
      "name": "KENROLL男女简洁多彩一片室外拖",
      "price": 88,
      "count": 3,
      "thumb": "https://yanxuan-item.nosdn.127.net/3a56a913e687dc2279473e325ea770a9.jpg"
    },
    {
      "id": 1004,
      "name": "低帮城市休闲户外鞋天然牛皮COOLMAX纤维",
      "price": 99,
      "count": 6,
      "thumb": "https://yanxuan-item.nosdn.127.net/3a56a913e687dc2279473e325ea770a9.jpg"
    }
  ],
  "friends": [
    {
      "id": 1,
      "name": "hang",
      "age": 18
    },
    {
      "id": 2,
      "name": "wang",
      "age": 29
    }
  ]
}

模拟数据库,在db文件夹下,调用系统cmd命令,启动模拟服务器

json-server --watch index.json

vue vuex 购物车案例_javascript_02

 

vue vuex 购物车案例_javascript_03

 main.js

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');

app.vue

<template>
  <div id="app">
    <!-- Header 区域   -->
    <cart-header></cart-header>

    <!-- Item 区域   -->
    <cart-item v-for="item in list" :key="item.id" :item="item"></cart-item>

    <!-- Footer 区域   -->
    <cart-footer></cart-footer>
  </div>
</template>

<script>
import CartHeader from "@/components/CartHeader";
import CartItem from "@/components/CartItem";
import CartFooter from "@/components/CartFooter";
import { mapState } from 'vuex'

export default {
  name: 'App',
  components: {
    CartHeader,
    CartItem,
    CartFooter
  },
  computed:{
    ...mapState('cart',['list'])
  },
  created() {
    this.$store.dispatch('cart/getList');
  }
}
</script>

<style>
  *{
    padding: 0;
    margin: 0;
  }
</style>

index.js

import Vue from 'vue'
import Vuex from 'vuex'
import cart from "@/store/modules/cart";

Vue.use(Vuex);

const store = new Vuex.Store({
    modules:{
        cart
    }
});

export default store;

cart.js

import axios from "axios";
export default {
    //开启命名空间
    namespaced:true,
    state(){
        return {
            list:[]
        }
    },
    getters:{
        //总数
        total(state){
            return state.list.reduce( (sum,item) => sum += item.count,0);
        },
        //总金额
        totalPrice(state){
            return state.list.reduce( (sum,item) => sum + item.count * item.price ,0);
        }
    },
    mutations:{
        updateList(state,newList){
            state.list = newList;
        },
        //
        updateCount(state,obj){
            //根据id找到对应的对象,更新count属性
            const goods = state.list.find( item => item.id === obj.id);
            goods.count = obj.newCount;
        }
    },
    actions:{
        //请求方式 get
        //请求地址:http://localhost:3000/cart
        async getList(context){
            const res = await axios.get('http://localhost:3000/cart');
            //console.log(res);
            context.commit('updateList',res.data);
        },
        //请求方式 patch
        //请求地址:http://localhost:3000/cart/:id值
        //请求参数 { name:'新值', [可选]}
        //
        async updateCountAsync(context,obj){
            //将修改更新同步到后台服务器
            const res = await axios.patch(`http://localhost:3000/cart/${obj.id}`,{
                count: obj.newCount
            });
            console.log(res);
            //调用mutation
            context.commit('updateCount',{
                id: obj.id,
                newCount: obj.newCount
            });
        }
    }
}

CartHeader.vue

<template>
    <div class="cart-header">
        <div class="title">购物车案例</div>
    </div>
</template>

<script>
    export default {
        name: "CartHeader"
    }
</script>

<style scoped>
    .cart-header{
        width: 100%;
        height: 70px;
        background-color: mediumseagreen;
        margin-bottom: 10px;
    }

    .cart-header .title{
        color: white;
        font-size: 34px;
        width: 200px;
        height: 100%;
        line-height: 70px;
        text-align: center;
        margin: 0 auto;
    }
</style>

CartItem.vue

<template>
    <div class="cart-item">
        <!-- 左侧图片区域       -->
        <div class="left">
            <img :src="item.thumb" alt="" class="avatar">
        </div>
        <!-- 右侧商品区域       -->
        <div class="right">
            <!-- 标题           -->
            <div class="title">{{ item.name }}</div>
            <div class="info">
                <span class="price">¥{{ item.price }}</span>
                <div class="btns">
                    <!-- 按钮区域                   -->
                    <button class="btn btn-light" @click="btnClick(-1)">-</button>
                    <span class="count">{{ item.count }}</span>
                    <button class="btn btn-light" @click="btnClick(+1)">+</button>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        name: "CartItem",
        props:{
            item: {
                type: Object,
                required:true
            }
        },
        methods:{
            btnClick(step){
                const newCount = this.item.count + step;
                const id = this.item.id;
                //console.log(id,newCount);
                if(newCount < 1) return;
                this.$store.dispatch('cart/updateCountAsync',{
                    id,
                    newCount,
                });
            }
        }
    }
</script>

<style scoped>


    .cart-item{
        width: 98%;
        height: 200px;
        margin-left: 2%;
    }

    .cart-item .left{
        width: 180px;
        height: 180px;
        float: left;
    }

    .left img{
        width: 100%;
        height: 100%;
    }

    .cart-item .right{
        width: 30%;
        height: 100%;
        float: left;
    }

    .right .title{
        text-indent: 40px;
        font-size: 24px;
        height: 75%;
        font-family: Arial,"Arial Black",Georgia;
    }

    .right .info{
        width: 100%;
        height: 25%;
        line-height: 30px;

    }

    .right .price{
        padding: 3px;
        margin-left: 40px;
        color: orange;
        font-size: 24px;
    }

    .right .btns{
        float: right;
    }

    .btns .btn{
        width: 30px;
        height: 33px;
        line-height: 30px;
        font-size: 20px;
        margin: 0 15px;
    }

    .btns .count{
        display: inline-block;
        width: 25px;
        text-align: center;
        font-size: 20px;
        font-weight: bold;
    }

    .btns .btn-light{
        background-color: #cccccc;
    }
</style>

CartFooter.vue

<template>
    <div class="cart-footer">
        <!--  中间合计      -->
        <div>
            <span>共 {{ total }} 件商品,合计:</span>
            <span class="price">¥ {{ totalPrice }}</span>
        </div>
        <!--  右侧结算按钮      -->
        <button class="btn">结算</button>
    </div>
</template>

<script>
    import { mapGetters} from 'vuex'
    export default {
        name: "CartFooter",
        computed:{
            ...mapGetters('cart',['total','totalPrice'])
        }
    }
</script>

<style scoped>
    .cart-footer{
        width: 30%;
        height: 50px;
        font-size: 20px;
        float: right;
    }

    .cart-footer div{
        display: inline;
        width: 400px;
        margin-left: 8%;
    }
    .cart-footer .price{
        font-size: 30px;
        font-weight: bold;
        color: red;
    }

    .cart-footer .btn{
        width: 150px;
        height: 50px;
        background-color: mediumseagreen;
        border-radius: 30px;
        float: right;
        margin-right: 40px;
    }
</style>

vue vuex 购物车案例_javascript_04

标签:vue,name,width,cart,购物车,item,height,vuex,id
From: https://blog.51cto.com/u_15356972/7495434

相关文章

  • vue vuex module mapActions
    新建vue项目 main.jsimportVuefrom'vue'importAppfrom'./App.vue'importstorefrom'@/store'Vue.config.productionTip=false;newVue({render:h=>h(App),store}).$mount('#app');app.vue<template>......
  • Vue 中的 slot 插槽
    目录一:知识点说明二:不使用插槽效果1:界面效果2:代码结构3:代码内容三:使用插槽组件(默认插槽slot)1:界面效果2:代码结构3:代码内容四:使用插槽组件(具名插槽slot)1:看界面效果2:代码结构3:代码内容五:作用域插槽(slot-scope/scope)1:看界面效果2:代码结构3:代码内容 一:知识点说明##插槽1.......
  • Vuex
    目录一:Vue知识要点说明:二:示例一:Vue知识要点说明##Vuex###1.概念 在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信。Github地址:https://github.com/vuejs......
  • Vue响应式原理
    该随笔是根据b站小满zs的Vue3+vite+Ts+pinia+实战+源码+electron的视频学习写的,Vue3+vite+Ts+pinia+实战+源码+electron......
  • springboot vue uniapp 小说电子书阅读小程序APP源码
    开发环境及工具:大等于jdk1.8,大于mysql5.5,idea(eclipse),nodejs,vscode(webstorm),HBuilderX技术说明:springbootmybatisvueelementuiuniapp代码注释齐全,没有多余代码,适合学习(毕设),二次开发,包含论文技术相关文档。功能介绍:用户端:登录注册首页显示搜索小说,轮播图,最新发布小说(可带推荐算......
  • vue3-路由遇到的问题
    在Vue3中,使用VueRouter来管理应用程序的导航和路由。下面是VueRouter的一些常见使用方法:通过npm或yarn安装VueRouter:npminstallvue-router或yarnaddvue-router在主文件(通常是main.js)中导入VueRouter并创建一个实例:import{createApp}from'vue'importrouterfrom'......
  • vue中elementui el-input绑定的值如何过滤掉输入的空格?
    在vue中可以在@input事件中使用Trim函数来去掉前后两端空格,再使用replace方法来删除中间空格,此时的值删除所有空格,用户输入值中的空格就会被过滤掉了。<template> <div> <el-inputv-model="searchValue"@input="handleInput"></el-input></div></template><scrip......
  • Vue进阶(幺柒肆):鼠标、键盘事件
    (文章目录)一、前言在项目开发过程中,需要根据鼠标事件进行相应处理。现予以梳理。鼠标事件如下所示:点击事件:@click//单击@dblclick//双击@mousedown//按下@mouseup//抬起@contextmenu//鼠标右键悬浮事件及触发顺序:@mouseover//划过@mouseenter//进入@mouse......
  • 不再困惑:一文读懂Vue2与Vue3的主要差异
    Vue3相对于Vue2有很多改进和新特性。以下是一些主要的区别:性能更好:Vue3的性能比Vue2更好,因为它使用了更少的代码和更高效的算法。例如,Vue3使用Proxy代替了Object.defineProperty来监听数据变化,这使得Vue3的性能更高。组合式API:Vue3引入了组合式API,这是一种新的编写组件逻辑的方式。......
  • Vue3开发环境搭建全攻略:Vite的详细介绍
    Vite简介Vite这个单词是一个法语单词,意思就是轻快的意思。它和我们以前使用Vue-cli的作用基本相同,都是项目初始化构建工具,相当于Vue项目构建的第二代产品,当然它也包含了项目的编译功能。需要注意一下Vite的生产环境下打包是通过Rollup来完成的。Vite特性介绍Vite主打特点就是轻快冷......