目标: 首页图标区域的布局与逻辑实现
创建index-icons分支
码云上创建一个名为index-icons的分支,然后在项目目录下git pull
将在线的分支拉到本地,git checkout index-icons
转到当前分支进行开发。
准备阶段
- 在components目录下创建Icons.vue组件
- 基本框架: template、script、style
- 设置导出的接口对象
exports default {name: 'HomeIcons'}
- Home.vue组件中引用子组件
- import
- components对象中添加HomeIcons
- 使用子组件
<home-icons></home-icons>
Icons.vue组件开发
-
最外层设置的div用于占位,设置该区域的宽高比,大概是2:1。(因为是一个div,所以可以省略width: 100%)
<style lang="stylus" scoped> .icons overflow: hidden height: 0 padding-bottom: 50% </style>
-
小图标的布局呈现
- 布局
<div class="icon"> </div>
- 样式
.icon float: left width: 25% 这里是父元素宽的25%, padding-bottom: 25% 注意: 高度设置的时候不能使用height: 50%, 因为父盒子的高度是0, 但是这里为什么是25%? 首先: 在css里面,padding-top,padding-bottom,margin-top,margin-bottom取值为百分比的时候,参照的是父元素的宽度。 第一种理解是: 因为icon宽度是父盒子的25%, 而它撑开的那个高度也应该是跟这个宽度一样大,同样是占父元素宽度的25%,这个padding-bottom的百分比的设置是基于父元素的宽。 第二种理解: 父元素的那个50%就可以看成那个撑开的高度, 而他本身的高度应该是父元素的高度的一半,所以是50%的一半。
- 呈现一个icon中的图标与文字
<div class="icon"> <img src="图片地址" /> <p>表述内容</p> </div>
此时会发现图标比盒子大,明显撑开,解决方法:
<div class="icon"> <div class="icon-img"> <img src="图片地址" /> </div> <p>表述内容</p> </div>
.icon overflow: hidden float: left width: 25% padding-bottom: 25% position: relative .icon-img position: absolute 不要忘记子绝父相 top: 0 left: 0 right: 0 // 这里上左右都设置为0是为了保证装图片的这个盒子始终与父盒子一样宽,这里我们不知道具体的高度, 这里是要定位一个放置图标的盒子, 此时图标的大小还是原来的大小。 bottom: .44rem // 这里是为了预留出需要写文字的部分
此时发现:图标太大,而且高度不是50%,解决方法: 先给img添加一个icon-img-content的类名,
.icon-img position: absolute top: 0 left: 0 right: 0 bottom: .44rem .icon-img-content height: 100%
解决高度超出50%的问题:.icon添加一个
height: 0
的样式
实现图标的水平居中显示:.icon-img position: absolute top: 0 left: 0 right: 0 bottom: .44rem box-sizing: border-box // IE盒子模型 2种盒模型:https://blog.csdn.net/zwkkkk1/article/details/79678177 box-sizing的默认属性是content-box padding: .1rem .icon-img-content display: block //默认情况下,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 这里使用的是网站主题文字颜色变量,该变量的自定义方法与$bgColor一样。
- 手动呈现8个图标
-
图标区域的逻辑实现:
- 需求说明: 首页的一个页面上呈现的是8个图标,刚有9个图标的时候,希望能够实现在两页上的轮播呈现。 ---- 借用swiper
<swiper> <swiper-slide> <div class="icon"> <div class="icon-img"> <img class="icon-img-content" src="图片网址" /> </div> <p class="icon-desc"></p> </div> </swiper-slide> <swiper-slide> <div class="icon"> <div class="icon-img"> <img class="icon-img-content" src="图片网址" /> </div> <p class="icon-desc"></p> </div> </swiper-slide> </swiper>
一个小问题: 只有在上部拖动的时候才会出现轮播的效果,下面那一部分无效,原因是:swiper-container的高度只有图标的高度,但是icons的高度很高,所以内容上并没有跟它有相同的高度。解决方法:
将.icons下面的样式全部往前提一个tab, 然后重写.icons的样式:.icons >>> .swiper-container <!--overflow: hidden 这个样式可以去掉, 因为.swiper-container自带了overflow: hidden--> height: 0 padding-bottom: 50%
- 设置data函数的返回数据对象,实现图标的循环呈现
<script> export default { data () { return { iconList: [{ id: '0001', imgUrl: '图片地址', desc: '图标描述' },{ id: '0002', imgUrl: '图片地址', desc: '图标描述' },{ id: '0003', imgUrl: '图片地址', desc: '图标描述' },{ id: '0004', imgUrl: '图片地址', desc: '图标描述' }] } } } </script>
要写9个图标的信息数据,这里的数据代码是很冗余的,以后会用ajax获取到的数据。此时,就可以使用循环的形式来写:
<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>
但是,以上的写法会将第9个图标隐藏,无法实现轮播显示—使用计算属性来实现。在data的后面定义一个计算属性(自带缓存机制,且语法简单):
<script> export default { data () { return { iconList: [......] } }, 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>
循环代码的修改:
<swiper> <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>
一点优化: 当图标下方的文字描述部分比较多的时候,多出的部分呈现三个点的形式,使用css样式来实现。在.icon-desc下添加
overflow: hidden whit-space: nowrap text-overflow: ellipsis
会发现,可能很多地方都能用到这个3个css样式,所以可以借助stylus提供的Mixins将它封装起来—封装方法:在styles目录下创建mixins.styl文件,在该文件中定义一个ellipsis方法,注意与小括号中间不要有空格:
ellipsis() overflow: hidden whit-space: nowrap text-overflow: ellipsis
使用的时候,先在style标签下
@import '~styles/mixins.styl'
,然后在.icon-desc中直接使用:ellipsis()
代码提交
lipsis方法,注意与小括号中间不要有空格:
css ellipsis() overflow: hidden whit-space: nowrap text-overflow: ellipsis
使用的时候,先在style标签下@import '~styles/mixins.styl'
,然后在.icon-desc中直接使用:ellipsis()