首页开发
App.vue 作为入口组件,打开 App.vue,删掉系统创建的代码,只需要保留 router-view 即可,router-view 显示的内容由路由匹配规则决定,代码如下。
import Vue from 'vue';
import Router from 'vue-router';
// 1. 引入首页文件
import index from '../views/index';
Vue.use(Router);
export default new Router({
routes: [
{
// 2. 当为根路径时,显示首页组件
path: '/',
name: 'index',
component: index
}
]
});
在 src 目录下创建 views 文件夹,用于存放网站页面,在 views 目录下新建 index 文件夹,存放首页文件,在 index 文件夹下新建 index.vue,如图 11-4 所示。

修改路由匹配规则,当路径为根路径时,显示 index.vue,代码如下。
<template>
<div id="app">
<!-- <router-view/> 中的内容是变化的,需要根据路由匹配规则显示-->
<router-view />
</div>
</template>
<script>
export default {
name: 'App'
};
</script>
<style scoped>
</style>
进入 views/index/index.vue 进行页面布局。
布局分析:根据效果图发现,首页和全部产品页面的头部及导航菜单不变,变化的是导航菜单下方的内容,这种效果可以使用嵌套路由实现,先布局头部和导航菜单部分,代码如下。
<template>
<div>
<div class="header">
<div class="content">
<img src="../../assets/images/logo.jpg" class="logo" />
<img src="../../assets/images/ad_top.jpg" class="ad_top" />
</div>
</div>
<div class="menu">
<div class="content">
<ul>
<li class="bg_active">首页</li>
<li>全部产品</li>
</ul>
</div>
</div>
<!--导航以下使用嵌套路由-->
<router-view></router-view>
</div>
</template>
只展示视图层代码,CSS 样式代码可以到配套资源中下载。 |
代码解析如下。
因为要使用嵌套路由,所以在首页文件中预留 router-view。
下面讲解首页代码分离。
首页文件中的头部和导航部分可以抽离成一个单独的组件,在 components 目录下新建 header.vue,把头部和导航菜单的视图层整体复制到 header.vue。
index.vue 首页文件引用 header 组件,代码如下。
<template>
<div>
//3.使用组件
<myHeader></myHeader>
//导航以下使用嵌套路由
<router-view></router-view>
</div>
</template>
<script>
//1.引入header组件
import myHeader from '../../components/header';
export default {
components: {
//2.注册组件
myHeader
}
};
</script>
最终运行结果如图 11-5 所示。

布局首页静态页面
本节完成整个首页布局,导航菜单以下所有内容都应该通过路由匹配规则,在 index/index.vue 的 router-view 中展现。
在 components 目录新建 home.vue,home.vue 为首页的其他内容,下面先通过匹配规则把 home.vue 中的内容在首页中显示出来,代码如下。
import Vue from 'vue';
import Router from 'vue-router';
import index from '../views/index';
// 1. 引入 home 组件
import home from '../components/home.vue';
Vue.use(Router);
export default new Router({
routes: [
{
path: '/',
name: 'index',
component: index,
// 2. 创建嵌套路由匹配规则
children: [
{
path: '/', // 注意:子路由的 path 不要以 / 开头
name: 'home',
component: home
}
]
}
]
});
运行代码,home.vue 组件的内容可以在首页中正常显示,最后布局 home.vue 组件即可,代码如下(注:此处只有视图代码,样式代码可在资源中下载)。
<template>
<div>
<div class="banner">
<img src="../assets/images/banner.jpg" />
</div>
<div class="content">
<div class="ad_product_menu">
<img src="../assets/images/ad_product.jpg" />
</div>
<div class="ad_product_main">
<ul>
<li>
<img src="../assets/images/ad_a.jpg" />
</li>
<li>
<img src="../assets/images/ad_a.jpg" />
</li>
<li>
<img src="../assets/images/ad_a.jpg" />
</li>
</ul>
</div>
</div>
<div class="content">
<div class="index_hot">
<div class="index_hot_menu">精品推荐</div>
<div class="index_hot_main">
<ul>
<li>
<img src="../assets/images/p1.jpg" />
</li>
<li>
<img src="../assets/images/p1.jpg" />
</li>
<li>
<img src="../assets/images/p1.jpg" />
</li>
</ul>
</div>
</div>
</div>
<div class="content">
<div class="index_hot_menu">精品推荐</div>
<div class="index_productlist">
<div class="index_productlist_left">
<img src="../assets/images/p2.jpg" />
</div>
<div class="index_productlist_right">
<ul>
<li>
<img src="../assets/images/p2.jpg" />
</li>
<li>
<img src="../assets/images/p2.jpg" />
</li>
<li>
<img src="../assets/images/p2.jpg" />
</li>
<li>
<img src="../assets/images/p2.jpg" />
</li>
</ul>
</div>
</div>
</div>
<div class="content">
<div class="index_hot_menu">精品推荐</div>
<div class="index_productlist">
<div class="index_productlist_left">
<img src="../assets/images/p2.jpg" />
</div>
<div class="index_productlist_right">
<ul>
<li>
<img src="../assets/images/p2.jpg" />
</li>
<li>
<img src="../assets/images/p2.jpg" />
</li>
<li>
<img src="../assets/images/p2.jpg" />
</li>
<li>
<img src="../assets/images/p2.jpg" />
</li>
</ul>
</div>
</div>
</div>
<div class="content">
<div class="ad_product_menu">
<img src="../assets/images/ad_product.jpg" />
</div>
<div class="ad_product_main">
<ul>
<li>
<img src="../assets/images/ad_a.jpg" />
</li>
<li>
<img src="../assets/images/ad_a.jpg" />
</li>
<li>
<img src="../assets/images/ad_a.jpg" />
</li>
</ul>
</div>
</div>
</div>
</template>
运行结果如图 11-6 所示。

使用axios获取轮播图
本节先使用 element-ui 实现轮播图功能,再使用 axios 获取服务器端真实数据,最终把数据渲染到 HTML 视图,步骤如下。
(1)安装 element-ui。在终端中运行以下命令。
npm i element-ui -S
(2)选择使用方式。使用方式分为全局使用和按需使用,为保证页面的加载速度,选择按需使用的方式,在终端中执行以下命令。
npm install babel-plugin-component -D
(3)修改 .babelrc。 代码如下。
"plugins": [
"transform-vue-jsx",
"transform-runtime",
[
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
]
(4)在 main.js 全局引入轮播图组件,在 home 组件中使用轮播图。
main.js 引用代码,代码如下。
import {carousel,carouselItem} from 'element-ui'
Vue.use(carousel)
Vue.use(carouselItem)
home.vue 轮播图代码(element-ui 默认代码)如下。
<div class="banner">
<el-carousel height="600px">
<el-carousel-item v-for="item in 4":key="item">
<h3 class="small">{{ item }}</h3>
</el-carousel-item>
</el-carousel>
</div>
下面讲解 axios 调用轮播图接口,步骤如下。
(1)安装 axios。在终端执行以下命令。
npm install axios -S
(2)打开 main.js,把 axios 挂载到 Vue 原型对象中,实现数据共享,节省内存空间,代码如下。
import Axios from 'axios'
Vue.prototype.$axios = Axios
此时可以全局使用 axios,打开 home.vue 组件,调用轮播图接口。
请求方式为 get 请求,代码如下。
export default {
data() {
return {
// 1. 声明 banner 属性,用于接收 axios 获取到的数据
banner: []
};
},
methods: {
// 2. 声明 getBanner 方法,把获取到的数据赋值给 banner 属性
getBanner() {
this.$axios.get("http://api.mm2018.com:8095/api/goods/home")
.then(res => {
// console.log(res.data.result)
this.banner = res.data.result[0].contents;
});
}
},
// 3. 在 created 生命周期函数中调用 getBanner 方法
created() {
this.getBanner();
}
};
代码解析如下。
通过 axios 调用接口,data 中的 banner 属性已经获取到图片数据,使用 v-for 指令把 banner 图片渲染到 HTML 页面即可,代码如下。
<div class="banner">
<el-carousel height="600px">
<el-carousel-item v-for="(item, i) in banner" :key="i">
<img :src="item.picUrl">
</el-carousel-item>
</el-carousel>
</div>
运行结果如图 11-7 所示。

首页广告版块数据渲染
本节完成首页数据渲染,banner 下面还有 6 个版块,这 6 个版块的渲染方法有两种。
第一种方法比较简单,和 banner 的获取方法一样,即使用下标的形式获取,例如第一个版块是 res.data.result[0],那么第二个版块的下标为 1,第三个版块的下标为 2,以此类推,这样虽然可以获取到各个版块的数据,但是有些烦琐。
第二种方法是循环遍历整个 res.data.result 数组,根据数组的 type 属性显示不同版块。下面使用第二种方法实现首页数据渲染。
首先获取整个首页版块数据,代码如下。
export default {
data() {
return {
banner: [],
// 1. 声明 allList 属性接收首页所有版块数据
allList: []
};
},
methods: {
getBanner() {
this.$axios.get("http://api.mm2018.com:8095/api/goods/home")
.then(res => {
// console.log(res.data.result)
this.banner = res.data.result[0].contents;
// 2. 把所有版块数据赋值给 allList 数组
this.allList = res.data.result; // 直接将 result 赋值给 allList
})
.catch(error => {
console.error("获取首页数据失败:", error);
// 处理错误,例如显示错误信息
});
}
},
//3.在created生命周期函数中调用getBanner方法
created() {
this.getBanner();
}
};
然后循环遍历 allList 属性,视图层代码如下。
<div v-for="(item,i) in allList" :key="i"></div>
代码解析如下。
此时 div 标签中,不管是什么内容都会遍历 7 次,要根据 type 属性判断是否显示,先把广告模块放到 div 标签中,代码如下。
<div v-for="(item, i) in allList" :key="i">
<div class="content" v-if="item.type == 1">
<div class="ad_product_menu">
<img src="../assets/images/ad_product.jpg" />
</div>
<div class="ad_product_main">
<ul>
<li v-for="(ad, i) in item.contents" :key="i">
<img :src="ad.picUrl" />
</li>
</ul>
</div>
</div>
</div>
运行结果如图 11-8 所示。

因为整个首页中有两个版块的 type 值为 1,所以前端显示两次广告。
首页商家推荐版块数据渲染
本节讲解商家推荐版块,代码如下。
<!--商家推荐的type值为2-->
<div class="content" v-if="item.type == 2">
<div class="index_hot">
<div class="index_hot_menu">{{ item.name }}</div>
<div class="index_hot_main">
<ul>
<!--循环遍历商家推荐产品-->
<li v-for="(hotdetail, i) in item.contents" :key="hotdetail.id">
<img :src="hotdetail.picUrl" />
</li>
</ul>
</div>
</div>
</div>
运行结果如图 11-9 所示。

首页其他版块数据渲染
西瓜子、原味瓜子、五香瓜子这 3 个版块的 type 值都等于 3,因此它们的页面布局也是一样的,代码如下。
<div class="content" v-if="item.type == 3">
<div class="index_hot_menu">{{ item.name }}</div>
<div class="index_productlist">
<div class="index_productlist_left" v-for="(bigImg, i) in item.contents" :key="bigImg.id" v-if="bigImg.type == 2">
<img :src="bigImg.picUrl" :alt="bigImg.altText" v-if="bigImg.picUrl" />
</div>
<div class="index_productlist_right">
<ul>
<li v-for="(smallImg, i) in item.contents" :key="smallImg.id" v-if="smallImg.type == 0">
<img :src="smallImg.picUrl" :alt="smallImg.altText" v-if="smallImg.picUrl" />
</li>
</ul>
</div>
</div>
</div>
运行结果如图 11-10 所示。
