nuxt.js 也是基于vue 的 那么就离不开组件化开发 我们按照组件结构来进行分析
navTop
页面的头部 通用组件 分隔了三个位置 适用于大多数头部 且预留插槽
<template>
<div class="nav-top">
<div class="left">
<slot name="left"></slot>
</div>
<div class="center">
<slot name="center"></slot>
</div>
<div class="right">
<slot name="right"></slot>
</div>
</div>
</template>
<script>
export default {
name: "Navtop"
}
</script>
<style scoped>
.nav-top{
display: flex;
line-height: 52px;
height: 52px;
overflow: hidden;
}
.left,.right{
display: flex;
width: 16%;
align-items: center;
justify-content: center;
}
.center{flex: 1}
</style>
在首页使用
引入:
import navTop from '../components/common/navtop/Navtop'
注册
components:{ navTop, },
使用 左边放logo 中间搜索框 右边放 标识
<navTop class="navtop">
<div slot="left">
<img src="~assets/img/common/logo-bai.png" alt="" class="img1" @click="GoHome">
</div>
<div slot="center">
<input type="text" class="input" placeholder="二建优学班" @click="GoSearch">
</div>
<div slot="right">
<img src="~assets/img/tabbar/class-bai.svg" alt="" class="img2 svg" @click="GoClass">
</div>
</navTop>
对应的回调 分别跳转到 不同的位置
methods:{
GoHome(){
this.$router.push('/home')
},
GoSearch(){
this.$router.push('/search')
},
GoClass(){
this.$router.push('/class')
}
}
Swiper 轮播组件
首先要安装 对应的依赖包
npm i swiper@4.5.1
npm i vue-awesome-swiper@3.1.3
创建对应的组件:
swiper 的相关配置 v-swiper:mySwiper 绑定到下方 swiperOption当中
轮播图的数据 由外部 组件 props 传进来
图片加载完成后 @onload 发射自定义事件 通知首页 计算图片加载完成后的首页页面长度
<template>
<div v-swiper:mySwiper="swiperOption" v-if="csbanner.length">
<div class="swiper-wrapper">
<div class="swiper-slide" v-for="banner in csbanner">
<img :src="banner" @load="homeswiperload()">
</div>
</div>
<div class="swiper-pagination swiper-pagination-bullets"></div>
</div>
</template>
<script>
export default {
name: "swiper",
props:{
csbanner:{
type:Array,
default(){
return[]
}
}
},
data(){
return{
swiperOption:{
spaceBetween: 0,
autoplay: {
delay: 3000,
disableOnInteraction: false,
},
pagination: {
el: '.swiper-pagination',
clickable: true,
},
speed:700,//切换速度
loop:true//前后循环
},
isload:false,
}
},
methods:{
homeswiperload(){
if(!this.isload){
console.log('首页swiper轮播图加载完成');
this.$emit('homeswiperload')
this.isload = true
}
}
}
}
</script>
<style scoped>
.swiper-pagination{
width: 100%;
bottom: 10px;
}
</style>
plugin/swiper.js
在这里编辑相关配置 挂载到nuxt.confin.js 的 plugin模块当中
这样写 还有一个作用就是 在ssr渲染中 没有全局this 导致 swiper的相关报错
import Vue from 'vue'
if (process.browser) {
const VueAwesomeSwiper = require("vue-awesome-swiper/dist/ssr");
Vue.use(VueAwesomeSwiper);
}
在首页 引入及使用
import homeSwiper from '../components/common/swiper/swiper'components:{ homeSwiper, },<homeSwiper :csbanner="homeData.bannerData" class="swiper"></homeSwiper>
homeIcon 和 homeRecommend 都是基础布局+数据渲染 没什么难度
<homeIcon :cicons="homeData.icons"></homeIcon> <homeRecommend :caws="homeData.aws" :chotclass="homeData.hotclass"></homeRecommend>
主要就是网络请求相关的 流程 梳理一下:
在nuxt.js 中 asyncData 属于一个生命周期 在此生命周期中请求数据 返回数据不用再赋值到组件的data 中 课直接供模板使用
async asyncData({$axios}){
const {data} = await $axios.get('http://www.wsg3096.com/ass/home-data.txt')
return {homeData:data}
},
homeIcon
<template>
<div class="homeicon">
<div v-for="n in cicons">
<a :href="n.url">
<img :src="n.img" alt="">
<div>{{n.title}}</div>
</a>
</div>
</div>
</template>
<script>
export default {
name: "Home-icon",
props:{
cicons:{
type:Array,
default(){
return[]
}
}
}
}
</script>
<style scoped>
.homeicon{
display: flex;
justify-items: center;
text-align: center;
padding: 10px 0px;
background: #fff;
box-shadow: 1px 8px 8px rgba(155,155,155,0);
}
.homeicon img{
width: 48px
}
.homeicon div{
width: 100%;
text-align: center;
cursor: pointer;
font-size: 14px}
</style>
homeRecommend
<template>
<div class="recommend">
<div class="tuijian-bt">
{{caws.boxBy1}}
<a href="https://m.zhongxin5.cn/Live/Index?classId=0&teacherId=0&isback=2" target="_blank">
<span>更多></span>
</a>
</div>
<div class="tuijian" v-for="w in chotclass.slice(0,4)">
<a :href="w.link">
<img :src="w.img" alt="">
<div class="right">
<span class="tuijian-name">{{caws.erjian}} - {{w.tit2}}<br>{{w.tit3}}</span>
<span class="tuijian-price">
<i>¥</i>{{w.price}}<i class="line-c">¥{{w.lastprice}}</i>
</span>
</div>
</a>
<div class="clear-fix"></div>
</div>
</div>
</template>
<script>
export default {
name: "Home-recommend",
props:{
caws:{
type:Object,
default() {
return {}
}
},
chotclass:{
type:Array,
default() {
return []
}
}
},
methods:{
}
}
</script>
<style scoped>
.tuijian{
padding: 12px 10px;
background: #fff;
margin: 0px 16px;
border-bottom: 1px solid #f8e8e8;
}
.tuijian-bt{
font-size: 20px;
font-weight: bold;
line-height: 3;
margin: 0px 18px;
display: flex;
justify-content: space-between;
align-items: center;
color: #f35;
}
.tuijian-bt span{
font-size: 15px;
font-weight: 400;
color: #666;
}
.tuijian img{
width: 45%;
float: left;
border-radius: 10px;
}
.tuijian-price i{
font-style: normal;
font-size: 16px;
font-weight: 400;
}
.tuijian-price{
font-size: 20px;
font-weight: 600;
color: #fc3f1d;
margin-top: 8px;
}
.right{
width: 55%;
padding-left: 8px;
}
.tuijian-name{
font-size: 16px;
line-height: 1.6;
white-space: nowrap;
}
.line-c{
text-decoration: line-through;
margin-left: 8px;
color: #666;
}
.right span{
display: block;
}
</style>