1 city
Home.vue新增一个属性:
<template>
<div>
<home-header :city="city"></home-header>
<home-swiper></home-swiper>
<home-icons></home-icons>
<home-recommend></home-recommend>
<home-weekend></home-weekend>
</div>
</template>
export default {
name: 'Home',
// 声明 局部组件,注册到 Home 组件之后,Home的模板里就能使用它了
components: {
HomeHeader,
HomeSwiper,
HomeIcons,
HomeRecommend,
HomeWeekend
},
data () {
return {
city: ''
}
},
修改对应的 Header 组件:
<script>
export default {
name: 'HomeHeader',
props: {
city: String
}
}
</script>
ajax请求到数据后,要拿到数据内容:
效果:
别急,还有获得的其他字段呢。
2 Swiper.vue
将之前定义的 list 删除,并新增一个 props:
【Swiper.vue】
<template>
<!-- div来包裹整个轮播图,防止图片还未加载出来导致轮播图区域下面的东西提前显示
最后又移动位置了-->
<div class="wrapper">
<!-- 通过v-if来判断是否展示轮播图,如果list数组有数据则展示,否则不展示-->
<swiper :options="swiperOption" v-if="showSwiper">
<swiper-slide v-for="item of list" :key="item.id">
<img class="swiper-img" :src="item.imgUrl" />
</swiper-slide>
<!-- 在swiper标签里面使用了一个不带页码的点号显示,通过slot来实现-->
<div class="swiper-pagination" slot="pagination"></div>
</swiper>
</div>
</template>
<script>
export default {
name: 'HomeSwiper',
props: {
list: Array
},
// 子组件中定义 data 时,必须是个函数 ES6中可省略 function 简化代码
data () {
return {
swiperOption: {
pagination: '.swiper-pagination',
// 轮播图支持循环轮播
loop: true
}
}
},
computed: {
// 判断list数组是否有数据,如果有则返回true,展示轮播图
showSwiper () {
return this.list.length
}
}
}
</script>
<style lang="stylus" scoped>
// <<< 符号表示使用深度选择器,可以选择父级的所有后代元素。
.wrapper >>> .swiper-pagination-bullet-active
// 将轮播图的当前页码的背景颜色设为白色
background: #fff
.wrapper
overflow: hidden
width: 100%
height: 0
// 这里是为了实现固定的宽高比(标准写法)
padding-bottom: 31.25%
background: #eee
.swiper-img
width: 100%
</style>
连带修改,得到 AJAX 接收到的值:
【Home.vue】
data () {
return {
city: '',
// 新增
swiperList: []
}
},
methods: {
getHomeInfo () {
axios.get('/api/index.json')
.then(this.getHomeInfoSuccess)
},
getHomeInfoSuccess (res) {
res = res.data
if (res.ret && res.data) {
const data = res.data
this.city = data.city
// 新增
this.swiperList = data.swiperList
}
}
},
效果:
3 icons
【Icons.vue】修改如下:
<!--在页面上显示一个图标集合,通过Swiper实现分页滑动效果-->
<template>
<div class="icons">
<!-- 在模板中,使用Swiper组件 并将swiperOption作为参数传入 swiperOption中设置了autoplay为false。-->
<swiper :options="swiperOption">
<!-- v-for循环遍历page数组中的每个元素,即每一页中的每个图标-->
<swiper-slide v-for="(page, index) of pages" :key="index">
<!-- 使用div包裹每个图标,并设置其样式。-->
<div class="icon" v-for="item of page" :key="item.id">
<div class='icon-img'>
<img class='icon-img-content' :src='item.imgUrl'/>
</div>
<p class="icon-desc">{{ item.desc }}</p>
</div>
</swiper-slide>
</swiper>
</div>
</template>
<script>
export default {
name: 'HomeIcons',
props: {
list: Array
},
computed: {
pages () {
const pages = []
// 将list数组中的每个元素,按8个为一组进行分页
// 存储在pages数组
this.list.forEach((item, index) => {
const page = Math.floor(index / 8)
if (!pages[page]) {
pages[page] = []
}
pages[page].push(item)
})
return pages
}
}
}
</script>
<!--设置图标的基本样式,包括宽高、位置 图标图片和描述的样式。-->
<style lang="stylus" scoped>
@import '~styles/varibles.styl'
@import '~styles/mixins.styl'
.icons >>> .swiper-container
height: 0
padding-bottom: 50%
.icons
margin-top: .1rem
.icon
position: relative
overflow: hidden
float: left
width: 25%
height: 0
padding-bottom: 25%
.icon-img
position: absolute
top: 0
left: 0
right: 0
bottom: .44rem
box-sizing: border-box
padding: .1rem
.icon-img-content
display: block
margin: 0 auto
height: 100%
.icon-desc
position: absolute
left: 0
right: 0
bottom: 0
height: .44rem
line-height: .44rem
text-align: center
color: $darkTextColor
ellipsis()
</style>
【Home.vue】
<template>
<div>
<home-header :city="city"></home-header>
<home-swiper :list="swiperList"></home-swiper>
<home-icons :list="iconList"></home-icons>
<home-recommend></home-recommend>
<home-weekend></home-weekend>
</div>
</template>
<script>
import HomeHeader from './components/Header'
import HomeSwiper from './components/Swiper'
import HomeIcons from './components/Icons'
import HomeRecommend from './components/Recommend'
import HomeWeekend from './components/Weekend'
import axios from 'axios'
export default {
name: 'Home',
// 声明 局部组件,注册到 Home 组件之后,Home的模板里就能使用它了
components: {
HomeHeader,
HomeSwiper,
HomeIcons,
HomeRecommend,
HomeWeekend
},
data () {
return {
city: '',
swiperList: [],
iconList: []
}
},
methods: {
getHomeInfo () {
axios.get('/api/index.json')
.then(this.getHomeInfoSuccess)
},
getHomeInfoSuccess (res) {
res = res.data
if (res.ret && res.data) {
const data = res.data
this.city = data.city
this.swiperList = data.swiperList
this.iconList = data.iconList
this.recommendList = data.recommendList
this.weekendList = data.weekendList
}
}
},
mounted () {
this.getHomeInfo()
}
}
</script>
<style>
</style>
效果:
4 recommend && weekend
<!--用于在页面上展示商品列表-->
<!--组件接受一个名为list的数组作为参数,每个元素包含商品的标题、描述和图片等信息。
组件会在页面上渲染一个标题“热销推荐”和一个商品列表,
每个商品都包含标题、描述、图片和一个“查看详情”的按钮。
当用户点击某个商品时,组件会跳转到该商品的详情页。-->
<!--代码中的<template>部分定义了组件的HTML结构,包括一个标题和一个商品列表。
商品列表中的每个商品都是一个<router-link>标签,用于实现页面跳转。
:v-for指令用于遍历list数组中的每个元素,并将其绑定到变量item上,
:key指令用于为每个商品设置一个唯一的标识符。-->
<template>
<div>
<div class="title">热销推荐</div>
<ul>
<router-link
tag="li"
class="item border-bottom"
v-for="item of list"
:key="item.id"
:to="'/detail/' + item.id"
>
<img class="item-img" :src="item.imgUrl"/>
<div class="item-info">
<p class="item-title">{{ item.title }}</p>
<p class="item-desc">{{ item.desc }}</p>
<button class="item-button">查看详情</button>
</div>
</router-link>
</ul>
</div>
</template>
<script>
export default {
name: 'HomeRecommend',
props: {
list: Array
}
}
</script>
<!-- 样式都是基于flex布局实现的,以便在不同设备上适应不同的屏幕尺寸。-->
<style lang="stylus" scoped>
@import '~styles/mixins.styl'
// 设置标题的样式
.title
margin-top: .2rem
line-height: .8rem
background: #eee
text-indent: .2rem
// .item样式用于设置商品的样式,包括图片、标题、描述和按钮等。
.item
overflow: hidden
display: flex
height: 1.9rem
.item-img
width: 1.7rem
height: 1.7rem
padding: .1rem
.item-info
flex: 1
padding: .1rem
min-width: 0
.item-title
line-height: .54rem
font-size: .32rem
ellipsis()
.item-desc
line-height: .4rem
color: #ccc
ellipsis()
.item-button
line-height: .44rem
margin-top: .16rem
background: #ff9300
padding: 0 .2rem
border-radius: .06rem
color: #fff
</style>
[Home.vue]
<template>
<div>
<home-header :city="city"></home-header>
<home-swiper :list="swiperList"></home-swiper>
<home-icons :list="iconList"></home-icons>
<home-recommend :list="recommendList"></home-recommend>
<home-weekend></home-weekend>
</div>
</template>
<script>
import HomeHeader from './components/Header'
import HomeSwiper from './components/Swiper'
import HomeIcons from './components/Icons'
import HomeRecommend from './components/Recommend'
import HomeWeekend from './components/Weekend'
import axios from 'axios'
export default {
name: 'Home',
// 声明 局部组件,注册到 Home 组件之后,Home的模板里就能使用它了
components: {
HomeHeader,
HomeSwiper,
HomeIcons,
HomeRecommend,
HomeWeekend
},
data () {
return {
city: '',
swiperList: [],
iconList: [],
recommendList: []
}
},
methods: {
getHomeInfo () {
axios.get('/api/index.json')
.then(this.getHomeInfoSuccess)
},
getHomeInfoSuccess (res) {
res = res.data
if (res.ret && res.data) {
const data = res.data
this.city = data.city
this.swiperList = data.swiperList
this.iconList = data.iconList
this.recommendList = data.recommendList
this.weekendList = data.weekendList
}
}
},
mounted () {
this.getHomeInfo()
}
}
</script>
<style>
</style>
[weekend.vue]
<template>
<div>
<div class="title">周末去哪儿</div>
<ul>
<li
class="item border-bottom"
v-for="item of list"
:key="item.id"
>
<div class="item-img-wrapper">
<img class="item-img" :src="item.imgUrl" />
</div>
<div class="item-info">
<p class="item-title">{{item.title}}</p>
<p class="item-desc">{{item.desc}}</p>
</div>
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'HomeWeekend',
props: {
list: Array
}
}
</script>
<style lang="stylus" scoped>
@import '~styles/mixins.styl'
.title
line-height: .8rem
background: #eee
text-indent: .2rem
.item-img-wrapper
overflow: hidden
height: 0
padding-bottom: 37.09%
.item-img
width: 100%
.item-info
padding: .1rem
.item-title
line-height: .54rem
font-size: .32rem
ellipsis()
.item-desc
line-height: .4rem
color: #ccc
ellipsis()
</style>
效果: