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

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="width: 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="width: 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;
}
},

  显示效果如下所示

  

前端Vue项目——购物车页面的更多相关文章

  1. 前端Vue项目——登录页面实现

    一.geetest滑动验证 geetest官方文档地址:https://docs.geetest.com/ 产品——极速验证:基于深度学习的人机识别应用.极验「行为验证」是一项可以帮助你的网站与APP ...

  2. 团队开发前端VUE项目代码规范

    团队开发前端VUE项目代码规范 2018年09月22日 20:18:11 我的小英短 阅读数 1658   一.规范目的: 统一编码风格,命名规范,注释要求,在团队协作中输出可读性强,易维护,风格一致 ...

  3. vue项目刷新页面,使数据不丢失(sessionStorage、localStorage、cookie)

    vue项目刷新页面时,存储在vuex中的数据会丢失,把他们存到stroage中可以保证不丢失.

  4. 前端Vue项目——首页/课程页面开发及Axios请求

    一.首页轮播图 1.elementUI走马灯 elementUI中 Carousel 走马灯,可以在有限空间内,循环播放同一类型的图片.文字等内容. 这里使用指示器样式,可以将指示器的显示位置设置在容 ...

  5. VUE项目实现页面跳转

    打开一个VUE项目,目录结构是这样的: 如现在有两个页面aaa和HelloWorld,路由配置在index.js中: import Vue from 'vue' import Router from ...

  6. 前端Vue项目——课程详情页面实现

    一.详情页面路由跳转 应用 Vue Router 编程式导航通过 this.$router.push() 来实现路由跳转. 1.绑定查看详情事件 修改 src/components/Course/Co ...

  7. 前端vue项目部署到tomcat,一刷新报错404解决方法

    公司前端写的后台部署到tomcat webapps目录下后,无法进行刷新,一刷新就会报错404,自动跳的404页面.在网上查了下,官方说是HTML5 History 模式引发的问题,但是解决方案中,并 ...

  8. 前端 | Vue 路由返回恢复页面状态

    需求场景:首页搜索内容,点击跳转至详情页,页面后退返回主页,保留搜索结果. 方案:路由参数:路由守卫 需求描述 在使用 Vue 开发前端的时候遇到一个场景:在首页进行一些数据搜索,点击搜索结果进入详情 ...

  9. 前端vue项目-关于下载文件pdf/excel(三)

    最近在做一些需求,需要下载一些文件信息,最频繁的就是下载excel文件到本地了 看过了很多方法,做个整理吧哈哈哈哈 参考的文章链接: https://www.cnblogs.com/jiangweic ...

随机推荐

  1. gradle中gredle -q 参数是什么意思

    很多地方在调用 gradle 命令时都加了 -q 参数.该参数用来控制 gradle 的日志级别,可以保证只输出我们需要的内容.

  2. iOS:捋一遍View的生命周期

    一.介绍 前面介绍了VC的生命周期,闲着没事也来捋一捋View的生命周期,简单用两个类型的View来监测.一个View纯代码创建,另一个View使用Xib创建. 二 .代码 MyCodeView:  ...

  3. LeetCode 136:只出现一次的数字 Single Number

    题目: 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次.找出那个只出现了一次的元素. Given a non-empty array of integers, every e ...

  4. IT兄弟连 HTML5教程 HTML5的靠山 W3C、IETF是什么

    无规矩不成方圆,软件开发当然不能例外.Web开发涉及的厂商和技术非常多,所以必须要有参考的标准,而且需要一系列的标准.Web程序都是通过浏览器来解析执行的,通过页面的展示内容与用户互动,所以Web标准 ...

  5. 利用Python进行数据分析-Pandas(第一部分)

    利用Python进行数据分析-Pandas: 在Pandas库中最重要的两个数据类型,分别是Series和DataFrame.如下的内容主要围绕这两个方面展开叙述! 在进行数据分析时,我们知道有两个基 ...

  6. P站全新官方精选集Pixivision

    P站是一个主要由日本艺术家所组成的虚拟社群,主打插画.漫画.二次元作品网上沟通. 不过好消息是,P站全新的精选网站Pixivision上线了,多种语言界面,国内用户访问毫无压力. 近期精选的一系列作品 ...

  7. go语言使用go-sciter创建桌面应用(八) 窗口显示时,自动加载后端数据。

    有些时候我们需要在窗口创建并显示时,加载一些后端的配置,这就需要用到view提供的几个事件. https://sciter.com/docs/content/sciter/View.htm state ...

  8. oracle学习笔记(八)——结果集元数据ResultSetMetaData以及ResultSet转为对应的实体类框架

    介绍 可用于获取关于 ResultSet 对象中列的类型和属性信息的对象,在持久框层框架(如:mybatis, hibernate)中被广泛的应用. 常用方法 int getColumnCount() ...

  9. Wpf Backgroundworker

    <Window x:Class="WpfApp53.MainWindow" xmlns="http://schemas.microsoft.com/winfx/20 ...

  10. Z从壹开始前后端分离【 .NET Core2.0/3.0 +Vue2.0 】框架之十 || AOP面向切面编程浅解析:简单日志记录 + 服务切面缓存

    本文梯子 本文3.0版本文章 代码已上传Github+Gitee,文末有地址 大神反馈: 零.今天完成的深红色部分 一.AOP 之 实现日志记录(服务层) 1.定义服务接口与实现类 2.在API层中添 ...