zoukankan      html  css  js  c++  java
  • Vue node.js商城-购物车模块

     

    一、渲染购物车列表页面

    新建src/views/Cart.vue
    获取cartList购物车列表数据就可以在页面中渲染出该用户的购物车列表数据

    1. data(){
    2.   return {
    3.      cartList:[] // 购物车商品列表
    4.   }
    5. },
    6. mounted:function(){
    7.   this.init();
    8. },
    9. methods:{
    10.   init(){ // 初始化商品数据
    11.     axios.get('/users/cartList').then((response)=>{
    12.       let res = response.data;
    13.       this.cartList = res.result;
    14.     })
    15.   }
    16. }

    购物车接口:server/routes/users.js

    1. // 查询当前用户的购物车数据
    2. router.get('/cartList',function(req,res,next){
    3.     var userId = req.cookies.userId;
    4.     User.findOne({userId:userId},function(err,doc){
    5.         if(err){
    6.             res.json({
    7.                 status:'1',
    8.                 msg:err.message,
    9.                 result:''
    10.             });
    11.         }else{
    12.             if(doc){
    13.                 res.json({
    14.                     status:'0',
    15.                     msg:'',
    16.                     result:doc.cartList
    17.                 })
    18.             }
    19.         }
    20.     })
    21. })

    建立路由src/router/index.js

    1. import Cart from '@/views/Cart' // 购物车列表
    2. export default new Router({
    3.   routes: [
    4.     {
    5.       path: '/cart', // 购物车列表路由
    6.       name: 'Cart',
    7.       component: Cart
    8.     }
    9.  
    10.   ]
    11. })

    二、购物车商品删除功能

    购物车删除接口:server/routes/users.js

    1. // 购物车删除功能
    2. router.post('/cartDel',function(req,res,next){
    3.     var userId = req.cookies.userId,productId = req.body.productId;
    4.     User.update({
    5.         userId:userId
    6.     },{
    7.         $pull:{
    8.             'cartList':{
    9.                 'productId':productId
    10.             }
    11.         }
    12.     },function(err,doc){
    13.         if(err){
    14.             res.json({
    15.                 status:'1',
    16.                 msg:err.message,
    17.                 result:''
    18.             });
    19.         }else{
    20.             res.json({
    21.                 status:'0',
    22.                 msg:'',
    23.                 result:'suc'
    24.             });
    25.         }
    26.     })
    27. });

    src/views/Cart.vue

    1. 点击删除图标模态框出现(导入模态Modal.vue子组件)
    2. <!-- 删除图标 -->
    3. <a href="javascript:;" class="item-edit-btn" @click="delCartConfirm(item.productId)">
    4.     <svg class="icon icon-del">
    5.         <use xlink:href="#icon-del"></use>
    6.     </svg>
    7. </a>
    8.  
    9. <!-- 模态框 -->
    10. <Modal :mdShow="modalConfirm" @close="closeModal">
    11.     <p slot="message">你确认要删除此条数据吗?</p>
    12.     <div slot="btnGroup">
    13.         <a href="javascript:;" class="btn btn--m" @click="delCart">确认</a>
    14.         <a href="javascript:;" class="btn btn--m" @click="modalConfirm = false">关闭</a>
    15.     </div>
    16. </Modal>
    17. import Modal from '@/components/Modal.vue' // 模态框
    18. export default {
    19.     data(){
    20.         return {
    21.           productId:'',
    22.           modalConfirm:false // 模态框是否显示
    23.         }
    24.     },
    25.     components:{
    26.       Modal
    27.     },
    28.     methods:{
    29.       delCartConfirm(productId){ // 点击删除图标
    30.         this.productId = productId;
    31.         this.modalConfirm = true; // 模态框显示
    32.       },
    33.       closeModal(){ // 关闭模态框
    34.         this.modalConfirm = false;
    35.       },
    36.       delCart(){ // 确认删除此商品
    37.         axios.post('/users/cartDel',{
    38.           productId:this.productId
    39.         }).then((response) => {
    40.           let res = response.data;
    41.           if(res.status = '0'){
    42.             this.modalConfirm = false; // 关闭模态框
    43.             this.init(); // 重新初始化购物车数据
    44.           }
    45.         })
    46.       }
    47.     }
    48. }

    **** 在这里发现一个bug,在商品列表页点击"加入购物车",购物车页面新添加的商品数量和总价格是未定义。mongoose添加属性问题

    这是后端接口处理的问题,在server/routes/goods.js的加入到购物车接口中,是从mongodb的数据库dumallgoods表根据商品id获取对应数据,再对此商品数据添加productNumchecked属性,之后再插入到users表的购物车列表中的。

    属性没有添加成功,在Goods模型中添加属性,要去models/goods.jsSchema添加这两个属性。

    1. server/models/goods.js
    2. // 定义一个Schema
    3. var produtSchema = new Schema({
    4.    'productId':String,
    5.    'productName':String,
    6.    'salePrice':Number,
    7.    'productImage':String,
    8.  
    9.     // 添加的属性
    10.     "checked":String,
    11.     "productNum":Number
    12. })
    13. module.exports = mongoose.model('good',produtSchema);

     

    重新启动express(node server/bin/www)

    三、购物车商品修改功能

    商品加减和商品勾选

    server/routes/users.js

    1. //修改商品数量接口
    2. router.post("/cartEdit",function(req,res,next){
    3.     var userId = req.cookies.userId,
    4.         productId = req.body.productId,
    5.         productNum = req.body.productNum,
    6.         checked = req.body.checked;
    7.     User.update({ // 查询条件
    8.         "userId":userId,
    9.         "cartList.productId":productId
    10.     },{ // 修改的数据
    11.         "cartList.$.productNum":productNum,
    12.         "cartList.$.checked":checked
    13.     },function(err,doc){
    14.         if(err){
    15.           res.json({
    16.             status:'1',
    17.             msg:err.message,
    18.             result:''
    19.           });
    20.         }else{
    21.           res.json({
    22.             status:'0',
    23.             msg:'',
    24.             result:'suc'
    25.           });
    26.         }
    27.     });
    28. })

    src/views/Cart.vue

    1. <!--选中图标-->
    2. <a href="javascipt:;" class="checkbox-btn item-check-btn" v-bind:class="{'check':item.checked=='1'}" @click="editCart('checked',item)">
    3.     <svg class="icon icon-ok">
    4.         <use xlink:href="#icon-ok"></use>
    5.     </svg>
    6. </a>
    7. <!--加减图标-->
    8. <a class="input-sub" @click="editCart('minu',item)">-</a>
    9. <a class="input-add" @click="editCart('add',item)">+</a>
    10.  
    11. methods:{
    12.     editCart(flag,item){
    13.         if(flag == 'add'){ // 添加商品数量
    14.           item.productNum++;
    15.         }else if(flag = 'minu'){ // 减少商品数量
    16.           if(item.productNum <= 1){
    17.             return;
    18.           }
    19.           item.productNum--;
    20.         }else{ // 商品控制选中
    21.           item.checked = (item.checked=='1') ? '0' : '1';
    22.         }
    23.         axios.post('/users/cartEdit',{
    24.           productId:item.productId,
    25.           productNum:item.productNum,
    26.           checked:item.checked
    27.         }).then((response)=>{
    28.           let res = response.data;
    29.         })
    30.       }
    31. }

    购物车全选和商品实时计算功能

    • 全选和取消全选

    server/routes/users.js

    1. //全选和取消全选
    2. router.post('/editCheckAll',function(req,res,next){
    3.     var userId = req.cookies.userId,
    4.       checkAll = req.body.checkAll?'1':'0';
    5.     User.findOne({userId:userId},function(err,user){
    6.         if(err){
    7.           res.json({
    8.             status:'1',
    9.             msg:err.message,
    10.             result:''
    11.           });
    12.         }else{
    13.           if(user){
    14.             user.cartList.forEach((item)=>{
    15.               item.checked = checkAll;
    16.             })
    17.             user.save(function (err1,doc) {
    18.                 if(err1){
    19.                   res.json({
    20.                     status:'1',
    21.                     msg:err1,message,
    22.                     result:''
    23.                   });
    24.                 }else{
    25.                   res.json({
    26.                     status:'0',
    27.                     msg:'',
    28.                     result:'suc'
    29.                   });
    30.                 }
    31.             })
    32.           }
    33.         }
    34.     })
    35. })

    src/views/Cart.vue

    1. <a href="javascipt:;" @click="toggleCheckAll">
    2.     <span class="checkbox-btn item-check-btn" v-bind:class="{'check':checkAllFlag}">
    3.         <svg class="icon icon-ok"><use xlink:href="#icon-ok"/></svg>
    4.     </span>
    5.     <span>Select all</span>
    6. </a>
    7.  
    8. export default {
    9.     data(){
    10.         return {
    11.           checkAllFlag:false // 控制全选
    12.         }
    13.     },
    14.     methods:{
    15.       toggleCheckAll(){ // 全选和取消全选
    16.         this.checkAllFlag = !this.checkAllFlag; // 取反
    17.         this.cartList.forEach((item)=>{
    18.           item.checked = this.checkAllFlag;
    19.         })
    20.         axios.post('/users/editCheckAll',{
    21.           checkAll:this.checkAllFlag
    22.         }).then((response)=>{
    23.           let res = response.data;
    24.           if(res.status=='0'){
    25.             console.log("update suc");
    26.           }
    27.         })
    28.       }
    29.     }
    30. }

     

    这里出现一个问题,在点击select All全选之后,显示正常,但是刷新页面之后全选的图标没有显示全选,因为全选的信息没有存储到数据库保存,所以刷新之后就没有了。

    【解决的办法】

    用到了实时计算的computed功能,实时计算的是属性,只不过是函数的写法,data里面就不用在声明了。

    src/views/Cart.vue

    1. export default {
    2.     data(){
    3.         return {
    4.           // checkAllFlag:false // 控制全选
    5.         }
    6.     },
    7.     computed:{ // 实时计算的是属性,只不过是函数的写法,data里面就不用在声明了
    8.       checkAllFlag(){ // 是否全选属性
    9.         return this.checkedCount == this.cartList.length; // 勾选的商品种数=购物车商品列表的商品种数时,返回true代表全选。
    10.       },
    11.       checkedCount(){ // 获取已勾选的商品种数(几种商品已勾选)
    12.         var i = 0;
    13.         this.cartList.forEach((item)=>{
    14.           if(item.checked=='1')i++;
    15.         });
    16.         return i;
    17.       }
    18.     },
    19.     methods:{
    20.       toggleCheckAll(){ // 全选和取消全选
    21.         // this.checkAllFlag = !this.checkAllFlag;
    22.         // 不能使用这种写法了,checkAllFlag是实时计算的属性,如果true取反变成false之后,还没来得及执行下面的所有商品取消勾选,就实时计算了检测到勾选的商品种数=购物车商品列表的商品种数,就又变成全选了。
    23.         var flag = !this.checkAllFlag; // 声明变量取代
    24.         this.cartList.forEach((item)=>{
    25.           item.checked = flag ?'1':'0';
    26.         })
    27.         axios.post('/users/editCheckAll',{
    28.           checkAll:flag
    29.         }).then((response)=>{
    30.           let res = response.data;
    31.           if(res.status=='0'){
    32.             console.log("update suc");
    33.           }
    34.         })
    35.       }
    36.     }
    37. }

     

    页面一刷新就实时计算了

    • 商品实时计算功能实现

    这里也要用到computed计算属性

    1. <div class="item-total">
    2.   Item total: <span class="total-price">{{totalPrice}}</span>
    3. </div>
    4.  
    5. computed:{
    6.     totalPrice(){ // 总价格属性
    7.         var money = 0;
    8.         this.cartList.forEach((item)=>{
    9.             if(item.checked=='1'){
    10.                 money += parseFloat(item.salePrice)*parseInt(item.productNum);
    11.             }
    12.         });
    13.         return money;
    14.     }
    15. }

     

    接下来要对价格进行格式化,vuex官网github有一个对购物车将格式化的函数https://github.com/vuejs/vuex/blob/dev/examples/shopping-cart/currency.js 可以拿过来对价格格式化,在src/util/currency.js

    格式化要用到过滤器:可以在src/views/Cart.vue导入使用局部过滤器,也可以在main.js使用全局过滤器

    1. <span class="total-price">{{totalPrice | currency('$')}}</span>
    2.  
    3. // 局部过滤器
    4. import {currency} from '@/util/currency.js'
    5. filters:{
    6.   currency:currency // currency.js传过来的本就是函数
    7. },
    8.  
    9. // 全局过滤器
    10. import {currency} from './util/currency'
    11. Vue.filter("currency",currency);

     

  • 相关阅读:
    tar命令,vi编辑器
    Linux命令、权限
    Color Transfer between Images code实现
    利用Eclipse使用Java OpenCV(Using OpenCV Java with Eclipse)
    Matrix Factorization SVD 矩阵分解
    ZOJ Problem Set
    Machine Learning
    ZOJ Problem Set
    ZOJ Problem Set
    ZOJ Problem Set
  • 原文地址:https://www.cnblogs.com/wangyawei/p/9236795.html
Copyright © 2011-2022 走看看