组件化开发一个底部导航栏

在这里插入图片描述

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'
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值