Vue----购物车Cart

本文介绍了一种使用Vue.js实现的购物车单价变化时总价自动更新的方法。通过监听单价和数量的变化,实时计算并显示购物车总价。文章还涵盖了全选、删除等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

功能:实现单个单价的变化,同步更新总价

html

<div class="wrap wrap-cart" id="app">
    <div class="area">

        <div class="cart-title"><span>购物车</span></div>

        <div class="cart-table">
            <div class="cart-head">
                <ul>
                    <li>商品信息</li>
                    <li>单价</li>
                    <li>数量</li>
                    <li>小计</li>
                    <li>编辑</li>
                </ul>
            </div>

            <ul class="cart-body">
                <li v-for="(item, index) in productList">
                    <div class="cart-item">                            
                        <a href="javascript:;" class="check-btn" v-bind:class="{'checked':item.checked}" v-on:click="selectProduct(item)">
                            <svg class="icon icon-ok"><use xlink:href="#icon-ok"></use></svg>
                        </a>

                        <div class="goods-msg clearfix">
                            <img class="img" v-bind:src="item.productImage" alt="">
                            <div class="title">
                                <a href="detail.html" target="_blank" v-text="item.productName"></a>
                                <p v-for="part in item.parts" v-text="part.partName"></p>
                            </div>
                        </div>  
                    </div>

                    <div class="cart-item">
                        <span class="item-price">{{ item.productPrice | partFilter('') }}</span>
                    </div>

                    <div class="cart-item">
                        <div class="num-amount">
                            <span class="num-increase" @click="changeMoney(item, -1)">-</span>
                            <input type="text" class="num-input" :value="item.productQuantity" disabled>
                            <span class="num-decrease" @click="changeMoney(item, +1)">+</span>
                        </div>    
                    </div>

                    <div class="cart-item">
                        <span class="item-price-total">{{ item.productPrice * item.productQuantity | money('元') }}</span>
                    </div>

                    <div class="cart-item">
                        <a href="javascript:;" class="icon-btn" @click="delBtn(item)">
                            <svg class="icon icon-del"><use xlink:href="#icon-del"></use></svg>
                        </a>
                    </div>                  
                </li>

            </ul>

        </div>

        <div class="cart-foot">
            <div class="f-l">
                <a href="javascript:;" class="check-btn" :class="{'checked':checkAllFlag}" @click="allSelect(true)">
                    <svg class="icon icon-ok"><use xlink:href="#icon-ok"></use></svg>
                </a>
                <a href="javascript:;" @click="allSelect(true)"  v-if="!checkAllFlag" >全选</a>
                <a @click="allSelect(false)" href="javascript:;" v-if="checkAllFlag">取消全选</a>
            </div>

            <div class="f-r">
                总金额:<span class="total-price">{{ totalMoney | partFilter('元') }}</span>
                <a href="goods-order.html" class=""><button class="btn gopay-btn radius">结账</button></a>
            </div>
        </div>

    </div>

    <!-- 遮罩层 -->
    <div class="md-overlay" v-if="delFlag"></div>

    <!-- 提示框 -->
    <div class="md-panel" :class="{'md-show':delFlag}">

        <div class="md-inner">
            <div class="panel-header"><div class="panel-close" @click="delFlag=false"></div></div>

            <div class="panel-body">你确认删除此订单信息吗?</div>

            <div class="panel-footer clearfix">
                <button class="btn-confirm" @click="confirmDel">YES</button>
                <button class="btn-cancel" @click="delFlag=false">NO</button>                   
            </div>
        </div> 

    </div>
</div>

js

<script src="./style/js/libs/vue/vue.min.js"></script>
<script src="./style/js/libs/vue/vue-resource.js"></script>
<script> 
new Vue({
    el:'#app',
    data:{
        productList  :[],
        totalMoney   : 0,
        checkAllFlag :false,
        delFlag      :false,
        curProduct   :''
    },
    filters:{
        partFilter:function(value, type){
            return '¥ ' + value.toFixed(2) + type;    // 保留2位仅做测试用
        }
    },
    mounted:function(){
        this.$nextTick(function(){
            this.getCartList();
        })
    },
    methods:{
        // 提取数据
        getCartList:function(){
            var _this = this;
            // this.$http.get('./style/js/cart.json', {'id':12}).then(res=>{       // ES6
            this.$http.get('./style/js/cart.json', {'id':12}).then( function(res) {
                _this.productList = res.data.result.list;

                // 效果是一样的
//                    console.log(res.data);    
//                    console.log(res.body);
            })
        },


        // 选择商品
        selectProduct:function(item){
            if(typeof item.checked == 'undefined'){
                // 注册一个变量¥set(obj, key, val), 也可以在数据库里增加字段处理
                this.$set(item, 'checked', true);
            } else {
                item.checked = !item.checked;
            }

            // console.log(item.checked)

            // 全部选中则全部按钮点亮,相反
            var checkAllFlags = true;
            this.productList.forEach( function(item, index){
                checkAllFlags = checkAllFlags && item.checked;
            });
            this.checkAllFlag = checkAllFlags;

            // 再计算金额
            this.callTotalMoney(); 
        },


        // 点击执行全选
        allSelect:function(flag){
            this.checkAllFlag = flag;

            // this.productList.forEach((item, index)=>{    // ES6
            var _this = this;
            this.productList.forEach( function(item, index){
                if(typeof item.checked == 'undefined'){
                    // 一上来就点全选的情况,也要注册一个变量
                    _this.$set(item, 'checked', true);
                } else {
                    item.checked = _this.checkAllFlag;
                }
            }); 

            // 再计算金额
            this.callTotalMoney(); 
        }, 


        // 计算金额
        callTotalMoney:function(){
            this.totalMoney = 0;

            // this.productList.forEach((item, index)=>{     // ES6
            var _this = this;
            this.productList.forEach( function(item, index){    
                if(item.checked){
                    _this.totalMoney += item.productPrice * item.productQuantity;
                }
            })
        },


        // 点击加减商品数量计算金额
        changeMoney:function(item, type){
          if(type < 0){
              item.productQuantity--;

              if(item.productQuantity < 1) item.productQuantity = 1;
          } else {
              item.productQuantity++;
          }

            // 再计算金额
            this.callTotalMoney(); 
        },


        // 点击删除
        delBtn:function(item){
            this.delFlag     = true;
            this.curProduct  = item;
        },


        // 点击确认删除按钮
        confirmDel:function(){
            this.delFlag = false;
            var index = this.productList.indexOf(this.curProduct);
            console.log(index);
            this.productList.splice(index, 1);

            // 再计算金额
            this.callTotalMoney(); 
        }

    }

})

// 全局过滤器
Vue.filter("money", function(value, type){
    return '¥ ' + value.toFixed(2) + type;
})
</script> 
### 基于 vue-element-admin 的点餐系统实现方案 #### 方案概述 `vue-element-admin` 是一个基于 Vue 和 Element UI 构建的后台管理框架,提供了丰富的功能模块和优雅的设计风格。为了构建一个完整的点餐系统,可以利用 `vue-element-admin` 提供的基础架构,并在此基础上扩展业务逻辑。 以下是基于 `vue-element-admin` 的点餐系统的实现思路: --- #### 数据结构设计 根据引用中的描述[^3],可以定义如下数据模型来支持点餐系统的开发: 1. **菜品表 (`dishes`)** - id (主键) - name (菜名) - price (价格) - image_url (图片路径) 2. **订单表 (`orders`)** - order_id (订单号) - user_id (用户ID) - total_price (总价) - create_time (下单时间) 3. **订单详情表 (`order_details`)** - detail_id (明细ID) - order_id (关联订单ID) - dish_id (关联菜品ID) - quantity (数量) 4. **评论表 (`food_comments`)** - comment_id (评论ID) - food_id (关联菜品ID) - user_id (用户ID) - content (评论内容) - parent_id (父级评论ID,可选) - create_time (创建时间) 这些表格可以通过后端 API 进行交互并存储到数据库中。 --- #### 页面布局与组件设计 通过 `vue-element-admin` 的模板,我们可以快速搭建以下页面模块: 1. **登录页** 使用 `vue-element-admin` 默认提供的登录界面完成身份验证。 2. **首页仪表盘** 展示当前订单统计、热门菜品排行等内容。 3. **菜单管理** 利用动态加载技术展示菜品列表,并提供增删改查的功能。 ```html <!-- 菜品列表 --> <el-table :data="dishes"> <el-table-column prop="name" label="名称"></el-table-column> <el-table-column prop="price" label="价格"></el-table-column> <el-table-column fixed="right" width="180" label="操作"> <template slot-scope="scope"> <el-button size="mini" @click="editDish(scope.row)">编辑</el-button> <el-button size="mini" type="danger" @click="deleteDish(scope.row)">删除</el-button> </template> </el-table-column> </el-table> ``` 4. **购物车功能** 结合 Vuex 状态管理工具保存用户的临时选购记录。 ```javascript // store/modules/cart.js import Vue from 'vue'; const state = { items: [] }; const mutations = { ADD_TO_CART(state, item) { let foundItem = state.items.find(i => i.id === item.id); if (!foundItem) { state.items.push({ ...item, qty: 1 }); } else { foundItem.qty += 1; } }, REMOVE_FROM_CART(state, itemId) { state.items = state.items.filter(item => item.id !== itemId); } }; const actions = { addToCart({ commit }, payload) { commit('ADD_TO_CART', payload); }, removeFromCart({ commit }, payload) { commit('REMOVE_FROM_CART', payload); } }; export default { namespaced: true, state, mutations, actions }; ``` 5. **订单提交流程** 用户确认购物车内的商品后,调用后端接口生成正式订单。 ```javascript async function submitOrder(orderData) { try { const response = await axios.post('/api/orders/submit', orderData); console.log('订单已成功提交:', response.data.orderId); } catch (error) { console.error('提交失败:', error.message); } } ``` 6. **评价反馈机制** 参考引用中的字段说明,允许用户对已完成的订单进行评分或留言。 ```html <!-- 食品评价 --> <el-form ref="formRef" :model="formData" status-icon> <el-form-item label="您的评价:" prop="content"> <el-input v-model="formData.content" type="textarea" rows="4"></el-input> </el-form-item> <el-form-item> <el-button type="primary" @click="handleSubmit">发表</el-button> </el-form-item> </el-form> ``` 7. **懒加载优化** 对于大型餐厅可能存在的海量菜品情况,建议引入按需渲染插件如 `vue-lazy-render` 来提升性能[^1]。 --- #### 后端服务对接 假设采用 Node.js + Express 搭配 MySQL 数据库作为后端技术支持,则需要编写 RESTful API 处理前端请求。例如: - 获取所有菜品 `/api/dishes` - 创建新订单 `/api/orders/create` - 查询历史订单 `/api/orders/history/:userId` 具体代码片段如下所示: ```javascript // app/routes/api/dishes.js const express = require('express'); const router = express.Router(); const db = require('../models'); router.get('/', async (req, res) => { try { const dishesList = await db.Dish.findAll({ attributes: ['id', 'name', 'price', 'image_url'] }); return res.json(dishesList); } catch (err) { return res.status(500).json({ message: err.message }); } }); module.exports = router; ``` --- #### 测试与部署 最后,在本地环境调试完成后可通过 Docker 容器化打包发布至云服务器运行;同时借助 Nginx 或 Caddy 设置反向代理规则保障 HTTPS 访问安全。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值