(08)首页开发——③ 图标区域组件 | Vue.js 项目实战: 移动端“旅游网站”开发1 需求 首页的“图标分类区域
转载请注明出处,未经同意,不可修改文章内容。
🔥🔥🔥“前端一万小时”两大明星专栏——“从零基础到轻松就业”、“前端面试刷题”,已于本月大改版,合二为一,干货满满,欢迎点击公众号菜单栏各模块了解。
1 需求
首页的“图标分类区域”一页展示 8 个图标,超过 8 个切换至第二页展示。
2 图标区域布局
1️⃣在 home 下的 components 文件夹中,新建“图标区域组件” Icons.vue
:
<template>
<div> <!-- 1️⃣-②:添加文字内容。 -->
Icons
</div>
</template>
<script>
export default {
name: 'HomeIcons' // 1️⃣-①:给组件命名为 HomeIcons;
}
</script>
<style lang="stylus" scoped>
</style>
2️⃣打开 Home.vue
,在首页使用 Icons.vue
组件:
<template>
<div>
<home-header></home-header>
<home-swiper></home-swiper>
<home-icons></home-icons> <!-- 2️⃣-③:使用 Icons 组件。 -->
</div>
</template>
<script>
import HomeHeader from './components/Header'
import HomeSwiper from './components/Swiper'
import HomeIcons from './components/Icons' // 2️⃣-①:引入 Icons.vue;
export default {
name: 'Home',
components: {
HomeHeader,
HomeSwiper,
HomeIcons // 2️⃣-②:在 Home.vue 中注册 Icons 组件;
}
}
</script>
<style>
</style>
保存后,返回页面查看效果,“Icons”出现在首页轮播下方,页面无报错:
3️⃣根据设计稿可以知道,图标区域的宽高比大致为 2:1,每个图标所占区域宽、高为整个图标区域宽的 25%,且每个图标下方有一个文字描述区域:
<template>
<div class="icons"> <!-- 3️⃣-①:最外层 div 类名为 icons; -->
<div class="icon"> <!-- 3️⃣-②:添加一个小的图标区域,类名为 icon,里面包含一个 div
和一个 p 标签; -->
<div class="icon-img"> <!-- 3️⃣-③:div 类名为 icon-img,里边是一个
图标图片的 img 标签; -->
<!-- 3️⃣-④:给图标图片添加类名 icon-img-content; -->
<img class="icon-img-content" src="https://qdywxs.github.io/travel-images/iconList01.png">
</div>
<p class="icon-desc">景点门票</p> <!-- 3️⃣-⑤:p 标签类名为 icon-desc,显示图标的
描述文字; -->
</div>
</div>
</template>
<script>
export default {
name: 'HomeIcons'
}
</script>
<style lang="stylus" scoped>
.icons /* 3️⃣-⑥:设置 .icons 区域的高度为宽度的 50%(即:设置 .icons 宽高比为 2:1); */
overflow: hidden
height: 0
padding-bottom: 50%
background: #ccc /* ❗️设置背景色为灰色,方便观察。 */
.icon
position: relative /*
3️⃣-⑥:给 .icon 添加定位为 relative,
让 .icon-img 相对于它绝对定位;
*/
overflow: hidden /* 3️⃣-④:设置每个 .icon 的宽、高为父元素宽的 25%,左浮动; */
float: left
width: 25%
height: 0
padding-bottom: 25%
background: red /* ❗️设置背景色为红色,方便观察。 */
.icon-img /*
3️⃣-⑤:让 .icon-img 绝对定位,设置 bottom 为 0.44rem,
给 p 标签的内容预留位置;
*/
position: absolute
top: 0
left: 0
right: 0
bottom: .44rem
box-sizing: border-box /*
3️⃣-⑦:在 .icon-img 上设置 box-sizing 为 border-box,
padding 为 0.1 rem 增加图标间距;
*/
padding: .1rem
background: blue /* ❗️设置背景色为蓝色,方便观察。 */
.icon-img-content /* 3️⃣-⑧:设置图片 display 为 block,在父元素内居中,高度为 100%; */
display: block
margin: 0 auto
height: 100%
.icon-desc /*
3️⃣-⑨:在 .icon-img 同级的位置,编写 .icon-desc 的样式,
设置 .icon-desc 绝对定位,高度和行高为 0.44rem,内容居中显示,字体颜色为 #333。
*/
position: absolute
left: 0
right: 0
bottom: 0
height: .44rem
line-height: .44rem
text-align: center
color: #333
</style>
保存后,返回页面查看效果:
这里的“景点门票”文字颜色,在页面的其他地方,可能也会使用到,所以我们可以给这个颜色设置一个变量。
4️⃣打开 src 下 assets 中 styles 里的 varibles.styl
:
$bgColor = #00bcd4
$darkTextColor = #333 /* 4️⃣-①:定义颜色变量 $darkTextColor; */
4️⃣-②:打开 home 下的 components 里的 Icons.vue
;
<template>
<div class="icons">
<!-- ❗️复制 .icon,在首页展示 8 个图标查看效果。 -->
<div class="icon">
<div class="icon-img">
<img class="icon-img-content" src="https://qdywxs.github.io/travel-images/iconList01.png">
</div>
<p class="icon-desc">景点门票</p>
</div>
<div class="icon">
<div class="icon-img">
<img class="icon-img-content" src="https://qdywxs.github.io/travel-images/iconList01.png">
</div>
<p class="icon-desc">景点门票</p>
</div>
<div class="icon">
<div class="icon-img">
<img class="icon-img-content" src="https://qdywxs.github.io/travel-images/iconList01.png">
</div>
<p class="icon-desc">景点门票</p>
</div>
<div class="icon">
<div class="icon-img">
<img class="icon-img-content" src="https://qdywxs.github.io/travel-images/iconList01.png">
</div>
<p class="icon-desc">景点门票</p>
</div>
<div class="icon">
<div class="icon-img">
<img class="icon-img-content" src="https://qdywxs.github.io/travel-images/iconList01.png">
</div>
<p class="icon-desc">景点门票</p>
</div>
<div class="icon">
<div class="icon-img">
<img class="icon-img-content" src="https://qdywxs.github.io/travel-images/iconList01.png">
</div>
<p class="icon-desc">景点门票</p>
</div>
<div class="icon">
<div class="icon-img">
<img class="icon-img-content" src="https://qdywxs.github.io/travel-images/iconList01.png">
</div>
<p class="icon-desc">景点门票</p>
</div>
<div class="icon">
<div class="icon-img">
<img class="icon-img-content" src="https://qdywxs.github.io/travel-images/iconList01.png">
</div>
<p class="icon-desc">景点门票</p>
</div>
</div>
</template>
<script>
export default {
name: 'HomeIcons'
}
</script>
<style lang="stylus" scoped>
/* 4️⃣-③:引入 varibles.styl; */
@import '~styles/varibles.styl'
.icons
overflow: hidden
height: 0
padding-bottom: 50%
/* background: #ccc ❗️删除无用代码; */
.icon
position: relative
overflow: hidden
float: left
width: 25%
height: 0
padding-bottom: 25%
/* background: red ❗️删除无用代码; */
.icon-img
position: absolute
top: 0
left: 0
right: 0
bottom: .44rem
box-sizing: border-box
padding: .1rem
/* background: blue ❗️删除无用代码。 */
.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 /* 4️⃣-④:使用颜色变量。 */
</style>
保存后,返回页面查看效果:
3 图标区域逻辑
图标区域的图标较多、数量不定。很明显的,这一块儿的代码也是通过循环数据来展示的。
❓那么,当图标超过 8 个时,如何让第一页仅显示八个,超出的内容展示到第二页呢? 答:这里,我们也可以用轮播来处理。
5️⃣打开 Icons.vue
:
<template>
<div class="icons">
<swiper> <!-- 5️⃣-⑥:添加 swiper 标签; -->
<swiper-slide> <!-- 5️⃣-⑦:使用 swiper-slide 包裹每个图标区域。 -->
<!-- 5️⃣-①:保留一个图标; -->
<!-- 5️⃣-③:循环 iconList 数组,绑定 key 值为循环项的 id; -->
<div class="icon" v-for="item of iconList" :key="item.id">
<div class="icon-img">
<img class="icon-img-content" :src="item.imgUrl"> <!-- 5️⃣-④:绑定图标图片
的地址为循环项的 imgUrl;
-->
</div>
<p class="icon-desc">{{item.desc}}</p> <!-- 5️⃣-⑤:渲染图标描述信息为循环项
的 desc; -->
</div>
</swiper-slide>
</swiper>
</div>
</template>
<script>
export default {
name: 'HomeIcons',
data () {
return {
iconList: [{ /*
5️⃣-②:在 data 函数中返回数据 iconList 数组,里面包含 9 个图标的数据,
包括 id、图标图片地址和图标描述信息;
*/
id: '0001',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList01.png',
desc: '景点门票'
}, {
id: '0002',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList02.png',
desc: '滑雪季'
}, {
id: '0003',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList03.png',
desc: '泡温泉'
}, {
id: '0004',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList04.png',
desc: '动植园'
}, {
id: '0005',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList05.png',
desc: '游乐园'
}, {
id: '0006',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList06.png',
desc: '必游榜单'
}, {
id: '0007',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList07.png',
desc: '演出'
}, {
id: '0008',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList08.png',
desc: '城市观光'
}, {
id: '0009',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList09.png',
desc: '一日游'
}]
}
}
}
</script>
<style lang="stylus" scoped>
@import '~styles/varibles.styl'
.icons
overflow: hidden
height: 0
padding-bottom: 50%
.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
</style>
❌保存后,返回页面发现轮播没问题,数据也正确渲染。但,第九个图标被隐藏了,它的位置被继续排列在了下方区域,没有显示在第二页:
❓如何让第九个图标正确显示到轮播的第二页呢? 答:我们可以利用计算属性。
6️⃣打开 home 中的 components 里的 Icons.vue
:
<template>
<div class="icons">
<swiper>
<swiper-slide>
<div class="icon" v-for="item of iconList" :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',
data () {
return {
iconList: [{
id: '0001',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList01.png',
desc: '景点门票'
}, {
id: '0002',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList02.png',
desc: '滑雪季'
}, {
id: '0003',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList03.png',
desc: '泡温泉'
}, {
id: '0004',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList04.png',
desc: '动植园'
}, {
id: '0005',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList05.png',
desc: '游乐园'
}, {
id: '0006',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList06.png',
desc: '必游榜单'
}, {
id: '0007',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList07.png',
desc: '演出'
}, {
id: '0008',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList08.png',
desc: '城市观光'
}, {
id: '0009',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList09.png',
desc: '一日游'
}]
}
},
computed: { /* 6️⃣-①:在 data 后新增 computed,定义一个 pages 计算属性; */
pages () {
const pages = [] /* 6️⃣-②:定义轮播页数为 pages,初始化为一个空数组; */
this.iconList.forEach((item, index) => { /*
6️⃣-③:循环 iconList 里的每一项数据,
接收循环项 item 和下标 index 两个参数;
*/
const page = Math.floor(index / 8) /*
6️⃣-④:定义 page 变量,指当前下标对应的
数据项展示在轮播的第几页(即轮播的页码);
6️⃣-⑤:用下标除以 8 来限制一页为八个数据,
通过 Math.floor 取得当前数据展示的页数
page(若当前数据下标为 3,3/8 小于 1,向下取整,
则 page 为 0,即展示在第一页;若当前数据下标
为 8,8/8 等于 1,向下取整,则 page 为 1,
即展示在第二页);
*/
if(!pages[page]) { /*
6️⃣-⑥:如果 pages 下的 page 不存在,则让 pages[page]
等于一个空数组(即初始化 pages[page] 为一个空数组);
*/
pages[page] = []
}
pages[page].push(item) /*
6️⃣-⑦:把循环项放入 pages[page] 中(若当前循环项下标为 3,
则 page 为 0,当前循环项放入轮播第一页;若当前循环项下标为 8,
则 page 为 1,当前循环项放入轮播第二页);
*/
})
return pages /* 6️⃣-⑧:循环完毕后,返回 pages。 */
}
}
}
</script>
<style lang="stylus" scoped>
@import '~styles/varibles.styl'
.icons
overflow: hidden
height: 0
padding-bottom: 50%
.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
</style>
❓当我们写完计算属性 pages 后,如何能查看数据是否正确呢?
答:安装“Chrome 网上应用店”的 Vue.js devTools
插件,可以友好的调试 Vue 项目,或查看 Vue 中组件的数据等。
打开 Chrome 网上应用店,搜索 vue devtools
,找到提供方为 https://vuejs.org
的插件,点击 “添加至 Chrome” 即可安装插件:
安装插件后,在控制台找到插件并打开(未找到插件,可关闭浏览器重新打开项目页面):
这里面,可以看到我们页面上所有的组件。点击 HomeIcons(即 Icons.vue
),可以在下方看见其中的数据。
比如,iconList 数组中有 9 个数据。 computed
里有一个 pages,它是一个二维数组(即数组里的元素也是数组)。pages 里的第一个数组有八个数据,即展示在第一页的数据;第二个数组有一个数据,即展示在第二页的数据:
(⚠️computed 里的逻辑,就是让我们把 iconList 里的数据,拆分为 pages 这样的二维数组,让“页码 page”和数据项进行关联。)
7️⃣在对 iconList 中的数据进行处理后,我们成功获取到图标轮播有几页,接下来就可以对数据进行渲染:
<template>
<div class="icons">
<swiper>
<!-- 7️⃣-①:在 swiper-slide 上循环 pages,获取轮播有几页; -->
<swiper-slide v-for="(page, index) of pages" :key="index">
<!-- 7️⃣-②:icon 中改为对 page 进行循环,即循环每一页上的数据。 -->
<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',
data () {
return {
iconList: [{
id: '0001',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList01.png',
desc: '景点门票'
}, {
id: '0002',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList02.png',
desc: '滑雪季'
}, {
id: '0003',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList03.png',
desc: '泡温泉'
}, {
id: '0004',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList04.png',
desc: '动植园'
}, {
id: '0005',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList05.png',
desc: '游乐园'
}, {
id: '0006',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList06.png',
desc: '必游榜单'
}, {
id: '0007',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList07.png',
desc: '演出'
}, {
id: '0008',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList08.png',
desc: '城市观光'
}, {
id: '0009',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList09.png',
desc: '一日游'
}]
}
},
computed: {
pages () {
const pages = []
this.iconList.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'
.icons
overflow: hidden
height: 0
padding-bottom: 50%
.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
</style>
❌保存后,返回页面查看,图标区域超过 8 个图标的部分,放入了轮播的第二页。但,这里的轮播是不需要自动播放的:
8️⃣我们通过vue-awesome-swiper 插件的一个属性,关闭图标区域轮播的自动播放:
<template>
<div class="icons">
<swiper :options="swiperOption"> <!-- 8️⃣-①:在 swiper 标签绑定 options; -->
<swiper-slide v-for="(page, index) of pages" :key="index">
<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',
data () {
return {
swiperOption: {
autoplay: false /*
8️⃣-②:在 data 中定义 swiperOption,设定 autoplay 为 false,
关闭轮播的自动播放。
*/
},
iconList: [{
id: '0001',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList01.png',
desc: '景点门票'
}, {
id: '0002',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList02.png',
desc: '滑雪季'
}, {
id: '0003',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList03.png',
desc: '泡温泉'
}, {
id: '0004',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList04.png',
desc: '动植园'
}, {
id: '0005',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList05.png',
desc: '游乐园'
}, {
id: '0006',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList06.png',
desc: '必游榜单'
}, {
id: '0007',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList07.png',
desc: '演出'
}, {
id: '0008',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList08.png',
desc: '城市观光'
}, {
id: '0009',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList09.png',
desc: '一日游'
}]
}
},
computed: {
pages () {
const pages = []
this.iconList.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'
.icons
overflow: hidden
height: 0
padding-bottom: 50%
.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
</style>
保存后,返回页面查看,轮播不再自动播放,图标区域显示正常:
❓当 iconList 数据少于八个时,图标区域能否正常显示呢? 答:我们可以保留 iconList 中的四个数据,进行测试。
<template>
<div class="icons">
<swiper :options="swiperOption">
<swiper-slide v-for="(page, index) of pages" :key="index">
<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',
data () {
return {
swiperOption: {
autoplay: false
},
iconList: [{
id: '0001',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList01.png',
desc: '景点门票'
}, {
id: '0002',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList02.png',
desc: '滑雪季'
}, {
id: '0003',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList03.png',
desc: '泡温泉'
}, {
id: '0004',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList04.png',
desc: '动植园'
}] /* ❗️保留 4 个数据,进行测试。 */
}
},
computed: {
pages () {
const pages = []
this.iconList.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'
.icons
overflow: hidden
height: 0
padding-bottom: 50%
.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
</style>
保存后,返回页面可以看到,当数据少于 8 个时,数据渲染没有问题。但,整个 .icons
区域中,有图标的区域才有轮播,在下半部分拖动时,则没有效果:
9️⃣通过上面的视频可以知道,能拖动的区域就是 .swiper-container
这个轮播区:
<template>
<div class="icons">
<swiper :options="swiperOption">
<swiper-slide v-for="(page, index) of pages" :key="index">
<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',
data () {
return {
swiperOption: {
autoplay: false
},
iconList: [{
id: '0001',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList01.png',
desc: '景点门票'
}, {
id: '0002',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList02.png',
desc: '滑雪季'
}, {
id: '0003',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList03.png',
desc: '泡温泉'
}, {
id: '0004',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList04.png',
desc: '动植园'
}]
}
},
computed: {
pages () {
const pages = []
this.iconList.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'
.icons >>> .swiper-container /*
9️⃣-①:由于 .swiper-container 是第三方插件的样式,所以这里
通过深度作用选择器,设置它的宽高比为整个图标区域的宽高比(swiper
的样式自带 overflow: hidden,所以这里省略);
*/
height: 0
padding-bottom: 50%
.icons /* 9️⃣-②:给图标区域增加 0.1rem 的 margin-top,调整图标区域间隙。 */
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
</style>
保存后,返回页面查看效果,整个图标区域基本没有问题了:
4 细节优化
当图标下方的描述文字过多时,信息显示不全。而当信息显示不全时,页面也没有明显的指示:
在这里,就可以给“溢出的文字加点”。在我们的项目中,其他部分也可能需要用到,所以可以直接对它进行封装,在需要用到时,再进行引用。
🔟在 src 下 assets 中的 styles 里新建一个 mixins.styl
的文件:
🔟-①:在 mixins.styl
中,定义一个 ellipsis
方法;
ellipsis() /* ❗️ellipsis 方法不需要参数,只需要写入“文字溢出加点”的三行代码即可。 */
overflow: hidden
white-space: nowrap
text-overflow: ellipsis
🔟-②:返回 home 下 components 里的 Icons.vue
,使用 ellipsis
方法;
<template>
<div class="icons">
<swiper :options="swiperOption">
<swiper-slide v-for="(page, index) of pages" :key="index">
<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',
data () {
return {
swiperOption: {
autoplay: false
},
iconList: [{
id: '0001',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList01.png',
desc: '景点门票'
}, {
id: '0002',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList02.png',
desc: '滑雪季'
}, {
id: '0003',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList03.png',
desc: '泡温泉'
}, {
id: '0004',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList04.png',
desc: '动植园'
}, {
id: '0005',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList05.png',
desc: '游乐园'
}, {
id: '0006',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList06.png',
desc: '必游榜单'
}, {
id: '0007',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList07.png',
desc: '演出'
}, {
id: '0008',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList08.png',
desc: '城市观光'
}, {
id: '0009',
imgUrl: 'https://qdywxs.github.io/travel-images/iconList09.png',
desc: '一日游'
}] /* ❗️恢复为原数据。 */
}
},
computed: {
pages () {
const pages = []
this.iconList.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'
/* 🔟-③:从 styles 下引入 mixins.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() /* 🔟-④:在 .icon-desc 调用 ellipsis 方法。 */
</style>
保存后,返回页面查看效果,当文字超出时,已经显示为“点”:
以上,我们就完成了“图标区域组件” Icons.vue
。
🏆本篇总结:
- 通过拆分 iconList 中的数据为二维数组,实现图标数据分页展示;
- “文字溢出加点”多处会用到时,单独封装为方法,需要时再调用。
祝好,qdywxs ♥ you!
转载自:https://juejin.cn/post/7399952146254020659