非node环境下的vue.js 实现简单的购物车计算功能 样式请无视

时间:2022-03-17 14:17:22

都说vue的双向数据绑定好用,自己用了下,感觉做购物车没想象中好用。自己的实现如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
    <script src="js/axios.min.js"></script>
</head>
<body>
<div id="app">
    <input type="checkbox" v-model="checkedAll">
    <ul>
        <li v-for="(item,index) in shopingcart">
            <input type="checkbox" v-model="checkedNames[index]"><img
                :src="item.imgUrl"
                alt="">
            <div><span class="price">¥{{item.unitPrice}}</span></div>
            <div class="item-amount "><a href="#" class="J_Minus no-minus" @click="minus(index)">-</a><input
                    @change="num(event,index)"
                    type="text"
                    v-model="item.quantity"
                    class="text text-amount J_ItemAmount"
                    autocomplete="off"><a href="#"
                                          class="J_Plus plus"
                                          @click="add(index)">+</a>
            </div>
            <div class="td-inner"><em tabindex="0" class="J_ItemSum number">¥{{Math.ceil(parseFloat(item.unitPrice*item.quantity)*10)/10}}</em>
                <div class="J_ItemLottery"></div>
                <div class="weight" data-spm-anchor-id="a1z0d.6639537.1997196601.i2.4cf574843pYndQ">
                    ({{Math.ceil(parseFloat(item.weight*item.quantity)*100)/100}}kg)
                </div>
            </div>
        </li>
    </ul>
    <span>Checked names: {{ checkedNames }}</span>
    <input type="checkbox" v-model="checkedAll"> <span>{{goodTotal}}</span>件 合计:<span>{{priceAll}}</span> 结算
</div>
<script>
    var Data = {
        test: [
            {
                imgUrl: 'https://img.alicdn.com/bao/uploaded/i2/725677994/TB1Z1mzXMmTBuNjy1XbXXaMrVXa_!!0-item_pic.jpg_80x80.jpg',
                unitPrice: 29.90,
                weight: 0.2,
                detail: '百草味 黄桃干100g*2 零食蜜饯水果干 杏果果脯杏脯',
                quantity: 1
            },
            {
                imgUrl: 'https://img.alicdn.com/bao/uploaded/i2/725677994/TB1Z1mzXMmTBuNjy1XbXXaMrVXa_!!0-item_pic.jpg_80x80.jpg',
                unitPrice: 19.90,
                weight: 0.15,
                detail: '百草味 黄桃干100g*2 零食蜜饯水果干 杏果果脯杏脯',
                quantity: 1
            },
            {
                imgUrl: 'https://img.alicdn.com/bao/uploaded/i2/725677994/TB1Z1mzXMmTBuNjy1XbXXaMrVXa_!!0-item_pic.jpg_80x80.jpg',
                unitPrice: 9.90,
                weight: 0.31,
                detail: '百草味 黄桃干100g*2 零食蜜饯水果干 杏果果脯杏脯',
                quantity: 1
            }
        ]
    }
    var app = new Vue({
        el: '#app',
        data: {
            goodTotal: 0,
            priceAll: 0,
            checkedAll: false,
            shopingcart: Data.test,
            checkedNames: []
        },
        methods: {
            add: function (index) {
                this.shopingcart[index].quantity++;
                console.log(this.shopingcart[index].quantity);
                // 如果checkedNames存在,即是选中
                if (this.checkedNames.length > 0) {
                    this.recalculation(this.checkedNames);
                }
            },
            num: function (event, index) {
                if (event.target.value <= 0) {
                    return false
                }
                var obj = event.target;
                this.shopingcart[index].quantity = event.target.value;
                // 如果checkedNames存在,即是选中
                if (this.checkedNames.length > 0) {
                    this.recalculation(this.checkedNames);
                }
            },
            minus: function (index) {
                if (this.shopingcart[index].quantity <= 1) {
                    return false
                }
                this.shopingcart[index].quantity--;
                // 如果checkedNames存在,即是选中
                if (this.checkedNames.length > 0) {
                    this.recalculation(this.checkedNames);
                }
            },
            checkAll: function () {
                if (!this.checkAll) {
                    this.checkAll = !this.checkAll;
                }
            },
            recalculation: function (newVal) {
                var _this = this,
                    Total = 0,
                    priceAll = 0;
                // 获取总数total和合计元
                newVal.forEach(function (item, index) {
                    if (item == true) {
                        Total += parseInt(_this.shopingcart[index].quantity);
                        priceAll += _this.shopingcart[index].unitPrice * _this.shopingcart[index].quantity;
                    }
                })
                this.goodTotal = Total;
                this.priceAll = Math.ceil(parseFloat(priceAll) * 100) / 100;
            }
        },
        watch: {
            checkedNames: function (newVal) {
                console.log(newVal)
                // 选项发生变化,重新计算价格
                this.recalculation(newVal);
            },
            checkedAll: function (Val) {
                var _this = this;
                if (!Val) {
                    _this.checkedNames = []
                    return false;
                }
                // 先置为空,保证checkedNames发生变化
                _this.checkedNames = []
                this.shopingcart.forEach(function (item, index) {
                    // _this.checkedNames[index] = true  此处有bug,为何?
                    _this.checkedNames.push(true)
                })
            }
        }
    })
    /*
    *  受现代js的限制,vue不能检测到对象属性的添加或删除。
    *  由于 Vue 会在初始化实例时对属性执行 getter/setter 转化过程,所以属性必须在 data 对象上存在才能让 Vue 转换它,这样才能让它是响应的
    * */
</script>
</body>
</html>

 

闲来无事,使用非node环境的vue,写一些功能,vue主要是数据的变化,个人感觉是这样,第一次写微博,难免疏漏,请谅解。

本人试过直接,把checkbox的value和text的value直接绑定,数量为空时会有true和false出现,所以用checkedNames数组的形式控制多个input值,数据变化参考最下方span标签。

这里还有个坑就是受现代js的限制,vue不能检测到对象属性的添加或删除。

本例子没使用es6箭头函数,因此使用_this获取vue对象。

本例子通过监听checkedNames的变化,每次重新计算所有商品的数量变化,从而实现所有商品价格的计算,有些地方感觉有bug,但是没弄懂,希望大家一起探讨