
1.添加购物车+验证登录状态
2.右上方购物车图标的小红圆圈数字
3.Vuex
4.购物车页面展示-后端接口
5.购物车页面展示-前端
6.解决一个购物车数量显示混乱的bug
1.添加购物车+验证登录状态1.添加购物车的整体思想购物车数据要存到redis中的:要存用户ID,课程ID
用户在课程详情页面点击了加入购物车:
拿到当前课程的课程ID 到数据库把课程ID所对应的信息(需要在购物车显示的)加工成一个字典,然后Json序列化成字符串保存到redis中
如何实现点击添加购物车,将购物车数据添加到redis中??????
2.添加购物车-后端接口1.创建一个cart应用,并配置INSTALLAPP
python3 ../../ manage.py startapp cart
2.总路由中添加cart
# lyAPI/urls.pypath('cart/',include("cart.urls") ),
3.cart/urls.py
from django.urls import path,re_pathfrom . vIEwsurlpatterns = [ path(add_cart/post':add'}))]
4.cart/vIEws.py
from rest_framework.vIEwsets VIEwsetfrom django_redis get_redis_connectionfrom course modelsfrom rest_framework.response Responseclass AddCartVIEw(VIEwSet): def add(self,request): course_ID = request.data.get(course_ID) user_ID = 1 先把用户ID写死 去redis里存数据 conn = get_redis_connection(cart) 校验一下课程ID是否合法 try: models.Course.objects.get(ID=course_ID) except: return Response({msg课程不存在'},status=400) '''选择用集合的数据类型去存储''' conn.sadd(cart_%s' % user_ID,course_ID) vheader右方的购物车小红数字显示 cart_length = conn.scard(' % user_ID) 获取商品数量 添加成功',cart_length dev.pyCACHES = { ...... ":{ BACKEND": django_redis.cache.RedisCache,LOCATIONredis://127.0.0.1:6379/3OPTIONS: { CLIENT_CLASSdjango_redis.clIEnt.DefaultClIEnt<!-- HTML --><div ="add-cart" @click="addCart"><img src="/static/img/cart-yellow.svg" alt="">加入购物车</div>注意:添加购物车要验证用户是否已经登录
axios发送的是异步请求,setting.Js里的check_login()函数和Detail.vue中的addCart是同步执行的,但是addCart添加购物车时需要验证登录状态的,
会出现:我这边还没有验证token呢,添加购物车那边就已经执行到检测token的代码位置了。
所以现在我们需要将两个请求变为同步请求,让token验证之后再进行别的 *** 作
异步改成同步还是比较麻烦的,所以我们直接将验证token的 *** 作写在addCart添加购物车方法里
// Js addCart(){ 获取前端存储的token值 let token = localstorage.token || sessionStorage.token; 如果token值存在 if (token){ 验证token this.$axios.post(`${this.$settings.Host}/users/verify/`,{ token:token,}).then((res)=>{ 验证通过,可以添加购物车 this.$settings.Host}/cart/add_cart/`,{ 获取课程ID course_ID:this.course_ID,1)">{ 添加购物车成功,打印添加成功的信息 .$message.success(res.data.msg); }) 验证没有通过(token错误或者token过期) 提示用户让用户去登录 }).catch((error)=>{ this.$confirm('您还没有登录!!!?','31s''取消' }).then(() => { this.$router.push('/user/login'); }) 将过期的token清理掉 sessionStorage.removeItem('token'); sessionStorage.removeItem('username'); sessionStorage.removeItem('ID'); localstorage.removeItem('token'); localstorage.removeItem('username'); localstorage.removeItem('ID'); }) } token获取不到 else { ); }) } },2.右上方购物车图标的小红圆圈数字
我们在后端已经将购物车的长度返回了,在前端我们就可以拿到购物车的长度
Detail.vue .$message.success(res.data.msg); 获取到后端发送过来的购物车长度 this.cart_length = res.data.cart_length })
现在就会有一个问题,我们这个cart_length数据属性是在Detail组件里面的,但是那个右上方购物车小红圆圈是在vheader组件里面的。不同组件之间的数据不是互通的
第一种思路:vheader组件是detail组件的子组件,我们可以通过vue的父子传值来实现。
那问题就来了
如果我们访问实战课页面 也就是/course,在course组件是不也要显示那个购物车小红圆圈?
但是在course组件我们根本就没有去获取购物车的长度。所以红圆圈数字根本显示不出来。所以父子传值这个思路行不通。
3.Vuex因为对于一些数据,需要在多个组件中即时共享,所以根据上述的问题,我们引出vuex
1.安装Vuexnpm install -S vuex2.把vuex注册到vue中
在src目录下创建store目录,并在store目录下创建一个index.Js文件,index.Js文件代码
store/index.Jsimport Vue from 'vue'import Vuex from 'vuex'Vue.use(Vuex) export default new Vuex.Store({ state: { 数据仓库,类似vue里面的data cart_length: 0 购物车数据 },mutations: { 数据 *** 作方法,类似vue里面的methods add_cart (state,cart_length) { state.cart_length = cart_length; 修改购物车的商品总数 } }})3.挂载store对象
把上面index.Js中创建的store对象注册到main.Js的vue中。
main.Jsimport Vue from 'vue'import App from './App'import router from './router'import store from './store'; 引入 Vue({ el: '#app' 挂载 components: { App },template: '<App/>'})4.Vheader组件读取store的数据(读取购物车长度)
在Vheader.vue头部组件中,直接就可以读取store里面的数据
router-link to="/"> b>{{$store.state.cart_length}}="@/assets/shopcart.png"span>购物车 >router-link>5.Detail组件修改store的数据(修改购物车长度)
当用户点击添加购物车时,触发addCart中的post方法,将购物车的长度进行修改
{ .$message.success(res.data.msg); 从后端获取到的购物车长度不存在当前组件的数据属性中了,而是存到vuex中 this.$store.commit('add_cart',res.data.cart_length) ; commit用来触发mutation中声明的方法})6.关于页面刷新,vuex数据丢失问题
问题:vuex中的数据是存放在内存中的,页面一刷新,vuex中的数据就没有了
解决方式:用户点击刷新时,我们可以监听用户刷新的这个动作,可以在刷新之前对页面做一些动作。
当点击刷新时,我们先把数据存到sessionStorage或localstorage中,
页面刷新完成之后,再把数据取回来放到vuex中。这样的话就可以做到页面刷新了,数据也没有丢。
1.点击刷新,将数据存到sessionStorage中app.vue<script>export default { name: 'App' 页面刷新之前把cart_length数据存到了sessionStorage中 window.addEventListener('beforeunload',()=>{ console.log('页面要刷新啦!!!,赶紧保存数据!!!!'); sessionStorage.setItem('cart_length',.$store.state.cart_length); }) }}</script>2..页面刷新完成之后,将数据从sessionStorage取出来放到vuex中
vheader.vue created() { if (this.$store.state.cart_length === 0) { let cart_length = sessionStorage.getItem('cart_length'); this.$store.commit('add_cart'5.购物车页面展示-前端1.购物车前端的初始界面utils/exceptions.pyfrom rest_framework.vIEws exception_handlerfrom django.db DatabaseError Responsefrom rest_framework statusfrom redis import RedisError 引入redis异常 logginglogger = logging.getLogger(django) custom_exception_handler(exc,context): """ 自定义异常处理 :param exc: 异常类 :param context: 抛出异常的上下文 :return: Response响应对象 """ 调用drf框架原生的异常处理方法 response = exception_handler(exc,context) if response is None: vIEw = context[vIEw'] 错误出现的那个函数或者方法 if isinstance(exc,DatabaseError) or isinstance(exc,RedisError): 数据库异常/redis异常 logger.error([%s] %s (vIEw,exc)) response = Response({message': 服务器内部错误'},status=status.http_507_INSUFFICIENT_STORAGE) return responseredis的异常捕获以及记录错误日志4.购物车页面展示-后端接口1.添加购物车-课程有效期1.在后端设置一个默认有效期
2.添加购物车时将有效期也存到redis中:之前的redis数据存储结构是集合,但是现在集合已经满足不了我们的需求了。要使用哈希数据类型存储。
哈希数据类型结构如下所示:
user_ID:{ course_ID:expire,course_ID:expire,} '''cart/vIEws.py AddCartVIEw(VIEwSet): 有效期:表示永久有效 存用户对应的课程ID和有效期 conn.hset(存放用户的购物车长度 cart_length = conn.hlen( user_ID) ......在上面的代码中,我们可以看到一共建立了两次conn连接,这样并不是很好,所以我们借助一个redis的管道pipe
pipe = conn.pipeline() 创建管道pipe.multi() 将下面两个指令放到管道里面pipe.hset(cart_length = pipe.hlen( user_ID)pipe.execute() 执行上面两条指令2.购物车列表-后端接口cart_List(self,request): user_ID = 1 用户ID先写死 conn = get_redis_connection(') 获取cart对应的redis库对象 将当前用户所对应的课程ID从redis中取出来 ret = conn.hgetall(' % user_ID) 封装成了字典{课程ID,有效期},dict {b'1': b'0',b'2': b'0'} cart_data_List = [] for cID,eID in ret.items(): cID:课程ID eID:有效期 redis中存的是字节 所以要解码 course_ID = cID.decode(utf-8) expire_ID = eID.decode() course_obj = models.Course.objects.get(ID=course_ID) 前端所需要的购物车数据包括 1.课程名称 2.课程封面图 3.课程价格 4.课程有效期 so 我们自己创建一个数据结构去存储前端所需要的内容 cart_data_List.append({ name:course_obj.name,1)">course_img':contains.SERVER_ADDR + course_obj.course_img.url,1)"> 图片路径是相对路径,我们将其变为绝对路径price:course_obj.price,1)">expire_ID:expire_ID }) Exception: logger.error(获取购物车数据失败) 后台数据库出问题了,请联系管理员status.http_507_INSUFFICIENT_STORAGE) 将数据响应给前端 xxxcart_data_List':cart_data_List})
...
2.将cart组件注册到路由上import Vue from 'vue'import Cart from '@/components/Cart'Vue.use(Router)export Router({ mode:'history'3.关于cart组件和cartitem组件
在购物车页面中,整个购物车是一个组件(cart组件),然后要展示的每条购物车数据又是一个子组件(cartitem组件)
cart.vue HTML部分 ="cart_course_List"CartItem v-for="(value,index) in cart_data_List" :key="index" :cart="value"></CartItem> 001 :cart 父组件往子组件传值 >
cart.vue Js部分<script>import CartItem from "./common/CartItem" { name: "Cart"return { cart_data_List:[],} },methods:{ },created() { let token = sessionStorage.token || localstorage.token; (token){ this.$axios.get(`${this.$settings.Host}/cart/add_cart/`) // 获取购物车数据 .then((res)=>{ this.cart_data_List = res.data.cart_data_List }) ..$message.error(error.response.data.msg); }) } { ); } },components:{ CartItem,}}</script>
父组件拿着自己的值 cart_data_List 传递给每个子组件进行渲染(父组件往子组件传值)
// cartitem.vuetemplate="cart_item"> ="cart_column column_1"> el-checkBox ="my_el_checkBox" v-model="checked"el-checkBox="cart_column column_2":src="cart.course_img"="/course/detail/1">{{cart.name}}="cart_column column_3"el-select v-model="cart.expire_ID" size="mini" placeholder="请选择购买有效期" class="my_el_select"> el-option label="1个月有效" value="30" key="30"el-option="2个月有效"="60"="60"="3个月有效"="90"="90"="永久有效"="0"="0"el-select="cart_column column_4">¥{{cart.price}}>删除>script>export default { name: "CartItemreturn { checked:false'cart// 002:子组件接受父组件传过来的值}>6.解决一个购物车数量显示混乱的BUG1.页面刷新导致的vuex数据重置
解决方法:页面刷新前将数据存到SessionStorage
App.vue<script>{ sessionStorage.setItem('cart_length',1)">.$store.state.cart_length); }) }}</script>2.不同页面显示的购物车小红圆圈数量不一致
在组件加载的时候,会执行vheader中的created方法,拿到sessionStorage的值
let cart_length = sessionStorage.getItem('cart_length');
created(){ this.$store.state.cart_length === 0){ 如果购物车没有数据 let cart_length = sessionStorage.getItem('cart_length'); 就去sessionStorage中拿数据 并将数据存放到vuex中 } },
总结 以上是内存溢出为你收集整理的day83:luffy:添加购物车&导航栏购物车数字显示&购物车页面展示全部内容,希望文章能够帮你解决day83:luffy:添加购物车&导航栏购物车数字显示&购物车页面展示所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)