【vue】饿了吗项目 – goods商品列表开发

PS:结合自己这几天看的,以及前人给出的经验,借鉴他人的博客,总结出下面的内容)

1.flex 属性是 flex-grow、flex-shrink 和 flex-basis 属性的简写属性。

  • flex-grow 一个数字,规定项目将相对于其他灵活的项目进行扩展的量。
  • flex-shrink 一个数字,规定项目将相对于其他灵活的项目进行收缩的量。
  • flex-basis 项目的长度。合法值:”auto”、”inherit” 或一个后跟 “%”、”px”、”em”或任何其他长度单位的数字。
    px和emde 区别
    任意浏览器的默认字体高都是16px。所有未经调整的浏览器都符合: 1em=16px。那么12px=0.75em,10px=0.625em。
    参考:https://blog.csdn.net/chenjuan1993/article/details/81356497

2.采用绝对定位,相对于父元素

.gooddisplay: flexposition: absolutewidth: 100%top: 174pxbottom: 46pxoverflow: hidden

3.使用vue-resourse获取json并应用到模板

现在越来越多的数据传输方式都是json数据格式,包括用jquery开发时,也有很好用的$.ajax来进行数据请求与处理,那么vue-resource提供了一种类似的,并且api更加简洁易用,压缩后文件更小。配合ES 6的Lambda写法,更加优雅
官网:https://github.com/pagekit/vue-resource/blob/master/docs/http.md

props: {seller: {type: Object}},data () {return {goods: [],  //一开始goods为空listHeight: [],scrolly: 0,selectedFood: {}};},created() {   //当这个组件被调用的时候,通过后端获得数据赋值给goodsthis.$http.get(‘/api/goods‘).then((response) => {  //   ‘/api/goods‘请求的是data.json下的goods数组response = response.body;if (response.errno === ERR_OK) {this.goods = response.data;this.$nextTick(() => {  //可以用 $nextTick 來确保Dom变化后再执行一些事情this._initScroll();this._calculateHeight();});}});this.classMap = [‘decrease‘, ‘discount‘, ‘special‘, ‘invoice‘, ‘guarantee‘];},

注:vue更新到2.0之后,作者就宣告不再对vue-resource更新,而是推荐的axios,它的基本用法可以参考:http://www.kancloud.cn/yunye/axios/234845

4.遍历取数据

<span class="text"><span v-show="item.type>0" class=" icon" :class="classMap[item.type]"></span>{{item.name}}
</span>   

classMap[item.type]是一个数组,通过item.type去取对应的class,item.type是data.json中mock的数据

5.display table

此元素会作为块级表格来显示(类似

),表格前后带有换行符。

在table中可用vertical-align:middle实现垂直居中

6.添加better-scroll依赖

链接:https://github.com/ustbhuangyi/better-scroll

<div class="menu-wrapper" ref="menuWrapper"><ul><li v-for="(item, index) in goods" class="menu-item border-1px" :class{‘current‘:currentIndex === index}" @click="selectMenu(index, $event)"><span class="text"><span v-show="item.type>0" class=" icon" :class="classMap[item.type]"  </span>{{item.name}}</span></li></ul>
</div>
<div class="foods-wrapper" ref="foodWrapper"><ul><li v-for="item in goods" class="food-list food-list-hook"><h1 class="title">{{item.name}}</h1><ul><li v-for="food in item.foods" class="food-item" @click="selectFood(food, $event)"><div class="icon"><img :src="food.icon" alt="" width="57"></div><div class="content"><h2 class="name">{{food.name}}</h2><p class="desc">{{food.description}}</p><div class="extra"><span class="count">月售{{food.sellCount}}</span><span class="count">好评{{food.rating}}</span></div><div class="price"><span class="now">¥{{food.price}}</span><span class="old" v-show
="food.oldPrice">¥{{food.oldPrice}}</span></div><div class="cartControl-wrapper"><cartControl :food="food" @increment="incrementTotal"></cartControl></div></div></li></ul></li></ul></div>

6.1 $refs 的使用是vue 2 操作dom的一种方式

ref 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。

如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素; 如果用在子组件上,引用就指向组件实例:

     _initScroll(){//初始化scroll区域this.menuScroll = new BScroll(this.$refs.menuWrapper, {click: true //结合BScroll的接口使用,是否将click事件传递,默认被拦截了});this.foodsScroll = new BScroll(this.$refs.foodsWrapper, {probeType: 3 //结合BScroll的接口使用,3实时派发scroll事件,探针的作用});//结合BScroll的接口使用,监听scroll事件(实时派发的),并获取鼠标坐标,当滚动时能实时暴露出scrollthis.foodsScroll.on(‘scroll‘, (pos) => { //事件的回调函数this.scrollY = Math.abs(Math.round(pos.y));//滚动坐标会出现负的,并且是小数,所以需要处理一下,实时取得scrollY}) }

vue中更改数据,DOM会跟着做映射,但vue更新DOM是异步的,用 $nextTick ()来确保Dom变化后能调用到_initScroll()方法。调用_initScroll()方法能计算内层ul的高度,当内层ul的高度大于外层wrapper的高度时,可以实现滚动。

6.2 左右两边联动

在vue实例生命周期的开始created分别加载 _initScroll_calculateHeight

  • 通过 _calculateHeight 计算foods内部每一个块的高度,组成一个数组listHeight
  • 在_initScroll里面,设置了bscroll插件的一个监听事件scroll,将food区域当前的滚动到的位置的y坐标设置到一个vue实例属性scrollY: this.scrollY = Math.abs(Math.round(pos.y));(取整舍入操作)
  • 通过计算属性currentIndex,获取到food滚动区域对应的menu区域的子块的索引,然后通过设置一个class来做样式切换变化 :class=”{‘current‘:currentIndex === index} ,实现联动

另外当点击menu 区域的时候,会触发selectMenu事件,也会根据点击到的menu子块的索引然后去触发food区域滚动到对应的高度区块区间 this.foodsScroll.scrollToElement(el, 300);scrollToElement():是better-scroll中的方法,滚动到某个元素,el(必填)表示 dom 元素,time 表示动画时间,offsetX 和 offsetY 表示坐标偏移量,easing 表示缓动函数

这样完成整个对应

_calculateHeight()方法计算各个右侧区间的高度

 _calculateHeight(){let foodList = this.$refs.foodsWrapper.getElementsByClassName(‘food-list-hook‘); //获取每一个food的dom对象let height = 0;this.listHeight.push(height); //初始化第一个高度为0for (let i = 0; i < foodList.length; i++) {let item = foodList[i]; //每一个item都是刚才获取的food的每一个domheight += item.clientHeight; //主要是为了获取每一个foods内部块的高度this.listHeight.push(height);}}}

实时取得scrollY的值后,需要与左边进行映射,利用计算属性:

**computed: {currentIndex(){ //计算到达哪个区域的区间的时候的对应的索引值for (let i = 0; i < this.listHeight.length; i++) {let height1 = this.listHeight[i]; //当前menu子块的高度let height2 = this.listHeight[i + 1]; //下一个menu子块的高度//滚动到底部的时候,height2为undefined,需要考虑这种情况//需要确定是在两个menu子块的高度区间if (!height2 || (this.scrollY >= height1 && this.scrollY < height2)) {return i; //返回这个menu子块的索引}}return 0;},selectFoods() { //自动将所有的goods.food添加一个count属性,方便做数量运算let foods = [];this.goods.forEach((good) => {good.foods.forEach((food) => {if (food.count) {foods.push(food);}});});return foods;}}**

:class=”{‘current‘:currentIndex === index}”当currentIndex === index时才设置current这个class

点击左侧 ,右侧响应:

关于在selectMenu中点击,在pc界面会出现两次事件,在移动端就只出现一次事件的问题:

原因:bsScrooler会监听事件(例如touchmove,click之类),并且阻止默认事件(prevent stop),并且他只会监听移动端的,pc端的没有监听

在pc页面上 bsScroller也派发了一次click事件,原生也派发了一次click事件

//bsScroll的事件,有_constructed: true
MouseEvent {isTrusted: false, _constructed: true, screenX: 0, screenY: 0, clientX: 0…}
//pc的事件
MouseEvent {isTrusted: true, screenX: -1867, screenY: 520, clientX: 53, clientY: 400…}

解决:针对bsScroole的事件,有_constructed: true,所以做处理,return掉非bsScroll的事件

selectMenu(index, event){if (!event._constructed) { //去掉自带的click事件点击,即pc端直接返回return;}let foodsList = this.$refs.foodsWrapper.getElementsByClassName(‘food-list-hook‘);let el = foodsList[index];//类似jump to的功能,通过这个方法,跳转到指定的domthis.foodsScroll.scrollToElement(el, 300);},

7.shopcart组件

也是采用flex布局,右侧部分固定宽度(flex: 0 0 105px)(width :105px),左边自适应宽度(flex: 1)

采用固定定位,定位在底部(position: fixed)

横向排列display:inline-block

包含购物车图标的div超出了父元素的高度,我们使用position:relative,并设置top为负来实现

box-sizing: border-box;(IE盒模型) 则div 设置的宽高将包含 边框及 padding

border-radius 50%,形成一个圆

选择了多少商品:定义成数组,底栏其余部分的变化都基于这个对象的变化而变化

selectFoods: {type: Array,default() {return [{price: 20, count: 2}];}}

计算部分(都基于selectFoods进行相应计算)computed中的函数可以直接在Tempplate中以指针的形式引用

computed: {totalPrice() {//计算总价,超过起送额度后提示可付款let total = 0;this.selectFoods.forEach((food) => {total += food.price * food.count;});return total;},
  totalCount() {//计算选中的food数量,在购物车图标处显示,采用绝对定位,top:0;right:0;显示在购物车图标右上角let count = 0;this.selectFoods.forEach((food) => {count += food.count;});return count;}

控制底部右边内容随food的变化而变化,payDesc()控制显示内容,payClass()添加类调整显示样式

 在template中  <div class="pay" :class="payClass">{{payDesc}}</div>    
在computed中:
payDesc() {if (this.totalPrice === 0) {return `¥${this.minPrice}元起送`; //这里使用的是es6中的反引号} else if (this.totalPrice < this.minPrice) {let diff = this.minPrice - this.totalPrice;return `还差¥${diff}元起送`;} else {return ‘去结算‘;                 //单引号,单引号和反引号不同}},payClass() {if (this.totalPrice < this.minPrice) {return ‘not-enough‘;} else {return ‘enough‘;}}

总结:通过以上学习我们能发现,selectFoods()的变化起着关键作用,它的变化会引起DOM的变化,并最终体现到界面上,而我们不用关注DOM内部的具体实现,这就是vue的一大好处。如果采用jQuery完成这些功能会略显繁杂。

8 cartcontrol组件,它是shopcart的子组件

可以给按钮增加padding,方便用户点击

this.foodScroll = new BScroll(this.$refs.foodWrapper, {probeType: 3,click: true});

click: true 是否派发click事件

通过import Vue from ‘vue‘;使用set接口,通过vue.set()添加属性,当它变化时就能被检测到

methods: {addCart(event) {if (!event._constructed) {// 去掉自带click事件的点击return;}if (!this.food.count) {<font color="red"> Vue.set(this.food, ‘count‘, 1);</font>} else {this.food.count++;}
//        event.srcElement.outerHTMLthis.$emit(‘increment‘, event.target); // 子组件通过 $emit触发父组件的方法 increment   还},decreaseCart(event) {if (!event._constructed) {// 去掉自带click事件的点击return;}this.food.count--;}}};

9 为减号按钮添加平移、滚动的动画

 <transition name="fade">   //减号和数字平移动画<div class="cart-decrease" v-show="food.count>0" @click.stop.prevent="decreaseCart($event)"><transition name="inner">    //数字滚动动画<span class="inner iconfont icon-jian"></span></transition></div></transition>
&.fade-enter-active, &.fade-leave-active {transition: all 0.4s linear    <--过渡效果的 CSS 属性的名称、过渡效果需要多少时间、速度效果的速度曲线-->}&.fade-enter, &.fade-leave-active {opacity: 0transform translate3d(24px, 0, 0) //这样可以开启硬件加速,动画更流畅,3D旋转,X轴位移24px}.innerdisplay inline-block <--设置成inline-block才有高度,才能有动画-->line-height 24pxfont-size 24pxvertical-align topcolor rgb(0, 160, 220, 0.2)&.inner-enter-active, &.inner-leave-active {transition: all 0.4s lineartransform: rotate(0)}&.inner-enter, &.inner-leave-active {opacity: 0transform  rotate(180deg)}

10 购物小球(抛物线小球)

滚动小球的实现,只需要考虑enter效果即可,用emit和on派发和监听事件,cartcontrol.vue派发事件{this.$emit('cart-add', event.target)};,goods.vue监听事件cart-add,并添加监听函数cartAdd<cartcontrol v-on:cart-add="cartAdd" :food="food"></cartcontrol>,在监听函数cartAdd中拿到shopcart的DOM对象 this.$refs.shopcart.drop(target);,返回shopcart.vue编写drop()获取下落小球的初始位置,并实现beforeEnter,enter和afterEnter方法,设置动画。

  • 在shopcart中定义小球,ball-container中存放小球,小球的状态存放在一个数组中,初始状态都是隐藏的
data() {return {balls: [{ //每一个成员都用来维护当前小球的状态,初始状态都是隐藏的show: false},{ show: false},{  show: false},{  show: false},{  show: false}],//添加一个变量,用来存贮已经下落的小球dropBalls: [],fold: true //购物车详情列表默认折叠};}
<div class="ball-container"><div v-for="ball in balls" :key="ball.id"><transition name="drop" @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter"><div v-show="ball.show" class="ball"><div class="inner inner-hook"> </div></div></transition></div>
</div>
  • 为小球添加样式,ball位于购物车图片的上方.ball position:fix z-index:200并设置缓动函数: transition 。
    设置inner,inner代表内层的一个小球,并设置缓动函数
  • 此处没有设置enter和leave的动画,是因为要动态计算cartcontrol中加号的位置(即起始点宽高的位置,left或者是top的值),首先要拿到cartcontrol中加号这个元素。因为在cartcontrol点击加号会出发事件,我们可以在cartcontral中添加一个派发事件,将它的DOM对象传出来,即在点击事件中添加分发事件addCart(event) {this.$emit('cart-add', event.target)};
methods: {addCart(event) { //解决PC端双点击的问题if (!event._constructed) { //浏览器直接return掉,去掉自带click事件的点击return;}//console.log('click');//点击不生效,不要忘了在foodScroll中添加click: true if (!this.food.count) {//food.count是原json中不存在的属性,不能直接添加//this.food.count = 1;Vue.set(this.food, 'count', 1);//给this.food增加一个count属性,并初始化为1} else {this.food.count++;}
//设置滚动对象时,点击加号,设置一个派发事件,将DOM对象传出去,将target(DOM)作为cart.add事件的对象传入
//$emit, $on, $off 分别来分发、监听、取消监听事件:this.$emit('cart-add', event.target);},decreaseCart(event) {//解决PC端双点击的问题if (!event._constructed) { //浏览器直接return掉,去掉自带click事件的点击return;}if (this.food.count) {this.food.count--;}}}
};
  • 之后在父组件goods中对cart-add进行监听并添加处理事件cartAdd(传入target),<cartcontrol v-on:cart-add="cartAdd" :food="food"></cartcontrol>,cartAdd函数添加在methods中
 <div class="cartcontrol-wrapper"><cartcontrol v-on:cart-add="cartAdd" :food="food"></cartcontrol> <!-- 传入food!!!--></div>
cartAdd(target) {//拿到traget(DOM对象)之后,将其传入shopcart组件中drop(target){}方法,//此处用this.$refs调用子组件,访问DOM时用的是ref="menuWrapper"this.$nextTick(() => { //回调函数异步执行,两个动画效果就不会卡顿了this.$refs.shopcart.drop(target);});}

goods父组件访问子组件shopcart的方法,不要忘了添加ref

<shopcart ref="shopcart" :select-foods="selectFoods" :delivery-price="seller.deliveryPrice" :min-price="seller.minPrice"></shopcart>
  • 此处回到shopcart.vue编写drop(el){}方法,drop方法对应name=”drop”的transition,并实现1)中的beforeEnter,enter和afterEnter方法,并在css中添加transition
data() {return {//添加一个变量,用来存贮已经下落的小球dropBalls: [],fold: true //购物车详情列表默认折叠};
}
methods: {drop(el) {//console.log(el); //验证是否能正确输出//遍历balls,拿到第一个show为false的球,做一个动画for (let i = 0; i < this.balls.length; i++) {let ball = this.balls[i];if (!ball.show) { //show为false的球ball.show = true; //小球下落ball.el = el;//保留当前的DOM对象,用来计算位置this.dropBalls.push(ball); //dropBalls存的是已经下落的小球,后续要对已经下落的小球进行处理return;}}},
//定义三个钩子函数实现动画beforeEnter(el) { //el为当前执行transition动画的DOM对象//先找到所有为true的小球(连续点击的情况)let count = this.balls.length;while (count--) {let ball = this.balls[count];if (ball.show) { //这个是要运动的小球truelet rect = ball.el.getBoundingClientRect();//获得元素相当于视口的位置let x = rect.left - 32;    //相对位置let y = -(window.innerHeight - rect.top - 22);el.style.display = ''; //v-show默认display:none,设置为空,让它显示//外层元素是纵向的动画,内层元素是横向的动画el.style.webkitTransform = `translate3d(0,${y}px,0)`;el.style.transform = `translate3d(0,${y}px,0)`;let inner = el.getElementsByClassName('inner-hook')[0];inner.style.webkitTransform = `translate3d(${x}px, 0, 0)`;inner.style.transform = `translate3d(${x}px, 0, 0)`;}}},           enter(el) {/* 触发浏览器重绘,重绘之后才可以设置transform*//* eslint-disable no-unused-vars */   //必须添加声明 否则会报错let rf = el.offsetHeight;this.$nextTick(() => { //样式重置el.style.webKitTransform = 'translate3d(0,0,0)';//没有变量时只能用单引,不能用反引el.style.transform = 'translate3d(0,0,0)';let inner = el.getElementsByClassName('inner-hook')[0];inner.style.webkitTransform = 'translate3d(0,0,0)';inner.style.transform = 'translate3d(0,0,0)';});
},afterEnter(el) { //动画完成let ball = this.dropBalls.shift();//删除并返回第一个ballif (ball) {ball.show = false; //重置ball.show的状态el.style.display = 'none';}},}

CSS:在运动的时候拉一个贝塞尔曲线,更加贴合实际效果

.ball-container.ballposition: fixed //相对于视口做布局left: 32pxbottom: 22pxz-index: 200transition: all 0.6s cubic-bezier(0.49, -0.29, 0.75, 0.41)   //贝塞尔曲线.innerwidth:16pxheight: 16pxborder-radius: 50%background: rgb(0,160,220)transition all: 0.4s linear  //x轴做一个线性的过渡即可

11 购物车详情页面的实现
在购物车中有商品时,点击购物车会出现购物车详情,会有一个购物车列表,商品右侧有加减号组件,右上方有清空组件,购物车详情页有固定高度,超过固定高度时就会滚动,不满足固定高度时,只能被自己的高度撑开

首先,在shopcart.vue中添加购物车详情页的DOM结构,v-show控制购物车的展示和收起状态,listShow默认为false,购物车主要分为两块,list-header(购物车标题+清空字块)和购物车商品的详情列表list-content,遍历的是selectFoods,li分为左右两侧,左侧为商品名称和价格,右侧为加减号组件。

在shopcart中添加实现样式

<transition name="fade"><div class="shopcart-list" v-show="listShow"><div class="list-header"><h1 class="title">购物车</h1><span class="empty" @click="empty">清空</span></div><div class="list-content" ref="listContent"><ul><li class="food" v-for="food in selectFoods" :key="food.id"><span class="name">{{food.name}}</span><div class="price"><span>¥{{food.price * food.count}}</span></div><div class="cartcontrol-wrapper"><!-- 记得将cartcontrol组件import到shopcart中,并注册components--><cartcontrol :food = "food"></cartcontrol></div></li></ul></div></div>
</transition>
  • cartcontrol组件引用 import 引入,在components中注册,就可以使用,在shopcart-list中设置了v-show=”listShow”,v-show默认display:none,所以此时看不到购物车列表的变化,可以在点击cartcontrol组件的加减号时观察动态HTML的变化以确认是否实现li列表的呈现

  • <div class="shopcart-list"v-show="listShow"> 计算属性listShow,取决于totalCount或者是totalPrice是否大于0

定义变量fold:true来确定详情列表是展开还是折叠的状态,默认为折叠状态

data() {return {//添加一个变量,用来存贮已经下落的小球dropBalls: [],fold: true //定义收起和展开状态,购物车详情列表默认折叠};}
     listShow() {// 没有商品时为折叠状态if (!this.totalCount) {this.fold = true;// true时为折叠状态return false; //不做切换}// 有商品的时候以变量show做状态切换let show = !this.fold; // fold为true则show为false,fold为false,则show为truereturn show;}}
  • 然后给contentbang绑定一个详情界面:点击cartcontrol(页面下方购物车)就可以来回切换详情表的展开和折叠
 <div class="content" @click="toggleList"> <!--  详情界面-->toggleList() {if (!this.totalCount) { //购物车没有商品的时候不可点击 return;}this.fold = !this.fold; //当前是收起状态就展开,展开状态就收起}
  • 编写购物车详情列表的样式,以便查看效果
.shopcart-listposition absolutetop 0left 0z-index -1width 100%transform translate3d(0, -100%, 0) //整个列表相对于当前自身的高度做一个偏移&.fade-enter-active, &.fade-leave-active transition: all 0.5s linear transform translate3d(0, -100%, 0) //每个表项相对于当前自身的高度做一个偏移&.fade-enter, &.fade-leave-activetransform translate3d(0, 0, 0).list-headerheight 40pxline-height 40pxpadding 0 18pxbackground #f3f5f7border-bottom 1px solid rgba(7, 17, 27, 0.1).titlefloat leftfont-size 14pxcolor rgb(7,17,27).emptyfloat rightfont-size 12pxcolor rgb(0,160,220).list-contentpadding 0 18pxmax-height 217pxoverflow hiddenbackground  #ffffff.foodposition relativepadding 12px 0box-sizing border-boxborder-1px(rgba(7,17,27,0.1)).nameline-height 24pxfont-size 14pxcolor rgb(7,17,27).price position absoluteright 90pxbottom 12pxline-height 24pxfont-size 14pxfont-weight 700color rgb(240, 20, 20).cartcontrol-wrapperposition absoluteright 0bottom 6px

@toggleList定义在购物车组件中,点击购物车,通过改变fold的true和false状态,控制购物车详情界面的展开或者折叠;listShow将fold的状态传回给shoplist的v-show,通过v-show来决定购物车详情的展开或折叠,同时listShow还设置没有商品时是不可展开的( this.fold = true)。

  • -

列表生成,还有几个问题没有解决,首先,购物车详情列表和主页面之间有一个半透明的背景色没有实现,还有就是清空按钮没有实现,加减号组件没有实现点击。

  • 首先看加减号不能点击的原因,我们是在betterScroll派发一个事件的时候进行的点击,所以需要betterScroll跟购物车列表相关联,当视口超过固定宽度时进行滚动

首先,引入betterScroll,

import BScroll from 'better-scroll';

并在listShow中进行初始化,之后在列表展示的时候才需要给列表做初始化

 listShow() {// 没有商品时为折叠状态if (!this.totalCount) {this.fold = true;// true时为折叠状态return false; //不做切换}// 有商品的时候以变量show做状态切换
// fold为true(折叠)则show为false(折叠),fold为false(展开),则show为true(展开);
// 这样,show就跟v-show的true和false状态同步了,变为true时展开,false时折叠let show = !this.fold; if (show) { // true为展示状态this.$nextTick(() => {if (!this.scroll) { // 没有scroll的时候才需要new,否则只需要刷新一下即可this.scroll = new BScroll(this.$refs.listContent, {click: true});} else {this.scroll.refresh();}});}return show;}
}

之后我们点击的时候,betterScroll就会自动派发一个事件,实现点击和动画

  • 实现click清空事件
     <div class="list-header"><h1 class="title">购物车</h1><span class="empty" @click="empty">清空</span></div>

将selectFoods中的food.count设为0即可

     empty() {this.selectFoods.forEach((food) => { //遍历food,将food的count都置零food.count = 0;});}
  • 还要添加一个背景,半透明模糊是相对于整个 屏幕 做定位的,所以要和shopCart 平级
    <transition name="fade"><!-- listShow表示当list详情列表显示的时候mask才显示 --><div class="list-mask" v-show="listShow" @click="hideList()"></div></transition>

写样式:相对于窗口固定布局,宽高都是100%,设定z-index要小于shopcart的z-index,之后添加缓动

 .list-maskposition fixed top 0left 0width 100%height 100%z-index 40 //z-index要小于shopcart的indexbackdrop-filter blur(10px) // 模糊效果-webkit-backdrop-filter blur(10px)opacity 1background rgba(7, 17, 27, 0.6)&.fade-enter-active, &.fade-leave-active  opacity 1transition: all 0.5s //设置缓动效果background rgba(7, 17, 27, 0.6)&.fade-enter, &.fade-leave-active opacity 0background rgba(7, 17, 27, 0)

点击背景的时候也可以收起列表,添加hideList()方法

 hideList() { this.fold = true; //点击mark层,购物车详情列表被收回}
  • 做点击结算:click pay函数
<!-- 点击去结算,结算过后因为事件冒泡的原因(pay按钮是content详情界面的子节点),详情列表会被展开,用stop.prevent阻止事件冒泡-->
<div class="content-right" @click.stop.prevent="pay"><div class="pay" :class="payClass"> <!-- 在这里做一个状态的判断-->{{payDesc}}</div>
</div>pay() { //点击去结算if (this.totalPrice < this.minPrice) {return;}window.alert(`支付¥${this.totalPrice}元`);//window.alert('支付' + this.totalPrice + '元');
}

点击结算按钮,购物车详情页被展开是因为事件的冒泡缘故,所以要阻止冒泡—–content-right冒泡到content上的缘故,导致content出现了切换购物车详情页的情况

 <div class="content" @click="toggleList"><div class="content-right" @click.stop.prevent="pay">

项目:Vue.js高仿饿了吗外卖APP(二)相关推荐

  1. 项目:Vue.js高仿饿了吗外卖APP(一)

    Vue.js高仿饿了吗外卖APP核心知识 使用Vue.js作为项目的技术栈!这是目前最火的MVVM框架(之一),轻量.简洁.高效.数据驱动.组件化的优点,被大家称为"简单却不失优雅,小巧而不 ...

  2. Vue.js高仿饿了么外卖App学习记录

    (给达达前端加星标,提升前端技能) 开发一款vue.js开发一款app,使用vue.js是一款高效的mvvm框架,它轻量,高效,组件化,数据驱动等功能便于开发.使用vue.js开发移动端app,学会使 ...

  3. Vue.js 高仿饿了么外卖APP

    第1章 课程简介 介绍课程的学习目标和学习内容. 1-1 课程简介 1-2 课程安排 第2章 Vuejs介绍 从前端开发趋势分析开始,引入 MVVM 开发框架和 Vue.js,接着对比流行框架Angu ...

  4. 【慕课网实战课程笔记】Vue.js高仿饿了么外卖App

    写在前面:该课程为慕课网付费课程,笔记内容代码居多.内容简略,仅供自己日后翻阅.如有疑问或者不妥,欢迎提出指正,我看到了会回复,谢谢! 第1章:课程简介 第2章:Vuejs介绍 Ctrl+Alt+l ...

  5. vue结合饿了么_Vue.js 高仿饿了么外卖app 全套_IT教程网

    资源名称:Vue.js  高仿饿了么外卖app  全套 资源目录: vue仿饿了么视频全套 全套 资源 │ files.txt │ project.zip │ resource.zip │ ├─第01 ...

  6. vue.js高仿饿了吗实现tips

    @[TOC]vue.js高仿饿了吗实现tips 高仿饿了吗–tip1 动态评星 目标:根据商家的星级生成指定的五行样式 注意点 无论星级多少,星星的个数都是五颗,所以利用v-for循环生成 利用内联标 ...

  7. vue + vue-router + vue-resource + es6 + stylus + webpack 高仿饿了么外卖App商家详情

    VUE高仿饿了么app 本项目github地址:https://github.com/motysla/eleme.git VUE 搭建简介 刚学习了VUE高仿饿了么app课,记录课的要点,巩固知识. ...

  8. 【笔记-vue】《imooc-vue.js高仿饿了么》、《imooc-vue 音乐app》、《imooc-vue.js源码全方位解析》

    20170709 - 20171128:<imooc-vue.js高仿饿了么> 一.第一章 课程简介 1-1课程简介 1.需求分析-脚手架工具-数据mock-架构设计-代码编写-自测-编译 ...

  9. 基于SpringBoot的仿饿了吗外卖APP设计与实现

    一.需求 本App主要实现了用户的登录,商品的浏览,购物车查询等功能,如下表所示 二.主体框架 2.1 整体框架 2.2 数据的流向 数据类型 数据流向 交易商品信息 数据库->客户 商品类别信 ...

最新文章

  1. 寒假作业--微信小程序开发1
  2. mysql 获取倒数第二_如何从MySQL中的表中获取倒数第二条记录?
  3. Redis中的Sentinel故障转移
  4. 手持终端可以根据行业的功能要求进行定制
  5. pyspark的rdd直接写入mysql
  6. java 双因素认证(2FA)TOTP demo
  7. 使用禅道Docker安装包安装
  8. python 归纳 (二五)_多进程数据共享和同步_信号量Semaphore
  9. oc基础-OC中对象方法的使用
  10. centos6.0的gnome桌面的一个大bug
  11. 一句话可以改变人的一生
  12. 科罗拉多州立大学计算机科学,科罗拉多州立
  13. 高质量病毒——暴风一号(BoyFine)代码.vbs
  14. EXCEL数据格式,字符型空值““参与计算、数值为0时单元格显示为空(解决了无法使用value()函数将字符型空值““转换为数字型的问题)
  15. [音乐推荐]水木年华 - 借我一生
  16. mysql new 与old_mysql触发器new和old区别 阿星小栈
  17. gson的解析demo JAVA
  18. 哲理小故事---理想和现实
  19. Windows电脑加速小技巧(VIP典藏版)
  20. navigation_plugin

热门文章

  1. 2020-07-03:简单的图书管理系统(Python、SQL Server)
  2. 如何用 GPU 硬件层加速优化 Android 系统的游戏流畅度
  3. CORS跨域与@crossorigin
  4. 大学c语言程序设计期末考试试卷,大学大一C语言程序设计期末考试试卷及答案...
  5. Anaconda D2L 虚拟环境安装配置
  6. SAP从入门到放弃系列之MRP区域
  7. 佳的美5820液晶电视盒使用体验
  8. 小米上市周年纪:股价暴跌43%,市值蒸发3000亿
  9. GBK、GB2312、iso-8859-1之间的区别
  10. 5G时代将让你的生活更美好