其二:首页部分开发
布局
先根据设计图(来源于辅助资料)分析下首页的布局
(图片是已实现的首页布局)
先说明,划分页面的方式多种多样,没有绝对的好坏。个人的项目可以以自己的喜好为准,团队的项目以大家都能接受的方案为准。
我将首页分成了两大块,wrap和docker。docker明显是一个固定底部,而且存在于所有页面,可以抽离出来作为一个全局组件。wrap里又可以细分,分成staticpart和nearby,或者position+search+banner+icons+gap和nearby。其实都一样。
组件
Docker
继续根据设计图分析下布局。
黑色的框表示每块图标都是单独的个体,可以只编写一次样式复制3遍。它们在同一排,可以通过flex布局实现。
每块图标都有图标字体和文字描述。简单点,用两个div解决。
<div class="docker">
<div
class="docker__item "
>
<div class="iconfont"></div>
<div class="docker__title">首页</div>
</div>
</div>
.docker{
position:absolute;
display:flex;
.docker__item{
flex:1;
}
}
BEM命名规范
BEM的全程是block__element–modifier
即块中的元素使用下划线表示,如docker__item表示的是上面黑色的框。
块中元素的状态使用–表示,如docker__item–active表示选中状态。
如何设置小于12px的字体
小于12px的字体在chrome浏览器里会被无视。
如果想设置字体大小为10px,可以先将字体大小设置成20px,再缩放0.5倍。
.docker__title {
font-size: 0.2rem;
transform: scale(0.5, 0.5);
transform-origin: center top;
}
Wrap
position
三个span标签,最右侧的可以用绝对定位。
单行文字溢出省略
.ellipsis{
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
search
示范代码和本人的代码都没有使用input框。我这里是用span标签,设置了可输入属性。
非input框设置可输入及placeholder效果
设置contenteditable="true"即可输入。
设置span的默认文字
监听focus事件,判断e.target.innerHTML是否与默认文字相同,是的话便清空。
如果需要获取用户输入的值,则监听blur事件,将e.target.innerHTML赋值给变量即可。
<span
class="search__text"
contenteditable="true"
@focus="handleFocus"
@blur="handleBlur"
>{{ search_text }}
</span>
handleFocus(e) {
if (e.target.innerHTML == this.search_text) {
e.target.innerHTML = ""
}
},
handleBlur(e) {
this.user_input = e.target.innerHTML
console.log(this.user_input)
},
是不是可以通过自定义v-model的方法实现,但是要组件套组件有点麻烦,没试。
icons
每个黑框都是一样的,可以写一遍复制9遍(不要啊)
.icons{
display:flex;
flex-wrap:wrap;
.icons__item{
width:20%;
}
}
使图片居中
.icons__item__img{
width:0.4rem;
height:0.4rem;
display:block;
margin:0 auto;
}
宽高要有值,需要变成块级元素,最后margin:0 auto;
Nearby
深红色框部分为可复用整体,使用flex布局,图片固定大小,绿色部分的文字设置flex:1自动撑开。
.nearby__item{
display:flex;
.item__img{
//设置宽高
}
.item__info{
flex:1;
}
}
溢出部分滚动
给wrap设置
overflow-y:auto;
绝对定位后的box-sizing
Docker和Wrap都使用了绝对定位,也使用了padding挤内边距。但是Docker使用了box-sizing但Wrap没有。
Docker | wrapper | |
---|---|---|
width | 100% | left:0;right:0; |
height | 0.49rem; | top:0;bottom:0.5rem; |
paddiing | 0 0.18rem | 0 0.18rem |
box-sizing | border-box | 不需要 |
得出的结论是宽高有具体数值(百分比、rem、px)的时候,需要使用box-sizing属性保证其宽高固定。
减少重复工作
使用v-for代替复制的部分。Docker、Icons及Nearby都可以将重复的代码抽离出来,不同的数据封装成数组。
抽离前:
<div class="docker">
<div class="docker__item docker__item--active">
<div class="iconfont"></div>
<div class="docker__title">首页</div>
</div>
<div class="docker__item">
<div class="iconfont"></div>
<div class="docker__title">购物车</div>
</div>
<!--......-->
</div>
可以看到,两个docker__item的代码是一样的,不同的只是它们展示数据的部分。将数据部分抽离:
dockerList:[
{
icon:"",
title:"首页"
},
{
icon:"",
title:"购物车"
}
]
使用v-for完成重复的部分,抽离后:
<div class="docker">
<div
class="docker__item "
v-for="item in dockerList"
:key="item.icon"
:class="{ 'docker__item--active': item.isActive }"
>
<div class="iconfont" v-html="item.icon"></div>
<div class="docker__title">{{ item.text }}</div>
</div>
</div>
item.icon是特殊字符,直接使用插值表达式可能会被转义,所以用了v-html