项目总结:vue.js2.5饿了么APP(4)主要组件实现 - 购物车相关组件(下)
说明:本总结来源于慕课网 @ustbhuangyi老师的课程《Vue.js2.5+cube-ui重构饿了么App》课程,本博客做了项目总结梳理便于回顾,需要学习的伙伴可以移步学习。与君共勉!
之前章节传送:
项目总结:vue.js2.5饿了么APP(1)概述+项目准备
项目总结:vue.js2.5饿了么APP(2)主要组件实现 - 头部相关组件
项目总结:vue.js2.5饿了么APP(3)主要组件实现 - 购物车相关组件(上)
购物车组件主要包含(shop-cart ,shop-control , shop-cart-list , shop-cart-sticky)4个部分,本节主要讲解后两个,以及一些购物车相关优化设计 。
速看
shop-cart-list组件+shop-cart-sticky组件 当购物车中有商品时,点击购物车会弹出购物车详细内容,列表限制高度并可以滚动。(起初一期时没有将这一部分抽离出来,因此就在shop-cart组件的后半部分,通过一个标记来控制区块显示)二期,对于这种弹层类组件选择使用cube-ui的<popup>组件实现,并将其设置为API调用,设置hide() show()方法来控制蒙层显示。
但是有个问题:shop-cart-list是API组件,会动态的向body中挂载结点,因此层级较高,高过内层组件层级。但是购物车组件是一个子组件,因此会遮盖到原来的购物车组件(这个组件有个向上突出的部分)。由于无法调整层级,解决方法就是:使用shop-cart-sticky组件。动态向body中挂载一个购物车组件的副本。
并且这一部分还要加入的功能有:(加入购物车的小球动画,结算,清空购物车)对于小球下落动画,可以调用cart-control的drop方法,两个弹出dialog的操作都使用了cube-ui中的dialog组件。而对于切换tab的购物车联动问题,只需要在请求数据之前判断是否已经拿到数据。
最后,对于header和shop-cart-list的弹层组件中都用到的hide() show() 方法用mixin抽离出来做代码简化。
目录
一、购物车详情shop-cart-list组件(二期)
1. 概述
2. 布局
3. 实现
(1)popup组件使用
(2)过渡动画
(3)列表滚动
(4)组件的使用
(5)添加弹出触发方法
(6)存在的问题
(7)商品购买时小球飞入动画
(8)清空购物车
(9)结算按钮
(10)公共部分mixin抽离
(11)滑动页面购物车关联
二、购物车详情shopcart-list区块(一期)
1. 概述
2. 布局
3. 实现
(1)实现组件显示隐藏
(2)实现动画
(3)蒙层的实现
三、shop-cart-sticky组件
1. 概括
2. 布局
3. 实现
四、createAPI详解
一、购物车详情shop-cart-list组件(二期)
1. 概述
当购物车中有商品时,点击购物车会弹出购物车详细内容,列表限制高度并可以滚动。(起初一期时没有将这一部分抽离出来,因此就在shop-cart组件的后半部分,通过一个标记来控制区块显示)二期,对于这种弹层类组件选择使用cube-ui的<popup>组件实现,并将其设置为API调用,设置hide() show()方法来控制蒙层显示。但是有个问题:shop-cart-list是API组件,会动态的向body中挂载结点,因此层级较高,高过内层组件层级。但是购物车组件是一个子组件,因此会遮盖到原来的购物车组件(这个组件有个向上突出的部分)。由于无法调整层级,解决方法就是:使用shop-cart-sticky组件。动态向body中挂载一个购物车组件的副本。
并且这一部分还要加入的功能有:(加入购物车的小球动画,结算,清空购物车)对于小球下落动画,可以调用cart-control的drop方法,两个弹出dialog的操作都使用了cube-ui中的dialog组件。而对于切换tab的购物车联动问题,只需要在请求数据之前判断是否已经拿到数据。
最后,对于header和shop-cart-list的弹层组件中都用到的hide() show() 方法用mixin抽离出来做代码简化。
2. 布局
当购物车中有商品时,点击购物车会弹出购物车详细内容。
布局:顶部是一个标题区+列表(有一个最大高度,超过最大高度列表可以滚动,如果列表高度不满足最大高度,只能被列表自身的高度撑高)
<transition name="fade"><cube-popup><transition name="move" @after-leave="onLeave"><div v-show="visible"><div class="list-header"><cube-scroll class="list-content" ref="listContent"><ul><li class="food" v-for="food in selectFoods" :key="food.name"><span class="name"></span><div class="price"></div><div class="cart-control-wrapper"><cart-control @add="onAdd" :food="food"></cart-control></div></li></ul></cube-scroll></div></transition></cube-popup></transition>
使用cube-scroll组件实现列表滚动,并且其中添加shop-control组件做商品的购买。
使用cube-ui将购物车组件变成一个createAPI模块的调用,并使用cube-popup弹层组件
3. 实现
(1)popup组件使用
<cube-popup>组件是所有弹层组件的基础组件. position是弹窗出现的置,:mask-closable=true点击蒙层会派发click=maskclick事件,而达到关闭的效果,z-index弹窗高这里的type类似于class,可以改变样式(设置bottom样式达到我们的效果),并通过v-show控制弹层显隐,以及驱动过渡动画<transition>。
<cube-popupv-show="visible":mask-closable=true:z-index=90position="bottom"type="shop-cart-list"@mask-click="maskClick">
</cube-popup>
(2)过渡动画
.cube-shop-cart-listbottom: 48px&.fade-enter, &.fade-leave-activeopacity: 0&.fade-enter-active, &.fade-leave-activetransition: all 0.3s ease-in-out.move-enter, .move-leave-activetransform: translate3d(0, 100%, 0).move-enter-active, .move-leave-activetransition: all 0.3 ease-in-out
(3)列表滚动
使用cube-scroll组件实现列表滚动,并且其中添加shop-control组件做商品的购买。
Data中添加visiable控制显示。提供两个方法show() hide()修改visiablemaskClick()方法控制其蒙层隐藏
(4)组件的使用
定义props有select Foods,从而使购物车中选择的商品通过props传递到shop-cart-list组件,
组件使用:将其变成API组件。 在register.js中修改,之后就可以通过API的方式调用。
import ShopCartList from 'components/shop-cart-list/shop-cart-list'
createAPI(Vue, ShopCartList)
(5)添加弹出触发方法
当我们点击底部购物车时会显示这个组件。在shop-cart的content中添加一个点击事件toggleList,并添加该方法。
(添加辅助变量listfold默认为收起状态)在函数中,只有是收起状态才会展开,并且判断商品件数是否为0,不为零显示lsit(_showShopCartList),为零隐藏list(_hidwShopCartList)
toggleList() {if (this.listFold) {if (!this.totalCount) {return}this.listFold = falsethis._showShopCartList()this._showShopCartSticky()} else {this.listFold = truethis._hideShopCartList()}},
并且实现这两个私有方法,使用api调用组件(由于每次都是单例,因此做缓存)
_showShopCartList() {this.shopCartListComp = this.shopCartListComp || this.$createShopCartList({$props: {selectFoods: 'selectFoods'},$events: {hide: () => {this.listFold = true},leave: () => {this._hideShopCartSticky()},add: (el) => {this.shopCartStickyComp.drop(el)}}})this.shopCartListComp.show()},_hideShopCartList() {const comp = this.sticky ? this.$parent.list : this.shopCartListCompcomp.hide && comp.hide()},
(6)存在的问题
但是有个问题就是,shop-cart-list是API组件,会动态的向body中挂载结点,因此层级较高,高过内层组件层级。但是购物车组件是一个子组件,因此会遮盖到原来的购物车组件。但是无法调整层级,
因此解决方法就是:使用shop-cart-sticky组件。动态向body中挂载一个购物车组件的副本。 shop-cart-sticky组件。
(7)商品购买时小球飞入动画
购物车小球,在shop-cat-list的cart-control点击需要向其父组件shop-cart组件派发onAdd()方法
<div class="cart-control-wrapper"><cart-control @add="onAdd" :food="food"></cart-control>
</div>onAdd(target) {this.$emit(EVENT_ADD, target)},
在shop-cart组件中监听该事件,在add中调用shop-cart-sticky组件的drop()方法,(其中需要在shop-cart-sticky中添加drop方法,并调用shop-cart的drop方法。)
_showShopCartList() {this.shopCartListComp = this.shopCartListComp || this.$createShopCartList({$props: {selectFoods: 'selectFoods'},$events: {hide: () => {this.listFold = true},leave: () => {this._hideShopCartSticky()},add: (el) => {this.shopCartStickyComp.drop(el)}}})this.shopCartListComp.show()},
(8)清空购物车
点击清空按钮,添加click事件empty(), 调用cube-ui的dialog,遍历food将所有的count设置为0
empty() {this.$createDialog({type: 'confirm',content: '确认清空购物车吗?',$events: {confirm: () => {this.selectFoods.forEach((food) => {food.count = 0})this.hide()}}}).show()}
}
当商品数量为0时,也要收回list,因此在shop-cart组件中添加watch,对于totalcount,当展开情况,并且值为0,将其关闭。
watch: {fold(newVal) {this.listFold = newVal},totalCount(newVal) {if (!this.listFold && !newVal) {this._hideShopCartList()}}},
(9)结算按钮
对于去结算按钮,添加点击事件pay(),使用cube-ui提供的dialog,当价格大于起送价,计算价格并显示
pay(e) {if (this.totalPrice < this.minPrice) {return}this.$createDialog({title: '支付',content: `您需要支付${this.totalPrice}元`}).show()e.stopPropagation()},
(10)公共部分mixin抽离
所有我们使用的弹层组件都包含了show() hide() 主要用途是修改visible的true false,因此可以抽象出这部分代码,在common中添加mixins文件夹popup.js,在shop-cart-list等中添加引用mixin:[popupMixin]
const EVENT_SHOW = 'show'
const EVENT_HIDE = 'hide'export default {data() {return {visible: false}},methods: {show() {this.visible = truethis.$emit(EVENT_SHOW)},hide() {this.visible = falsethis.$emit(EVENT_HIDE)}}
}
(11)滑动页面购物车关联
对于滑动页面也可以实现购物车的联动问题:在tab组件中我们定义了一个onChange()方法
onChange(current) {this.index = currentconst component = this.$refs.component[current]component.fetch && component.fetch()},
其中会执行组件的fetch方法,在goods组件中定义了这样一个fetch方法,每次都会getGoods,因此添加一个标记,只有当没有定义过时才会getGoods,如果已经获取过一次时就不用再次获取了。
fetch() {if (!this.fetched) {this.fetched = truegetGoods().then((goods) => {this.goods = goods})}},
二、购物车详情shopcart-list区块(一期)
1. 概述
一期实现没有很复杂的部分就是需要添加计算属性listShow,判断totalCount没有商品时将fold = true,否则为true。点击触发togglelist方法控制该部分显示。
2. 布局
组件部分没有抽离出来,而是直接在shop-cart组件中写入,放在整个组件的最下部。
<div class="shopcart-list" v-show="listShow" transition="fold"><div class="list-header"><h1 class="title">购物车</h1><span class="empty" @click="empty">清空</span></div><div class="list-content" v-el:list-content><ul><li class="food" v-for="food in selectFoods"><span class="name">{{food.name}}</span><div class="price"><span>¥{{food.price*food.count}}</span></div><div class="cartcontrol-wrapper"><cartcontrol :food="food"></cartcontrol></div></li></ul></div></div>
3. 实现
(1)实现组件显示隐藏
添加一个fold默认值为true,添加计算属性listShow。判断this.totalCount没有商品fold = true,否则为true。
listShow() {if (!this.totalCount) {this.fold = true;return false;}let show = !this.fold;if (show) {this.$nextTick(() => {if (!this.scroll) {this.scroll = new BScroll(this.$els.listContent, {click: true});} else {this.scroll.refresh();}});}return show;}},
在点击content时触发事件togglelist,并实现方法,当点击list-mask可以收回shop-cart,添加事件listShow事件
toggleList() {if (!this.totalCount) {return;}this.fold = !this.fold;},
(2)实现动画
动画:向上滑动,添加transition=fold,此处点击事件是better-scroll组件派发的事件。
&.fold-transitiontransition: all 0.5stransform: translate3d(0, -100%, 0)&.fold-enter, &.fold-leavetransform: translate3d(0, 0, 0)
(3)蒙层的实现
该组件出现时背后是一个蒙层,因此在shop-cart组件同级下定义list-mask
<div class="list-mask" @click="hideList" v-show="listShow" transition="fade"></div>
并添加渐变效果和样式。模糊效果使用 backdrop-filter: blur(10px)
.list-maskposition: fixedtop: 0left: 0width: 100%height: 100%z-index: 40backdrop-filter: blur(10px)&.fade-transitiontransition: all 0.5sopacity: 1background: rgba(7, 17, 27, 0.6)&.fade-enter, &.fade-leaveopacity: 0background: rgba(7, 17, 27, 0)
三、shop-cart-sticky组件
1. 概括
shop-cart-list是API组件,会动态的向body中挂载结点,因此层级较高,高过内层组件层级。但是购物车组件是一个子组件,因此会遮盖到原来的购物车组件。但是无法调整层级,因此解决方法就是:使用shop-cart-sticky组件。动态向body中挂载一个购物车组件的副本。而Sticky组件就是对chop-cart组件的简单包装。
2. 布局
Sticky组件就是对chop-cart组件的包装,把它需要的数据通过props传入,因此可以把sticky组件作为API调用就可以了。并且也包含hide() show()函数控制visible显隐。
<div class="shop-cart-sticky" v-show="visible"><shop-cartref="shopCart":selectFoods="selectFoods":deliveryPrice="deliveryPrice":minPrice="minPrice":fold="fold":sticky=true></shop-cart></div>
3. 实现
sticky组件要可以跟着页面的切换而保存,因此调用要添加在shop-cart组件的toggleList函数中(如上代码)并实现该私有函数,并接收props
_showShopCartSticky() {this.shopCartStickyComp = this.shopCartStickyComp || this.$createShopCartSticky({$props: {selectFoods: 'selectFoods',deliveryPrice: 'deliveryPrice',minPrice: 'minPrice',fold: 'listFold',list: this.shopCartListComp}})this.shopCartStickyComp.show()},
_hideShopCartSticky() {this.shopCartStickyComp.hide()}
四、createAPI详解
仓库地址:https://github.com/cube-ui/vue-create-api
执行create-api会向vue原型上挂载$createX的方法(如:name:'head-detail' 就会变成$createHeadDetail);
在header组件实例中调用this.createheadDetail而将header看作为其父组件
它的结果是一个组件实例apiComponent,因此就可以调用组件的方法
showDetail() {this.headerDetailComp = this.headerDetailComp || this.$createHeaderDetail({$props: {seller: 'seller'}})this.headerDetailComp.show() // 调用组件的show方法}
在调用vue.prototype.$createX会做什么事情?
像vue组件生命周期一样,它也有创建,更新和销毁过程。
创建过程:根据传入的参数做一些处理,如processProps。之后就会新建一个vue实例,它的child就是实例组件。在执行vue实例初始化的过程中首先执行init()方法(append to body将组件的DOM添加到body下,这也是它可以动态挂载到body的原因)
更新过程:(如props数据更新)组件会重新渲染,一般使用的组件来说props就是响应式的,一旦改变就会触发组件重新渲染。但是create-api组件会对更新的props进行watch(调用方watch传入的props)当调用方数据发生变化,就会执行回调函数(触发vue的forceupdate,从而使api组件重新渲染)
销毁过程:当调用方销毁,api组件会做相应处理:监听before Destroy钩子函数,当我们api组件的父实例销毁,那么apiComponent 会执行remove方法(清理并执行destroy方法,从而把DOM从body上移除)
整个create-api模块的设计也使用了vue的钩子函数实例方法完成api组件的生命周期
项目总结:vue.js2.5饿了么APP(5)主要组件实现 - 商品详情页部分
项目总结:vue.js2.5饿了么APP(6)主要组件实现 - 评价页+商家页部分
项目总结:vue.js2.5饿了么APP(7)项目部署与总结
项目总结:vue.js2.5饿了么APP(4)主要组件实现 - 购物车相关组件(下)相关推荐
- 项目总结:vue.js2.5饿了么APP(1)概述+项目准备
说明:本总结来源于慕课网 @ustbhuangyi老师的课程<Vue.js2.5+cube-ui重构饿了么App>课程,本博客做了项目总结梳理便于回顾,需要学习的伙伴可以移步学习.与君共勉 ...
- 项目总结:vue.js2.5饿了么APP(5)主要组件实现 - 商品详情页部分
说明:本总结来源于慕课网 @ustbhuangyi老师的课程<Vue.js2.5+cube-ui重构饿了么App>课程,本博客做了项目总结梳理便于回顾,需要学习的伙伴可以移步学习.与君共勉 ...
- 项目总结:vue.js2.5饿了么APP(7)项目部署与总结
说明:本总结来源于慕课网 @ustbhuangyi老师的课程<Vue.js2.5+cube-ui重构饿了么App>课程,本博客做了项目总结梳理便于回顾,需要学习的伙伴可以移步学习.与君共勉 ...
- 项目总结:vue.js2.5饿了么APP(3)主要组件实现 - 购物车相关组件(上)
说明:本总结来源于慕课网 @ustbhuangyi老师的课程<Vue.js2.5+cube-ui重构饿了么App>课程,本博客做了项目总结梳理便于回顾,需要学习的伙伴可以移步学习.与君共勉 ...
- 【Vue项目实战】vue.js2.5 饿了么APP(1)概述+项目准备
一.概述 1. 项目简介 使用vue.js vue是当前最火的MVVM框架,(优点:轻量.简洁.高效.数据驱动.组件化) 本项目做的是:高仿上线外卖APP商家模块 开发过程:需求分析-脚手架工具-数据 ...
- vue高仿饿了么APP(二)
这里我直接跳过vue-cli的安装. 一,vue.js代码是如何运行的? 1,进入页面,首先加载index.html和main.js文件. ① index.html文件 <!DOCTYPE ht ...
- vue高仿饿了么APP(三)
一·需求分析 二,制作css字体图标的制作和使用 前面已经有人做过总结,我就直接引用了 css字体图标的制作和使用. 三,项目目录结构设计 1,每一个组件都单独建立一个文件夹,例如商品页建立goods ...
- VUE高仿饿了么app开发思维导图
来自互联网 文章来源:刘俊涛的博客 地址:http://www.cnblogs.com/lovebing
- vue外卖十九:商家详情-底部购物车组件,购物车相关vuex状态设计、相关计算、清空购物车+滚动购物车
一.购物车基础 1)购物车状态设计cartFoods+mutation store/state.js // 所有要管理的状态数据:从页面需求分析出来,最好和api/index.js里的命名相同 exp ...
最新文章
- runtime系统的Cello
- 《CDN 之我见》系列二:原理篇(缓存、安全)
- 2016_6_27日报
- mysql命令导入存储过程报错_mysql导入存储过程时declare报错的有关问题解决
- Python学习笔记:Day 16 编写移动App
- Html.ActionLink
- python中threading产生死锁_什么是死锁,如何避免死锁(4种方法)
- PPPOE拨号上网流程及密码窃取具体实现
- HTML5 文本元素
- 面向站长和网站管理员的Web缓存加速指南[翻译]
- 烟台市建筑物矢量数据(Shp格式+带高度)
- MATLAB电路仿真搭建教程
- 线性代数02 线性方程组的解的情况(矩阵的秩)
- matlab贝塔分布,怎么拟合贝塔分布函数
- office2019word2019excel2019ppt2019关闭自动更新设置步骤
- LaTex常用技巧6:矩阵编写总结
- 群晖显示服务器错误代码21,群晖 DSM 6.2.3 升级 25426 错误 21 的解决办法 | 智享阁...
- VMware Workstation Pro 转移服务器中的虚拟机
- 激光SLAM与视觉SLAM的区别
- 两个MATLAB在线工具,画图啥的都不用安装了
热门文章
- SpringBoot 整合模板引擎 Thymeleaf 页面跳转失败的解决方案
- 一个传统物流企业开发一款专属物流app需要多少成本?
- 文档级关系抽取:QIUXP:DORE: Document Ordered Relation Extraction based on Generative Framework
- Kicad 导出立创商城标准BOM格式插件---带立创商城元件库---预览(带下载链接)
- 三角函数---诱导公式
- mysql 5.7 utf8mb4_Mysql 5.7 设置默认urf8mb4
- 微机原理与接口技术课程设计——数字电压表的设计(含完整代码与实验连接图)
- DM 共享存储集群架构DSC讲解
- 从离线分析建模到稳健风控升级,为什么说顶象Dinsight实时风控引擎是对的选择?
- MATLAB坐标系变换动画gif(附代码):坐标系旋转动画+坐标系平移动画代码