目录
1. Nav-Header组件
2. 首页轮播功能实现
一. Nav-Header组件
(1)组件复用的一个技巧:
因为商场网站中多个页面共用了头部组件nav-header和底部组件nav-footer,而为了避免 每个需要这两个组件的页面中都需要单独引入组件,我们可以通过一个home页面来复用共用的组件。
- 在路由文件中:
{
path: '/',
name: 'home',
component:Home,
redirect: '/index',
children: [ //下面是需要头部和底部组件的页面
{
path: '/index',
name: 'index',
component: Index,
},
{
path: '/product/:id',
name: 'product',
component: Product,
},
{
path: '/detail/:id',
name: 'detail',
component: Detail,
}
]
},
- 在home.vue中:
<template>
<div>
home
<nav-header></nav-header>
<router-view></router-view>
<nav-footer></nav-footer>
</div>
</template>
<script>
import NavHeader from './../components/NavHeader';
import NavFooter from './../components/NavFooter';
export default {
name: 'nav-home',
components: {
NavHeader,
NavFooter
}
}
</script>
(2)通过@mixin
简化代码
为了有效的维护和开发项目,代码的重复利用就显得尤为重要。在Sass中,除了@import
和@extend
可以使代码更加具有重复利用性,@mixin
指令也同样能提高代码的重复使用率并简化你的代码。
- 在assets文件夹中创建一个scss文件夹。在scss文件夹中创建mixin.scss文件,在里面存放将会共用的代码:
@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;
margin-right: 4px;
}
- 在用到mixin.scss里样式的文件NavHeader里,在
<style>
标签中引入mixin.scss文件并替换用到的css代码
<style lang="scss">
@import './../assets/scss/mixin.scss';
.container{
height: 112px;
/* display: flex;
justify-content: $hov;
align-items: $col; */
@include flex();
}
.my-cart{
width: 100px;
background-color: #FF6600;
text-align: center;
color: #ffffff;
.icon-cart{
/*
display: inline-block;
width: 16px;
height: 12px;
background:url('/imgs/icon-cart-checked.png') no-repeat center;
background-size: contain;
margin-right: 4px;
*/
@include bgImg(16px, 12px, '/imgs/icon-cart-checked.png');
margin-right:4px;
}
}
</style>
- @mixin学习资料:
(3)统一修改系统主题色
- 在scss文件夹中加入文件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; //用于需要突出和强调的文字、按钮和icon
$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; //弹框标题背景色
$colorK: #FFFAF7 !default; //订单标题背景色
- 在需要用到常规样式的组件或页面中引入config.scss并使用样式:
<style lang="scss">
@import "./../assets/scss/config.scss";
&:hover {
color:$colorA;
}
</style>
(4) 数据请求
export default {
name: "nav-header",
data() {
return {
username: "jack",
phoneList: []
};
},
mounted() {
this.getProductList();
},
methods: {
getProductList() {
this.axios
.get("/products", {
params: {
categoryId: "100012"
}
})
.then(res => {
if (res.list.length > 6) {
this.phoneList = res.list.slice(0, 6);
}
});
},
}
};
二. 首页轮播功能实现
(1)使用vue-awesome-swiper实现轮播图
- 安装vue-awesome-swiper:
npm install vue-awesome-swiper --save
- 在需要用到该插件的文件里导入和使用组件:
<template>
<div class="swiper-box">
<swiper v-bind:options="swiperOption">
<swiper-slide v-for="(item, index) in slideList" v-bind:key="index">
<a v-bind:href="'/#/product' + item.id">
<img v-bind:src="item.img"/>
</a>
</swiper-slide>
<div class="swiper-pagination" slot="pagination"></div>
<div class="swiper-button-prev" slot="button-prev"></div>
<div class="swiper-button-next" slot="button-next"></div>
</swiper>
</div>
</template>
<script>
import {swiper, swiperSlide} from 'vue-awesome-swiper';
import 'swiper/dist/css/swiper.css'
export default {
name: 'index',
components: {
swiper,
swiperSlide,
},
data() {
return {
swiperOption: {
autoplay:true, //自动播放
loop:true, //循环播放
effect:'cube', //切换效果
cubeEffect: { //cube的相关配置参数
slideShadows:true,
shadow:true,
shadowOffset:100,
shadowScale:0.6
},
pagination: { //指定分页器
el: '.swiper-pagination',
clickable:true //允许分页器可点击
},
navigation: { //指定前进后退按钮
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev'
}
},
slideList: [ //轮播图片数组
{
id: '42',
img:'/imgs/slider/slide-1.jpg'
},
{
id: '45',
img:'/imgs/slider/slide-2.jpg'
},
{
id: '46',
img:'/imgs/slider/slide-3.jpg'
}
]
}
}
}
</script>
<!--省略样式代码-->
(2)首页轮播菜单实现
关于实现一个3行4列的图片展示区域:(数据为已定义好的静态数据)
<div class="children">
<ul v-for="(item,i) in menuList" v-bind:key="i">
<li v-for="(sub, j) in item" v-bind:key="j">
<a v-bind:href="sub?'/#/product/'+sub.id : ''">
<img v-bind:src="sub?sub.img:'/imgs/item-box-1.png'">
{{sub?sub.name:'小米9'}}
</a>
</li>
</ul>
</div>
<script>
export default {
data() {
return {
menuList: [
[
{
id:30,
img:'/imgs/item-box-1.png',
name:'小米CC9'
},{
id:31,
img:'/imgs/item-box-2.png',
name:'小米8青春版'
},{
id:32,
img:'/imgs/item-box-3.jpg',
name:'Redmi K20 Pro'
},{
id:33,
img:'/imgs/item-box-2.png',
name:'移动4G专区'
}
],
[0,0,0,0],
[0,0,0,0]
]
}
}
}
</script>
(3)Modal弹窗动画 与 父子组件通信
- 用到vue的transition组件,考虑到较多页面需要用到弹窗,所以将弹窗写成一个独立的组件,在Modal.vue中:
<!--弹窗内容写在transition组件中-->
<template>
<transition name="slide">
<div class="modal" v-show="showModal">
<div class="mask"></div>
<div class="modal-dialog">
<div class="modal-header">
<span>{{title}}</span>
<a href="javascript:;" class="icon-close" v-on:click="$emit('cancel')"></a>
</div>
<div class="modal-body">
<slot name="body"></slot>
</div>
<div class="modal-footer">
<a href="javascript:;" class="btn" v-if="btnType==1" v-on:click="$emit('submit')">{{sureText}}</a>
<a href="javascript:;" class="btn" v-if="btnType==2" v-on:click="$emit('cancel')">{{cancelText}}</a>
<div class="btn-group" v-if="btnType==3">
<a href="javascript:;" class="btn" v-on:click="$emit('submit')">{{sureText}}</a>
<a href="javascript:;" class="btn btn-default" v-on:click="$emit('cancel')">{{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,
sureText:{
type:String,
default:'确定'
},
cancelText:{
type:String,
default:'取消'
},
showModal:Boolean
}
}
</script>
<style lang="scss">
@import './../assets/scss/config.scss';
@import './../assets/scss/mixin.scss';
@import './../assets/scss/modal.scss';
</style>
- 在modal.scss中关于弹窗的动画:
.modal{
transition: all .5s;
&.slide-enter-active{
top:0;
}
&.slide-leave-active{
top:0;
}
&.slide-enter{
top:-100%;
}
}
/*其他样式省略*/
- 在index.vue页面中使用弹窗组件:
<modal
title="提示"
sureText="查看购物车"
btnType="1"
modalType="middle"
v-bind:showModal="showModal"
v-on:submit="goToCart"
v-on:cancel="showModal=false"
>
<template v-slot:body>
<p>商品添加成功!</p>
</template>
</modal>
<script>
import Modal from './../components/Modal'
export default {
name: "index",
components: {
Modal
},
data() {
return {
showModal: false
}
},
methods: {
addCart() {
this.showModal = true;
},
gotoCart() {
this.$router.push('/cart');
}
}
}
</script>
(4)懒加载
- 下载插件:
npm i vue-lazyload -S
- 在main.js里引入并配置:
import VueLazyLoad from 'vue-lazyload'
Vue.use(VueLazyLoad, {
loading:'/imgs/loading-svg/loading-bars.svg'//图片在加载过程的动画
})
- 在index.vue中使用懒加载:
<!--没有懒加载的写法-->
<a
v-bind:href="'/#/product/' + item.id"
v-for="(item, index) in adsList"
v-bind:key="index"
>
<img v-bind:src="item.img" alt />
</a>
<a href="/#/product/30">
<img src="'/imgs/banner-1.png'" alt />
</a>
<!--使用懒加载的写法-->
<a
v-bind:href="'/#/product/' + item.id"
v-for="(item, index) in adsList"
v-bind:key="index"
>
<img v-lazy="item.img" alt />
</a>
<a href="/#/product/30">
<img v-lazy="'/imgs/banner-1.png'" alt />
</a>