1.整体的文件架构
(1)asset文件夹:里面可以细分成img和css文件夹
-------------img中存放图片,其中对于每个不同组件的图片最好另外再创建一个文件夹
-------------css文件夹里面包含着base.css,base.css在App.vue中导入
<style>
@import "./assets/css/base.css";
</style>
/* 把我们所有标签的内外边距清零 */
* {
margin: 0;
padding: 0;
/* CSS3 盒子模型 */
box-sizing: border-box;
}
/* em 和 i 斜体的文字不倾斜 */
em,
i {
font-style: normal;
}
/* 去掉li 的小圆点 */
li {
list-style: none;
}
img {
/* border 0 照顾低版本浏览器 如果 图片外面包含了链接会有边框的问题 */
border: 0;
/* 取消图片底侧有空白缝隙的问题 */
vertical-align: middle;
}
button {
/* 当我们鼠标经过button 按钮的时候,鼠标变成小手 */
cursor: pointer;
border: 0;
}
a {
color: #666;
text-decoration: none;
}
a:hover {
color: black;
}
button,
input {
/* "\5B8B\4F53" 就是宋体的意思 这样浏览器兼容性比较好 */
font-family: Microsoft YaHei, Heiti SC, tahoma, arial, Hiragino Sans GB, '\5B8B\4F53', sans-serif;
/* 默认有灰色边框需要手动抹掉 */
border: 0;
/* 点击input默认的蓝色边框去掉 */
outline: none;
}
body {
/* CSS3 抗锯齿形 让文字显示的更加清晰 */
-webkit-font-smoothing: antialiased;
background-color: #fff;
font: 12px/1.5 Microsoft YaHei, Heiti SC, tahoma, arial, Hiragino Sans GB, '\5B8B\4F53', sans-serif;
color: #666;
}
.hide,
.none {
display: none;
}
/* 清除浮动 */
.clearfix:before,
.clearfix:after {
content: '';
display: table;
/*转换成表格*/
}
.clearfix:after {
clear: both;
}
.clearfix {
*zoom: 1;
}
(2)components文件夹:存放的是需要公用的一些组件,其中组件名一般都是使用大驼峰的写法,之后在使用的时候是用小写并且用-分割
(3)view文件夹中放的一般是大的整体的视图
2.实现的细节
(1)flex布局:
我们知道当并列书写多个div标签,它们会纵向向下排位,如果我们想将多个div并列成一排,就得借助position,float,或display属性,这便是传统的盒模型做法。
而flex布局则是一种新的布局方案,通过为修改父div的display属性,让父元素成为一个flex容器,从而可以自由的操作容器中子元素(项目)的排列方式。
修改父元素display:flex,你会发现div自动就排列成了一行
flex布局链接:https://www.cnblogs.com/echolun/p/11299460.html
容器属性:
--------------justify-content属性
取值:flex-start(默认) | flex-end | center | space-between | space-around | space-evenly;
用于控制项目在横轴的对齐方式,默认flex-start即左对齐,center 为居中,对应的flex-end为右对齐。
space-between为左右两端对齐,即左右两侧项目都紧贴容器,且项目之间间距相等。
space-around为项目之间间距为左右两侧项目到容器间距的2倍,比较特别的布局,日常使用不太多。
space-evenly为项目之间间距与项目与容器间距相等,相当于除去项目宽度,平均分配了剩余宽度作为项目左右margin。
----------------align-items
center使用最多,自然不会陌生,在纵轴中心位置排列:
项目属性: order flex-grow flex-shrink flex-basis
(2)flex为一个非负数字n:该数字为flex-grow的值,
flex:n;= flex-grow:n;
flex-shrink:1;
flex-basis:0%;
flex为两个非负数字n1,n2: 分别为flex-grow和flex-shrink的值,
flex:n1 n2; = flex-grow:n1;
flex-shrink:n2;
flex-basis:0%;
flex为一个长度或百分比L:视为flex-basis的值,
flex: L; = flex-grow:1;
flex-shrink:1;
flex-basis:L;
flex为一个非负数字n和一个长度或百分比L:分别为flex-grow和flex-basis的值,
flex:n L;= flex-grow:n;
flex-shrink:1;
flex-basis:L;
可以发现,flex-grow和flex-shrink在flex属性中不规定值则为1,flex-basis为0%。
到这里我已经解决我的问题啦,flex:1即为flex-grow:1,经常用作自适应布局,将父容器的display:flex,侧边栏大小固定后,将内容区flex:1,内容区则会自动放大占满剩余空间。
(2) text-align:使用text-align=center属性控制文本的水平方向的对齐方式:左对齐、居中对齐、右对齐,注意这里的文本既可以是文字也同样针对于img,因为img是行内块元素。设置文本垂直方向居中是使用 height = lineheight
vertical-align:设置元素垂直方向的排列
2.功能实现细节
(1)对于点击不同的选项,跳转到不同的页面的实现
----------是在TabBarItem里设置一个path属性,在前端页面传的时候就把path传过来,之后再绑定给点击属性,通过this.$router.push(‘path’)进行代码跳转
<tab-bar-item path="/home">
<img src="./assets/img/tabbar/home.png" slot="item-icon">
<img src="./assets/img/tabbar/home_active.png" slot="item-icon-active">
<div slot='item-text'>首页</div>
</tab-bar-item>
<div class="tab-bar-item" @click="itemClick">
.................
.................
</div>
props: {
path: String
},
methods: {
itemClick () {
this.$router.push(this.path)
}
}
(2)对于激活状态下图片不同的切换
首先是要把两个图片都加载出来的,设置一个isActive属性,通过v-if和v-else来控制显示哪一个图片,
isActive是需要计算出来的,因此是需要写在conputed里
<div v-if='!isActive'><slot name="item-icon"></slot></div>
<div v-else><slot name='item-icon-active'></slot></div>
computed: {
isActive () {
// eslint-disable-next-line eqeqeq
return this.$route.path.indexOf(this.path) !== -1
}
}
这里是通过判断当前激活的路由和本组件的路由是否一致来判断的,indexOf( )函数是用来两个字符串是否一致,没有一致的话则返回 -1
(3)对于组件动态的选择激活文字的颜色设置:
首先是设置activeColor属性:
props: {
path: String,
activeColor: {
type: String,
default: 'red'
}
},
因为这里并不是所有元素都是激活状态,所以需要计算哪一个组件是处于激活状态,是激活状态就把activeColor传给它,这个时候需要绑定样式activeStyle
<div :style='activeStyle'><slot name='item-text'></slot></div>
这里需要注意,并不能把:style直接写到slot上,因为slot之后是要被替换的,不确定哪一个元素属性不能放,所以最后是外面再嵌套一层div,把属性写到div里
computed: {
activeStyle () {
return this.isActive ? { color: this.activeColor } : {}
}
}
这里是通过三目运算符,不同的条件传不同的值
3.文件路径问题:
<tab-bar>
<tab-bar-item path="/home">
<img src="./assets/img/tabbar/home.png" slot="item-icon">
<img src="./assets/img/tabbar/home_active.png" slot="item-icon-active">
<div slot='item-text'>首页</div>
</tab-bar-item>
<tab-bar-item path="/cart">
<img src="./assets/img/tabbar/cart.png" slot="item-icon">
<img src="./assets/img/tabbar/cart_active.png" slot="item-icon-active">
<div slot='item-text'>购物车</div>
</tab-bar-item>
<tab-bar-item path="/category">
<img src="./assets/img/tabbar/category.png" slot="item-icon">
<img src="./assets/img/tabbar/category_active.png" slot="item-icon-active">
<div slot='item-text'>分类</div>
</tab-bar-item>
<tab-bar-item path="/profile">
<img src="./assets/img/tabbar/profile.png" slot="item-icon">
<img src="./assets/img/tabbar/profile_active.png" slot="item-icon-active">
<div slot='item-text'>我的</div>
</tab-bar-item>
</tab-bar>
问题:在导入图片资源或者是组件的时候这里会出现 ./ 等这种,代码不好看而且也容易出错,
这个时候可以给文件夹起一个别名,在node_modules@vue\cli-service\lib\config\base.js中设置
.modules
.add('node_modules')
.add(api.resolve('node_modules'))
.add(resolveLocal('node_modules'))
.end()
.alias
.set('@', api.resolve('src'))
添加
.alias
.set('@', api.resolve('src'))
.set('assets', api.resolve('@/assets'))
.set('components', api.resolve('@/components'))
.set('views', api.resolve('@/views'))
其中set第一个参数是文件夹的别名,api.resolve()里面写的文件夹具体的位置,其中可以使用第一个设置的@来设置下面的文件路径
<tab-bar-item path="/home">
<img src="~assets/img/tabbar/home.png" slot="item-icon">
<img src="~assets/img/tabbar/home_active.png" slot="item-icon-active">
<div slot='item-text'>首页</div>
</tab-bar-item>
@/是可以省略的,这里需要注意的是 像是img里面这种src的引入,是需要在前面加上 ~ 才可以,而像是import这种的就不需要
import TabBar from 'components/tabbar/TabBar.vue'
import TabBarItem from 'components/tabbar/TabBarItem.vue'