-
transition动画文档:
https://cn.vuejs.org/v2/guide/transitions.html
-
transition不需要引入,因其本身是Vue内置的
-
组件(只展示了相关代码)
- index.vue(父组件)
<template>
<div class="index">
<div class="product-box">
<div class="container">
<span class="product-box-title">手机</span>
<div class="wrapper">
<div class="wrapper-left">
<a href="javascript:;">
<img src="/imgs/mix-alpha.jpg" />
</a>
</div>
<div class="wrapper-box">
<div class="wrapper-box-list" v-for="(item,index) in phoneList" :key="index">
<div class="list-item" v-for="(sub,i) in item" :key="i">
<span :class="{'new-pro':i%2==0}">新品</span>
<div class="list-item-img">
<img :src="sub.mainImage" />
</div>
<div class="list-item-info">
<p class="info-name">{{sub.name}}</p>
<p class="info-describe">{{sub.subtitle}}</p>
<p @click="addCart" class="info-price">{{sub.price}}元</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!--
在父组件定义一个submit事件
(组件中不能用click进行事件绑定,需要用子组件传来的名称进行定义,即submit)
-->
<Modal title="提示" btnType="3" modalType="middle" :showModal="showModal" v-on:submit="goToCart" v-on:cancel="showModal=false">
<!--
插槽的用法:
嵌套一个template模板,用v-slot定义插槽的名称(Modal.vue中的<slot name="body"></slot>)
-->
<template v-slot:body>
<p>商品添加成功!</p>
</template>
</Modal>
</div>
</template>
<script>
import Modal from "../components/Modal";
export default {
name: "index",
components: {
Modal
},
data() {
return {
// 手机商品功能的实现
phoneList: [],
// Modal动画是否展示
showModal:false
};
},
mounted() {
this.init();
},
methods: {
init() {
// 需要后台的真实接口
this.axios.get("/products", {
params: {
categoryId: 100012,
pageSize: 14
}
}).then(res => {
res.list = res.list.slice(6, 14);
this.phoneList = [res.list.slice(0, 4), res.list.slice(4, 8)];
});
},
// 添加至购物车
addCart(){
this.showModal=true;
// 调后台接口
// this.axios.post('/carts',{
// productId:id,
// selected: true
// }).then((res)=>{
// });
},
goToCart(){
this.$router.push('/cart');
}
}
};
</script>
<style lang="scss" scope>
@import "../assets/scss/config.scss";
@import "../assets/scss/mixin.scss";
@import "../assets/scss/base.scss";
.index {
.product-box {
background-color: $colorJ;
padding: 30px auto 50px;
.product-box-title {
display: block;
font-size: $fontF;
color: $colorB;
padding: 30px 0;
}
.wrapper {
display: flex;
.wrapper-left {
margin-right: 16px;
width: 224px;
height: 619px;
}
.wrapper-box {
margin-bottom: 51px;
.wrapper-box-list {
@include flex();
margin-bottom: 15px;
&:last-child {
margin-bottom: 0;
}
.list-item {
width: 236px;
height: 302px;
background-color: $colorG;
margin-right: 14px;
text-align: center;
&:nth-child(4n) {
margin-right: 0;
}
span {
display: inline-block;
width: 67px;
height: 24px;
line-height: 24px;
text-align: center;
color: $colorG;
// 可通过动态修改class,实现颜色的切换
&.new-pro {
background-color: #7ecf68;
}
&.kill-pro {
background-color: #e82626;
}
}
.list-item-img {
img {
width: 190px;
height: 195px;
object-fit: cover;
}
}
.list-item-info {
.info-name {
font-size: $fontJ;
font-weight: bold;
color: $colorB;
line-height: $fontJ;
}
.info-describe {
font-size: $fontK;
color: $colorD;
line-height: 13px;
margin: 6px auto 13px;
}
.info-price {
font-size: $fontJ;
font-weight: bold;
color: #f20a0a;
cursor: pointer;
&::after {
content: " ";
@include bgImg(20px, 20px, "/imgs/icon-cart-hover.png");
margin-left: 8px;
vertical-align: middle;
}
}
}
}
}
}
}
}
}
</style>
-
Modal.vue(子组件)
通过在 props 中对 modalType(弹框类型)、title(弹框标题)、btnType(按钮类型)、 confirmText(确定文本)、cancelText(取消文本)以及 showModal(弹框是否需要展示)的设置, 实现动态设置组件的功能,以便于对组件进行复用。
<template>
<transition name="slide">
<div class="modal" v-show="showModal">
<!-- 遮罩 -->
<div class="mask"></div>
<!-- 会话 -->
<div class="modal-dialog">
<div class="dialog-header">
<span>{{title}}</span>
<a href="javascript:;" class="icon-close" v-on:click="$emit('cancel')"></a>
</div>
<div class="dialog-body">
<slot name="body"></slot>
</div>
<div class="dialog-footer">
<!-- 子组件点击“确定”以后向父组件传递,父组件用emit进行传递;在这里点击“确定”之后,调用父组件的submit -->
<a href="javascript:;" v-if="btnType==1" @click="$emit('submit')" class="btn btn-default btn-margin">{{confirmText}}</a>
<a href="javascript:;" v-if="btnType==2" @click="$emit('cancel')" class="btn btn-default btn-margin btn-gray">{{cancelText}}</a>
<div v-if="btnType==3" class="btn-margin">
<a href="javascript:;" @click="$emit('submit')" class="btn btn-default btn-margin">{{confirmText}}</a>
<a href="javascript:;" @click="$emit('cancel')" class="btn btn-default btn-margin btn-gray">{{cancelText}}</a>
</div>
</div>
</div>
</div>
</transition>
</template>
<script>
export default {
name: "modal",
props: {
// 弹框类型:小small、中middle、大large、表单form
modalType: {
type: String,
default: "form"
},
// 弹框标题
title: String,
// 按钮类型:1、 确定按钮 2、取消按钮 3、确定取消
btnType: String,
// 确定文本
confirmText: {
type: String,
default: "确定"
},
// 取消文本
cancelText: {
type: String,
default: "取消"
},
// 弹框是否需要展示
showModal: Boolean
}
};
</script>
<style lang="scss" scope>
@import "../assets/scss/mixin.scss";
@import "../assets/scss/config.scss";
@import "../assets/scss/modal.scss";
</style>
- 样式文件
-
modal.scss
对modal动画进行设置
.modal{
@include position(fixed);
z-index: 10;
transition: all .5s linear;
.mask{
@include position(fixed);
background-color: $colorI;
opacity: 0.5;
}
// slide-enter需要放在slide-enter-active、slide-leave-active下面
&.slide-enter-active{
top: 0;
}
&.slide-leave-active{
top: -100%;
}
&.slide-enter{
top: -100%;
}
.modal-dialog{
@include position(absolute,40%,50%,660px,auto);
background-color: $colorG;
transform: translate(-50%,-50%);
.dialog-header{
height: 60px;
line-height: 60px;
background-color: $colorJ;
span{
font-size: $fontI;
padding: 22px 26px;
box-sizing: border-box;
color: $colorB;
}
.icon-close{
@include positionImg(absolute,23px,25px,16px,16px,'/imgs/icon-close.png');
transition: all .2s linear;
&:hover{
transform: scale(1.4);
}
}
}
.dialog-body{
padding: 42px 40px;
font-size: $fontJ;
}
.dialog-footer{
height: 80px;
line-height: 80px;
text-align: center;
background-color: $colorJ;
}
}
}
-
button.scss
对项目中的所有提示框按钮的样式进行设置; 直接在App.vue中引入,就不需要在相应组件进行引入。
.btn{
display: inline-block;
text-align: center;
font-size: $fontI;
color: $colorG;
border: none;
cursor: pointer;
background-color: $colorA;
}
.btn-gray{
background-color: #B0B0B0;
}
.btn-margin{
margin-right: 21px;
&:last-child{
margin-right: 0;
}
}
.btn-buy{
width: 110px;
line-height: 30px;
}
.btn-pay{
width: 130px;
line-height: 35px;
}
.btn-like{
width: 142px;
height: 54px;
}
.btn-default{
width: 160px;
line-height: 40px;
}
.btn-success{
width: 200px;
line-height: 54px;
}
.btn-account{
width: 202px;
line-height: 50px;
}
.btn-join{
width: 300px;
line-height: 54px;
}
.btn-request{
width: 332px;
line-height: 42px;
}
.btn-login{
width: 348px;
line-height: 50px;
}
-
mixin.scss
对项目中使用较多的样式进行针对设计,在style可使用 @include flex() 等方法进行设置
// flex布局复用
@mixin flex($hov:space-between,$col:center){
display: flex;
justify-content: $hov;
align-items: $col;
}
@mixin bgImg($w:0,$h:0,$img:'',$size:contain){
display: inline-block;
width: $w;
height: $h;
background: url($img) no-repeat center;
background-size: $size;
}
@mixin position($pos:absolute,$top:0,$left:0,$w:100%,$h:100%){
position: $pos;
top: $top;
left: $left;
width: $w;
height: $h;
}
@mixin positionImg($pos:absolute,$top:0,$right:0,$w:0,$h:0,$img:''){
position: $pos;
top: $top;
right: $right;
width: $w;
height: $h;
background: url($img) no-repeat center;
background-size: contain;
}
-
config.scss
样式规范表,字体大小与颜色可根据项目自行定义
$min-width:1226px; //容器安全区域宽度
// 常规字体大小设置
$fontA: 80px;
$fontB: 38px;
$fontC: 28px;
$fontD: 26px;
$fontE: 24px;
$fontF: 22px;
$fontG: 20px;
$fontH: 18px;
$fontI: 16px;
$fontJ: 14px;
$fontK: 12px;
// 常规配色设置
$colorA: #FF6600 !default;
$colorB: #333333 !default;
$colorC: #666666 !default;
$colorD: #999999 !default;
$colorE: #cccccc !default;
$colorF: #d7d7d7 !default;
$colorG: #ffffff !default;
$colorH: #e5e5e5 !default;
$colorI: #000000 !default;
$colorJ: #F5F5F5 !default;
-
结果展示
Modal动画:点击商品价格旁的“购物车”后,提示框会淡入页面;点击“取消”或“×”,均会使提示框淡出页面。 点击“购物车”,会将商品添加至购物车内,但这里没有后台接口,因此只做了跳转至cart(购物车页面)路由; 点击“确定”也可跳转至cart路由; 点击“取消”或“×”,均可回到当前页面;