zoukankan      html  css  js  c++  java
  • 前端Vue项目——购物车页面

    一、加入购物车的两种策略

    1、加入购物车接口

      在 src/restful/api.js 中写入添加购物车接口:

    // 加入购物车的接口
    export const shopCart = (params) => {
      return Axios.post('user/shop_cart/create/', params).then(res=>res.data)
    };

    2、添加Axios的请求拦截器

      Axios 的拦截器:在请求或响应被 then 或 catch 处理前拦截它们,说明文档:Axios使用说明。模板如下所示:

    // 添加请求拦截器
    axios.interceptors.request.use(function (config) {
        // 在发送请求之前做些什么
        return config;
      }, function (error) {
        // 对请求错误做些什么
        return Promise.reject(error);
      });
    
    // 添加响应拦截器
    axios.interceptors.response.use(function (response) {
        // 对响应数据做点什么
        return response;
      }, function (error) {
        // 对响应错误做点什么
        return Promise.reject(error);
      });

      在项目 src/restful/api.js 中添加请求拦截器:

    import Axios from 'axios'  // 导入axios
    Axios.defaults.baseURL = 'https://www.luffycity.com/api/v1/';   // 设置公共url
    
    // 添加请求拦截器
    Axios.interceptors.request.use(function (config) {
      // 在发送请求之前做些什么
      if (localStorage.getItem('access_token')){
        // 配置的默认值/defaults
        // Axios.defaults.headers.common['Authorization'] = localStorage.getItem('access_token');
        console.log(config.headers);
        config.headers.Authorization = localStorage.getItem('access_token');
      }
      return config;
    }, function (error) {
      // 对请求错误做些什么
      return Promise.reject(error);
    });

      查看控制台 config.headers 中包含的信息:

      

    3、改写CouseDetail页面中购物车事件

    (1)课程信息获取

      添加购物车首先要获取当前课程信息。

    <script>
      export default {
        name: 'CourseDetail',
        data(){
          return {
            // 声明变量存储数据
            coursedetailtop: {},    // 课程顶部详情数据
            content: "",
            // currentIndex: 0,     // 为0时,页面刷新默认选择了第一项
            currentIndex: null,     // 默认不选择
            prices: []
          }
        },
        methods: {
          // 加入购物车事件
          addShopCart(){
            if(this.currentIndex){    // 判断当前currentIndex是否有值
              if(window.localStorage.getItem('access_token')){    // 判断用户是否登录
                // 添加到购物车
                alert('买吧');
                let course = {
                  courseId: this.$route.params.detailId,  // 课程id
                  validPeriodId: this.prices[this.currentIndex].valid_period,
                };
                console.log(course);
                // this.$http.shopCart();
    
              } else {
                // 跳转登录页面
                // 使用编程式导航来跳转// 代码略
    </script>

      在控制台查看打印的course对象:

      

    (2)添加购物车事件

    methods: {
      // 加入购物车事件
      addShopCart(){
        if(this.currentIndex){    // 判断当前currentIndex是否有值
          if(window.localStorage.getItem('access_token')){    // 判断用户是否登录
            // 添加到购物车
            alert('买吧');
            let course = {
              courseId: this.$route.params.detailId,  // 课程id
              validPeriodId: this.prices[this.currentIndex].valid_period,
            };
            console.log(course);
            this.$http.shopCart(course)
              .then(res=>{
                console.log("当前添加是否成功", res);
              })
              .catch(err=>{
                console.log('添加失败', err);
              })
    
          } else {
            // 跳转登录页面
            // 使用编程式导航来跳转
            this.$router.push({
              name: 'Login',
              query: {
                // window.location 只读属性,返回一个 Location  对象,其中包含有关文档当前位置的信息
                return_url: window.location.href,   // 将当前页面地址作为查询参数
              }
            })
          }
        } else {
          // element组件错误提示
          this.$message({
            message: '您还没有选择要加入的套餐哦!',
            center: true        // 使用 center 属性让文字水平居中
          });
        }
      },

      点击添加购物车显示效果如下:

      

      购物车没有当前课程时,点击添加后,信息为error_no:0,显示 “添加成功”。

      如果购物车已经有了当前课程,选择一个套餐后点击添加,信息为error_no:10,显示“购物车中该课程已更新成功”。

    二、购物车页面实现

    1、使用elementui显示加入购物车提示

      elementui中Message消息提示:常用于主动操作后的反馈提示。这里引入基础用法,从顶部出现,3秒后自动消失。

    methods: {
      // 加入购物车事件
      addShopCart(){
        if(this.prices[this.currentIndex]){    // 不能直接使用this.currentIndex,因为第一个值为0
          if(window.localStorage.getItem('access_token')){    // 判断用户是否登录
            // 添加到购物车
            alert('买吧');
            let course = {
              courseId: this.$route.params.detailId,  // 课程id
              validPeriodId: this.prices[this.currentIndex].valid_period,
            };
            console.log(course);
            this.$http.shopCart(course)
              .then(res=>{
                console.log("当前添加是否成功", res);
                if(res.error_no===0){
                  this.$message('购物车' + res.data.status);  // elementui提示框
                }
                if(res.error_no===10){
                  this.$message(res.msg);
                }
              })
              .catch(err=>{
                console.log('添加失败', err);
              })
    
          } else {
            // 跳转登录页面
            // 使用编程式导航来跳转
            this.$router.push({
              name: 'Login',
              query: {
                // window.location 只读属性,返回一个 Location  对象,其中包含有关文档当前位置的信息
                return_url: window.location.href,   // 将当前页面地址作为查询参数
              }
            })
          }
        } else {
          // element组件错误提示
          this.$message({
            message: '您还没有选择要加入的套餐哦!',
            center: true        // 使用 center 属性让文字水平居中
          });
        }
      },

      选择套餐后点击“加入购物车”,显示如下信息:

      

    2、购物车组件及路由

    (1)index.js中添加购物车组件路由

    // 代码略
    import Cart from '@/components/Cart/Cart'
    
    Vue.use(Router);
    
    // 配置路由规则
    export default new Router({
      linkActiveClass: 'is-active',
      mode: 'history',   // 改为history模式
      routes: [
        // 代码略
        // 购物车页面
        {
          path: '/purchase/shopping_cart',
          name: 'purchase.shop',
          component: Cart
        }
      ]
    })

    (2)创建购物车组件

      创建购物车文件夹及文件:src/components/Cart/Cart.vue

      使用elementUI中Table表格模板来构筑组件页面结构。Table表格可用于展示多条结构类似的数据,可对数据进行排序、筛选、对比或其他自定义操作。

      实现多选非常简单: 手动添加一个el-table-column,设type属性为selection即可。每个 el-table-column 组件中有 template,可以定义当前内容的展示。

      scope.row相当于获取了数组中的每一条数据。

    <template>
      <div class="shopping-cart-wrap">
        <h3 class="shopping-cart-tit">我的购物车<small>共1门课程</small></h3>
        <div class="row">
          <el-table
            ref="multipleTable"
            :data="shopCartList"
            tooltip-effect="dark"
            style=" 100%"
            @selection-change="handleSelectionChange">
            <el-table-column
              type="selection"
              width="55">
            </el-table-column>
            <el-table-column
              label="日期"
              width="120">
              <template slot-scope="scope">{{ scope.row.date }}</template>
            </el-table-column>
            <el-table-column
              prop="name"
              label="姓名"
              width="120">
            </el-table-column>
            <el-table-column
              prop="address"
              label="地址"
              show-overflow-tooltip>
            </el-table-column>
          </el-table>
        </div>
        <div class="total">
          <el-button type="primary">去结算</el-button>
          <h3>总计: ¥399</h3>
        </div>
      </div>
    </template>
    
    <script>
      export default {
        name:'Cart',
        data(){
          return {
    
          }
        },
      };
    </script>

    (3)页首按钮跳转购物车

    <div class="nav-right" v-if="userInfo.access_token" @mouseenter="enterHandler" @mouseleave="leaveHandler">
      <span class = 'el-dropdown-link'>学习中心</span>
      <span class="user">{{userInfo.username}}</span>
      <img :src="userInfo.avatar" alt="">
      <ul class="my_account" v-show="isShow">
        <li>我的账户<i>></i></li>
        <li>我的订单<i>></i></li>
        <li>我的优惠券<i>></i></li>
        <li>我的消息<span class="msg">({{userInfo.notice_num}})</span><i>></i></li>
        <li @click="shopCartInfo">购物车<span class="count">({{userInfo.shop_cart_num}})</span></li>
        <li>退出<i>></i></li>
      </ul>
    </div>
    
    methods: {
      shopCartInfo(){
        // 跳转到购物车路由
        this.$router.push({
          name: 'purchase.shop'
        })
      },

    三、购物车页面数据展示

    1、获取购物车页面接口

      在 src/restful/api.js 添加如下信息:

    // 购物车数据
    export const shopCartList = () => {
      return Axios.get('user/shop_cart/list/').then(res=>res.data);
    };

    2、car组件发送请求

      修改Cart.vue组件。

      handleSelectionChange(val) { this.multipleSelection = val; }  其中,val 为选中数据的集合。通过this.multipleSelection.prop字段 取得每一个选项的值,prop字段就是表格里面子项的prop值。this.multipleSelection.length为选择了多少项。

    <script>
      export default {
        name:'Cart',
        data(){
          return {
            multipleSelection: [], // 存放选中的当前数据
            shopCartList: [],
          }
        },
        methods: {
          getShopCartList(){
            this.$http.shopCartList()
              .then(res=>{
                console.log(res);
                if(res.error_no === 0){
                  this.shopCartList = res.data.myShopCart;
                }
              })
              .catch(err=>{
                console.log(err);
              })
          },
          handleSelectionChange(val){    // 处理点选
            this.multipleSelection = val;
          }
        },
        created() {
          this.getShopCartList();
        }
      };
    </script> 

    3、将数据绑定到template中

    (1)页面构建和数据绑定

      javascript:void(0) 中最关键的是 void 关键字, void 是 JavaScript 中非常重要的关键字,该操作符指定要计算一个表达式但是不返回值。

      有效期栏目中,添加select组件,点选到对应的有效期。HTML <select> 元素表示一个控件,提供一个选项菜单。菜单内的选项为<option> , 可以由 <optgroup> 元素分组。选项可以被用户预先选择。

    <div class="row">
      <el-table
        ref="multipleTable"
        :data="shopCartList"
        tooltip-effect="dark"
        style=" 100%"
        @selection-change="handleSelectionChange">
        <el-table-column
          type="selection"
          width="55">
        </el-table-column>
        <el-table-column
          label="课程"
          width="555">
          <template slot-scope="scope">
            <img :src="scope.row.courseImg" alt="">
            <a href="javascript:void(0);">{{scope.row.courseName}}</a>
          </template>
        </el-table-column>
        <el-table-column
          prop="name"
          label="有效期"
          width="212">
          <template slot-scope="scope">
            <select>
              <option v-for="(item, index) in scope.row.validPeriodChoices"
                  :value="item.validPeriodId" :key="index">
                有效期: {{item.validPeriodId}}
              </option>
            </select>
          </template>
        </el-table-column>
        <el-table-column
          prop="address"
          label="单价"
          show-overflow-tooltip>
          <template slot-scope="scope">
            ¥{{scope.row.coursePrice}}
          </template>
        </el-table-column>
      </el-table>
    </div>

      显示效果如下所示:

      

    (2)v-model默认选定selected

      在select中,当v-model的值等于option中的value,则默认选中。

    <el-table-column
      prop="name"
      label="有效期"
      width="212">
      <template slot-scope="scope">
        <select v-model="scope.row.validPeriodId">
          <option v-for="(item, index) in scope.row.validPeriodChoices"
              :value="item.validPeriodId" :key="index">
            有效期: {{item.validPeriodId}}
          </option>
        </select>
      </template>
    </el-table-column>

    四、购物车页面数据响应

    1、添加删除按钮

    (1)表格中添加操作列

      @click.native.prevent:调用组件原生的click事件,阻止默认事件发生。在封装好的组件上使用,所以要加上.native才能click。

      prevent就相当于 event.preventDefault():如果此事件没有被显式处理,那么它默认的动作也不要做(因为默认是要做的)。此事件还是继续传播,除非碰到事件侦听器调用stopPropagation() 或stopImmediatePropagation(),才停止传播。

    <el-table>
      <!--代码略-->
      <el-table-column
        fixed="right"
        label="操作"
        width="100">
        <template slot-scope="scope">
          <el-button @click.native.prevent="deleteRow(scope.$index, shopCartList)" type="text" size="small">
            删除
          </el-button>
          <el-button type="text" size="small">编辑</el-button>
        </template>
      </el-table-column>
    </el-table>

    (2)删除课程操作

      未完成

    methods: {
      // 删除课程
      deleteRow(index, rows){
        console.log(index);
        console.log(rows);
        rows.splice(index, 1);
    
      },

    2、监控课程总价变化

      使用computed实时监控鼠标点选课程总价变化。

    computed: {
      totalPrice(){
        let total_price = 0;
        this.multipleSelection.forEach((item,index)=>{  // 遍历数组中对象的价格
          // parseInt() 方法用于将字符串参数作为有符号的十进制整数进行解析
          total_price += parseInt(item.coursePrice)   // 将获取的价格相加
        });
        return total_price;
      }
    },

      显示效果如下所示

      

  • 相关阅读:
    ElasticSearch 之 Client
    Ubuntu 更新源
    ThinkPad 禁用 触摸板
    编译OpenGL代码时发生 Inconsistency detected by ld.so: dl-version.c: 224: _dl_check_map_versions: Assertion `needed != ((void *)0)' failed! 错误的解决方案
    python 自动认证登录
    RIDE的使用
    robotframework的分支和循环
    webdriver入门
    python字符串中的中文处理
    带认证的页面的自动认证登录
  • 原文地址:https://www.cnblogs.com/xiugeng/p/11341114.html
Copyright © 2011-2022 走看看