vuejs2-5 goods页面
1 goods.vue组件功能(当未使用其他组件时)
1.1 src/App.vue 传递值
<keep-alive>
<router-view :seller="seller"></router-view>
</keep-alive>
1.2 src/components/goods.vue
<template>
<div>
<div class="goods">
<!--左侧分类-->
<div class="menu-wrapper" ref="menuWrapper">
<ul>
<li v-for="(item,index) in goods" class="menu-item"
:class="{'current':currentIndex===index}"
@click="slectMenu(index,$event)">
<span class="text border-1px">
<span class="icon" v-show="item.type>0"
:class="classMap[item.type]"></span>
{{item.name}}
</span>
</li>
</ul>
</div>
<!--右侧商品列表-->
<div class="foods-wrapper" ref="foodsWrapper">
<ul>
<li v-for="item in goods" class="foot-list food-list-hook" ref="foodList">
<h2 class="title">{{item.name}}</h2>
<ul>
<li v-for="food in item.foods" class="foods-item border-1px" @click="selectFood(food,$event)">
<div class="icon">
<img :src="food.icon" width="57" height="57">
</div>
<div class="content">
<h3 class="name">{{food.name}}</h3>
<p class="desc">{{food.description}}</p>
<div class="extra">
<span class="count">月售{{food.sellCount}}</span>
<span>好评率:{{food.rating}}%</span>
</div>
<div class="price">
<span class="now">¥{{food.price}}</span>
<span v-show="food.oldPrice" class="odd">¥{{food.oldPrice}}</span>
</div>
</div>
</li>
</ul>
</li>
</ul>
</div>
</div>
</div>
</template>
<script type="text/ecmascript-6">
import BScroll from 'better-scroll';
const ERR_OK = 0; // 验证后台数据是否可用
export default{
props: { // 用来接收其他组件的数据
seller: {
type: Object
}
},
data() { // 数据
return {
goods: [],
listHeight: [],
scrollY: 0,
selectedFood: {}
};
},
computed: { // 计算属性
currentIndex() { // 右侧内容区滚动时左侧对应添加样式
for (let i = 0; i < this.listHeight.length; i++) {
let height1 = this.listHeight[i];
let height2 = this.listHeight[i + 1];
if (!height2 || (this.scrollY >= height1 && this.scrollY < height2)) { // 滚动高度大于或等于当前i区块的高度 小于i+1区块的高度
return i;
};
};
return 0; // 刚加载进来默认左侧第一个分类添加样式
}
},
created() { // dom加载时的操作
this.classMap = ['decrease', 'discount', 'special', 'invoice', 'guarantee'];
// 请求获取goods的数据
this.$http.get('/api/goods')
.then((res) => {
res = res.body;
if (res.errno === ERR_OK) {
this.goods = res.data;
this.$nextTick(() => { // 保证dom渲染好后
this._initScroll();
this._calcullateHeight(); // 计算区间高度组成的数组
});
}
;
});
},
methods: { // 方法
_initScroll() {
this.menuScroll = new BScroll(this.$refs.menuWrapper, {
click: true // 可以点击
});
this.foodsScroll = new BScroll(this.$refs.foodsWrapper, {
probeType: 3, // scroll滚动时监听滚动位置
click: true
});
this.foodsScroll.on('scroll', (pos) => {
this.scrollY = Math.abs(Math.round(pos.y));
// console.log(this.scrollY);
});
},
_calcullateHeight() { // 计算右侧内容各自分区的高度 添加到this.listHeight数组中
// let foodList = this.$refs.foodsWrapper.getElementsByClassName('food-list-hook');
let foodList = this.$refs.foodList; // 获得右侧li的dom集合
let height = 0;
this.listHeight.push(height);
for (let i = 0; i < foodList.length; i++) {
let item = foodList[i];
height += item.clientHeight; // 每个区间累加后的高度
this.listHeight.push(height); // 区间高度放到数组里面
};
},
slectMenu(_index, ev) { // 点击左侧分类添加样式,右侧对应内容滚动到顶部
if (!ev._constructed) { // 使用了BS
return;
};
let foodList = this.$refs.foodList;
let els = foodList[_index];
this.foodsScroll.scrollToElement(els, 300);
}
}
};
</script>
<style lang="stylus" rel="stylesheet/stylus">
@import "../../common/stylus/mixin.styl"
.goods
$main_bg = #f3f5f7
$line_bg = #d9dde1
$bottom_bg = rgba(7,17,27,0.1)
display:flex
overflow:hidden
position:absolute
top:174px
bottom:46px
width:100%
.menu-wrapper
flex:0 0 80px
width:80px
background:$main_bg
.menu-item
display:table
height:54px
width:56px
line-height:14px
padding:0 12px
&.current
position:relative
z-index:10
margin-top: -1px
background:#fff
&:before
content:''
display:block
width:4px
height:100%
position:absolute
top:0
left:0
background-color:#00A0DC
.text
border-none()
font-weight:700
.text
display:table-cell
width:56px
vertical-align:middle
font-size:12px
border-1px($bottom_bg)
.icon
display:inline-block
width:12px
height:12px
margin-right:2px
background-size:12px
background-repeat:no-repeat
&.decrease
bg-img("decrease_3")
&.discount
bg-img("discount_3")
&.invoice
bg-img("invoice_3")
&.special
bg-img("special_3")
&.guarantee
bg-img("guarantee_3")
.foods-wrapper
flex:1
.title
height:26px
background-color:$main_bg
border-left:1px solid $line_bg
text-indent:13px
font-size:12px
color:rgb(147,153,159)
line-height:26px
.foods-item
display:flex
margin:18px
padding-bottom:18px
border-1px($bottom_bg)
&:last-child
padding:0
border-none()
$:first-child
.content
.cartcontroll-wrapper
bottom:5px
.icon
flex:0 0 57px
margin-right:10px
img
border-radius:3px
.content
flex:1
position:relative
.name
margin:2px 0 8px 0
font-size:14px
color:rgb(7,17,27)
line-height:14px
height:14px
.desc,txtra
font-size:10px
color:rgb(147,153,159)
line-height:10px
.desc
margin-bottom:8px
line-height:12px
.extra
font-size:0px
.count
margin-right:12px
.price
.now,add
line-height:24px
font-weight:700
.now
font-size:14px
color:rgb(240,20,20)
margin-right:8px
.odd
font-size:10px
color:rgb(147,153,159)
text-decoration:line-through
.cartcontroll-wrapper
position:absolute
bottom:-8px
right:0
</style>

2 使用 shopcart.vue组件

2.1 未添加小球下落动画 src/components/goods.vue
<template>
<div>
<div class="goods">
<!--左侧分类-->
<div class="menu-wrapper" ref="menuWrapper">
<ul>
<li v-for="(item,index) in goods" class="menu-item"
:class="{'current':currentIndex===index}"
@click="slectMenu(index,$event)">
<span class="text border-1px">
<span class="icon" v-show="item.type>0"
:class="classMap[item.type]"></span>
{{item.name}}
</span>
</li>
</ul>
</div>
<!--右侧商品列表-->
<div class="foods-wrapper" ref="foodsWrapper">
<ul>
<li v-for="item in goods" class="foot-list food-list-hook" ref="foodList">
<h2 class="title">{{item.name}}</h2>
<ul>
<li v-for="food in item.foods" class="foods-item border-1px" @click="selectFood(food,$event)">
<div class="icon">
<img :src="food.icon" width="57" height="57">
</div>
<div class="content">
<h3 class="name">{{food.name}}</h3>
<p class="desc">{{food.description}}</p>
<div class="extra">
<span class="count">月售{{food.sellCount}}</span>
<span>好评率:{{food.rating}}%</span>
</div>
<div class="price">
<span class="now">¥{{food.price}}</span>
<span v-show="food.oldPrice" class="odd">¥{{food.oldPrice}}</span>
</div>
<div class="cartcontroll-wrapper">
<cart-controll :food="food" ref="food"></cart-controll>
</div>
</div>
</li>
</ul>
</li>
</ul>
</div>
<!--底部购物车-->
<shop-cart ref="shopcart" :select-foods="selectFoods" :delivery-price="seller.deliveryPrice" :min-price="seller.minPrice"></shop-cart>
</div>
</div>
</template>
<script type="text/ecmascript-6">
import BScroll from 'better-scroll';
import shopcart from 'components/shopcart/shopcart';
import cartcontroll from 'components/cartcontroll/cartcontroll';
const ERR_OK = 0;
export default{
props: { // 用来接收其他组件的数据
seller: {
type: Object
}
},
data() { // 数据
return {
goods: [],
listHeight: [],
scrollY: 0,
selectedFood: {}
};
},
computed: { // 计算属性
currentIndex() { // 右侧内容区滚动时左侧对应添加样式
for (let i = 0; i < this.listHeight.length; i++) {
let height1 = this.listHeight[i];
let height2 = this.listHeight[i + 1];
if (!height2 || (this.scrollY >= height1 && this.scrollY < height2)) {
return i;
};
};
return 0;
},
selectFoods() { // 计算商品数量是否变化(可以监听到被cartcontroll.vue改变的food)
// 因为在使用cartcontroll.vue时传给它的就是food
// 将变化结果传递给shopcart.vue( :select-foods="selectFoods")
let foods = [];
this.goods.forEach((good) => {
good.foods.forEach((food) => {
if (food.count) { // 此时food的数量不为0说明已经被添加或减小更改了
foods.push(food);
}
});
});
return foods;
}
},
created() { // dom加载时的操作
this.classMap = ['decrease', 'discount', 'special', 'invoice', 'guarantee'];
// 请求获取goods的数据
this.$http.get('/api/goods')
.then((res) => {
res = res.body;
if (res.errno === ERR_OK) {
this.goods = res.data;
this.$nextTick(() => { // 保证dom渲染好后
this._initScroll();
this._calcullateHeight(); // 计算区间高度组成的数组
});
}
;
});
},
methods: { // 方法
_initScroll() {
this.menuScroll = new BScroll(this.$refs.menuWrapper, {
click: true // 可以点击
});
this.foodsScroll = new BScroll(this.$refs.foodsWrapper, {
probeType: 3, // scroll滚动时监听滚动位置
click: true
});
this.foodsScroll.on('scroll', (pos) => {
this.scrollY = Math.abs(Math.round(pos.y));
// console.log(this.scrollY);
});
},
_calcullateHeight() { // 计算右侧内容各自分区的高度 添加到this.listHeight数组中
// let foodList = this.$refs.foodsWrapper.getElementsByClassName('food-list-hook');
let foodList = this.$refs.foodList; // 获得右侧li的dom集合
let height = 0;
this.listHeight.push(height);
for (let i = 0; i < foodList.length; i++) {
let item = foodList[i];
height += item.clientHeight; // 每个区间累加后的高度
this.listHeight.push(height); // 区间高度放到数组里面
};
},
slectMenu(_index, ev) { // 点击左侧分类添加样式,右侧对应内容滚动到顶部
if (!ev._constructed) { // 使用了BS
return;
};
let foodList = this.$refs.foodList;
let els = foodList[_index];
this.foodsScroll.scrollToElement(els, 300);
}
},
components: { // 注册组件
shopCart: shopcart, // 底部购物车
cartControll: cartcontroll // 增加减少
}
};
</script>
<style lang="stylus" rel="stylesheet/stylus">
@import "../../common/stylus/mixin.styl"
.goods
$main_bg = #f3f5f7
$line_bg = #d9dde1
$bottom_bg = rgba(7,17,27,0.1)
display:flex
overflow:hidden
position:absolute
top:174px
bottom:46px
width:100%
.menu-wrapper
flex:0 0 80px
width:80px
background:$main_bg
.menu-item
display:table
height:54px
width:56px
line-height:14px
padding:0 12px
&.current
position:relative
z-index:10
margin-top: -1px
background:#fff
&:before
content:''
display:block
width:4px
height:100%
position:absolute
top:0
left:0
background-color:#00A0DC
.text
border-none()
font-weight:700
.text
display:table-cell
width:56px
vertical-align:middle
font-size:12px
border-1px($bottom_bg)
.icon
display:inline-block
width:12px
height:12px
margin-right:2px
background-size:12px
background-repeat:no-repeat
&.decrease
bg-img("decrease_3")
&.discount
bg-img("discount_3")
&.invoice
bg-img("invoice_3")
&.special
bg-img("special_3")
&.guarantee
bg-img("guarantee_3")
.foods-wrapper
flex:1
.title
height:26px
background-color:$main_bg
border-left:1px solid $line_bg
text-indent:13px
font-size:12px
color:rgb(147,153,159)
line-height:26px
.foods-item
display:flex
margin:18px
padding-bottom:18px
border-1px($bottom_bg)
&:last-child
padding:0
border-none()
$:first-child
.content
.cartcontroll-wrapper
bottom:5px
.icon
flex:0 0 57px
margin-right:10px
img
border-radius:3px
.content
flex:1
position:relative
.name
margin:2px 0 8px 0
font-size:14px
color:rgb(7,17,27)
line-height:14px
height:14px
.desc,txtra
font-size:10px
color:rgb(147,153,159)
line-height:10px
.desc
margin-bottom:8px
line-height:12px
.extra
font-size:0px
.count
margin-right:12px
.price
.now,add
line-height:24px
font-weight:700
.now
font-size:14px
color:rgb(240,20,20)
margin-right:8px
.odd
font-size:10px
color:rgb(147,153,159)
text-decoration:line-through
.cartcontroll-wrapper
position:absolute
bottom:-8px
right:0
</style>
2.2 添加小球下落动画
2.2.1 src/components/goods.vue
<div class="cartcontroll-wrapper">
<cart-controll :food="food" @add="addFood"></cart-controll>
</div>
methods:
// 小球相关
addFood(target) { //获得cart-controll.vue 点击的对象 可以获得的原因 1传递了add事件 2 $emit这个对象
this._drop(target);
},
_drop(target) {
this.$nextTick(() => { // 体验优化,异步执行下落动画
this.$refs.shopcart.drop(target); // 访问子组件shopcart.vue
});
}
3 src/components/cartcontroll.vue组件(增加时旋转和平移)
<template>
<div class="cartcontroll">
<transition name="move">
<div class="cart-decrease" v-show="food.count>0"
@click.stop.prevent="decreaseCart">
<span class="inner icon-remove_circle_outline"></span>
</div>
</transition>
<div class="cart-count" v-show="food.count>0">{{food.count}}</div>
<div class="cart-add icon-add_circle" @click.stop.prevent="addCart"></div>
</div>
</template>
<script type="text/ecmascript-6">
import Vue from 'vue';
export default {
props: { // 接收其他组件传递过来的数据
food: {
type: Object
}
},
methods: { // 指令方法
addCart: function(ev) { // 增加商品到购物车里
if (!ev._constructed) { // 去掉触发pc的事件--保证pc移动事件相同
return false;
};
if (!this.food.count) {
// this.food.count = 1; 不生效
Vue.set(this.food, 'count', 1); // 此时这个属性变化就能被观测到
} else {
this.food.count++;
};
// this.$dispatch('cart.add', ev.target); 2.0- 已被废除
this.$emit('add', event.target); // 触发当前实例上的事件。附加参数都会传给监听器回调。event.target点击的按钮的dom
},
decreaseCart: function (ev) { // 减少购物车里面商品的数量
if (!ev._constructed) {
return false;
};
if (this.food.count) {
this.food.count--;
};
}
}
};
</script>
<style lang="less" rel="stylesheet/less">
.cartcontroll{
font-size:0px;
.cart-decrease{ /*该层负责平移*/
display:inline-block;
line-height: 24px;
font-size: 24px;
transition: all 0.4s linear;
opacity: 1;
transform: translate3d(0,0,0);
.inner{ /*文字层负责旋转*/
display:inline-block;
padding: 6px;
color:#00A0DC;
transition:all 0.4s linear;
transform: rotate(0deg);
}
&.move-enter-active, &.move-leave-active {
transition: all 0.4s linear;
}
&.move-enter, &.move-leave-active{
opacity: 0;
transform: translate3d(24px,0,0);
.inner{
transform: rotate(180deg);
}
}
}
.cart-count{
display:inline-block;
vertical-align: top;
width:12px;
padding-top:6px;
line-height: 24px;
text-align: center;
font-size: 10px;
color:rgb(147,153,159);
}
.cart-add{
display:inline-block;
line-height: 24px;
font-size: 24px;
padding: 6px;
color:#00A0DC;
}
}
</style>

4 点击购物车出现列表(购物列表可折叠 增加 减少产品数量) src/components/shopcart.vue
<template>
<div>
<div class="shop-cart">
<div class="content" @click="toggleList">
<div class="con-left">
<div class="logo-wrapper">
<div class="logo" :class="{'highlight':totalCount>0}">
<i class="icon-shopping_cart" :class="{'highlight':totalCount>0}"></i>
</div>
<div class="num" v-show="totalCount>0">{{totalCount}}</div>
</div>
<div class="price" :class="{'highlight':totalCount>0}">¥{{totalPrice}}</div>
<div class="desc">另需配送费¥{{minPrice}}元</div>
</div>
<div class="con-right" :class="{enough:isEnoughPay}" @click.stop.prevent="pay">
<div class="pay">{{payDesc}}</div>
</div>
</div>
<div class="ball-container">
<div v-for="ball in balls">
<transition name="drop" @before-enter="beforeDrop" @enter="dropping" @after-enter="afterDrop">
<div class="ball" v-show="ball.show">
<div class="inner inner-hook"></div>
</div>
</transition>
</div>
</div>
<transition name="fold">
<div class="shopcart-list" v-show="listShow" transition="fold">
<div class="list-header">
<h2 class="title">购物车</h2>
<span class="empty" @click="empty">清空</span>
</div>
<div class="list-conent" ref="listContent">
<ul>
<li class="food border-1px" v-for="food in selectFoods">
<span class="name">{{food.name}}</span>
<div class="price">
<span>¥{{food.price*food.count}}</span>
</div>
<div class="cartcontroll-wrapper">
<cart-controll @add="addFood" :food="food"></cart-controll>
</div>
</li>
</ul>
</div>
</div>
</transition>
</div>
<!--模糊背景-->
<transition name="fade">
<div class="list-mask" v-show="listShow" @click="hideList"></div>
</transition>
</div>
</template>
<script type="text/ecmascript-6">
import cartcontroll from 'components/cartcontroll/cartcontroll';
import BScroll from 'better-scroll';
export default {
data() {
return {
isEnoughPay: false,
balls: [ // 小球相关
{
show: false
},
{
show: false
},
{
show: false
},
{
show: false
},
{
show: false
}
],
dropBalls: [], // 小球相关
fold: false // 购物车商品详情页展开还是折叠
};
},
props: { // 接收其他组件传递过来的数据
selectFoods: {
type: Array,
default: []
},
deliveryPrice: {
type: Number,
default: 0
},
minPrice: {
type: Number,
default: 0
}
},
computed: { // 计算
totalPrice() { // 选中商品总价格
let total = 0;
this.selectFoods.forEach((food) => { // food表示selectFoods数组的每项
total += food.price * food.count;
});
return total;
},
totalCount() { // 选中的商品总数量
let count = 0;
this.selectFoods.forEach((food) => { // food表示selectFoods数组的每项
count += food.count;
});
return count;
},
payDesc() { // 判断是否满足配送条件
if (this.totalPrice === 0) {
this.isEnoughPay = false;
return `¥${this.minPrice}元起送`;
} else if (this.totalPrice < this.minPrice) {
let diff = this.minPrice - this.totalPrice;
this.isEnoughPay = false;
return `还差¥${diff}元起送`;
} else {
this.isEnoughPay = true;
return '去结算';
}
},
listShow: function () {
if (!this.totalCount) { // 折叠
this.fold = true;
return false;
};
let show = !this.fold; // 展开
if (show) {
this.$nextTick(() => {
if (!this.scroll) { // list-show不断变化,不能变化的时候就初始化
this.scroll = new BScroll(this.$refs.listContent, { // $refs.listContent 要和ref值一样,区分大小写
click: true
});
} else {
this.scroll.refresh();
};
});
};
return show;
}
},
methods: {
// 小球相关 开始
drop(el) { // 取的父goods.vue组件传来的数据el
for (let i = 0; i < this.balls.length; i++) {
let ball = this.balls[i];
if (!ball.show) {
ball.show = true;
ball.el = el;
this.dropBalls.push(ball);
return;
};
};
},
addFood(target) {
console.log(1);
this.drop(target);
},
beforeDrop(el) {
let count = this.balls.length;
while (count--) {
let ball = this.balls[count];
if (ball.show) {
let rect = ball.el.getBoundingClientRect();
// 用于获得页面中某个元素的左,上,右和下分别相对浏览器视窗的位置
let x = rect.left - 32;
let y = -(window.innerHeight - rect.top - 22);
// console.log(x);
// console.log(y);
el.style.display = '';
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)`;
}
}
},
dropping(el, done) {
/* 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)';
el.addEventListener('transitionend', done);
});
},
afterDrop(el) {
let ball = this.dropBalls.shift();
if (ball) {
ball.show = false;
el.style.display = 'none';
}
},
// 小球相关结束
toggleList() {
if (!this.totalCount) {
return;
};
this.fold = !this.fold;
},
empty() { // 清空购物车
this.selectFoods.forEach((food) => {
food.count = 0;
});
},
hideList() { // 购物车商品列表隐藏
this.fold = true;
},
pay() { // 满足支付条件点击后操作
if (this.totalPrice < this.minPrice) {
return;
};
window.alert(`支付${this.totalPrice}元`);
}
},
components: {
cartControll: cartcontroll
}
};
</script>
<!--<style lang="stylus" rel="stylesheet/stylus">
</style>-->
<style lang="less" rel="stylesheet/less">
.shop-cart{
position: fixed;
height:48px;
width:100%;
left:0;
bottom:0;
z-index: 50;
.content{
display:flex;
background-color: rgb(20,29,39);
font-size: 0;
.con-left{
flex: 1;
font-size:0px;
.logo-wrapper,
.price,
.desc{
display: inline-block;
}
.logo-wrapper{
position: relative;
top:-10px;
margin:0 12px;
padding: 6px;
width:56px;
height:56px;
box-sizing: border-box;
vertical-align: top;
border-radius:50%;
background-color:#141d27;
.logo{
width:100%;
height: 100%;
border-radius:50%;
background-color: rgb(43,52,60);
font-size: 24px;
line-height: 45px;
text-align: center;
&.highlight{
background:rgb(0,160,220)
}
.icon-shopping_cart{
color:rgba(255,255,255,0.4);
font-size: 24px;
&.highlight{
color:#fff;
}
}
}
.num{
position: absolute;
top:0;
right:0;
width:24px;
height:16px;
line-height: 16px;
text-align: center;
border-radius: 16px;
font-size: 9px;
font-weight: 700;
color:#fff;
background-color: rgb(240,20,20);
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.4);
}
}
.price{
display: inline-block;
vertical-align: top;
margin-top: 12px;
line-height: 24px;
height:24px;
padding-right: 12px;
box-sizing: border-box;
border-right: 1px solid rgba(255,255,255,0.1);
font-size: 16px;
font-weight: 700;
color:rgb(127,133,138);
&.highlight{
color:#fff;
}
}
.desc{
display: inline-block;
font-size: 10px;
line-height: 24px;
height:24px;
color:rgb(127,133,138);
margin-top:12px;
text-indent: 12px;
}
}
.con-right{
flex: 0 0 105px;
width: 105px;
line-height: 48px;
height:48px;
padding:0 8px;
box-sizing: border-box;
color:rgb(127,133,138);
background-color: rgb(43,52,60);
text-align: center;
&.enough{
background-color:#34B413;
.pay{
color:#fff;
font-size: 16px;
}
}
.pay{
font-size: 12px;
font-weight: 700;
}
}
}
.ball-container{
.ball{
position: fixed;
left:32px;
bottom:22px;
z-index: 200;
&.drop-transition{
transition: all 0.4s cubic-bezier(0.49,-0.29,0.75,0.41);
.inner{
width:16px;
height: 16px;
border-radius: 50%;
background-color: rgb(0,160,220);
transition:all 0.4s linear;
}
}
}
}
.shopcart-list{
position: absolute;
left:0;
top:0;
z-index: -1;
width:100%;
transform: translate3d(0,-100%,0);
&.fold-enter-active, &.fold-leave-active{
transition:all 0.5s;
}
&.fold-enter,&.fold-leave-active{
transform: translate3d(0,0,0);
}
.list-header{
height:40px;
line-height: 40px;
padding:0 18px;
background-color: #f3f5f7;
border-bottom:1px solid rgba(7,17,27,0.1);
.title{
float:left;
font-size: 14px;
color:rgb(7,17,27);
}
.empty{
float: right;
font-size:12px;
color:rgb(0,160,220);
}
}
.list-conent{
padding:0 18px;
max-height:217px;
background-color: #fff;
overflow:hidden;
.food{
position: relative;
padding:12px 0;
border-bottom:1px solid rgba(7,17,27,0.1);
.name{
line-height: 24px;
font-size: 14px;
color:rgb(7,17,27);
}
.price{
position: absolute;
right:94px;
bottom:12px;
line-height: 24px;
font-size: 14px;
font-weight: 700;
color:rgb(240,20,20);
}
.cartcontroll-wrapper{
position: absolute;
right:0;
bottom:6px;
}
}
}
}
}
.list-mask{
position:fixed;
top:0;
left:0;
width:100%;
height:100%;
z-index:40;
backdrop-filter:blur(10px);
opacity: 1;
background: rgba(7, 17, 27, 0.6);
&.fade-enter-active, &.fade-leave-active{
transition:0.5s all;
}
&.fade-enter,&.fade-leave-active{
opacity:0;
background:rgba(7,17,27,0);
}
}
</style>
组件间简单图解


浙公网安备 33010602011771号