想利用暑假时间好好学习一下vue,会记录每一天的学习内容。
今天是学习vue的第13
天!
起起伏伏乃人生常态,继续加油~
这一篇比较适合新手小白看!有vue项目经验的可以不用看了,挺基础的
学习内容
TabBar
1. TabBar实现思路
- 如果在下方有一个单独的
TabBar
组件,如何封装- 自定义
TabBar
组件,在App中使用 - 让
TabBar
处于底部,并且设置相关样式
- 自定义
TabBar
中显示的内容由外界决定- 定义插槽
- flex布局平分
TabBar
- 自定义
TabBarItem
,可以传入图片和文字- 定义
TabBarItem
,并且定义两个插槽:图片、文字 - 给两个插槽外层包装
div
,用于设置样式 - 填充插槽,实现底部
TabBar
的效果
- 定义
- 传入 高亮图片
- 定义另外一个插槽,插入
item-active-icon
的数据 - 定义一个变量
isActive
,通过v-if
来决定是否显示高亮的item-icon
- 定义另外一个插槽,插入
TabBarItem
绑定路由数据- 安装路由,
vue-router
- 完成
router/index.js
的内容,创建对应的组件 main.js
中注册router
App
中加入<router-view>
组件
- 安装路由,
- 点击
item
跳转到对应路由,并且动态决定isActive
- 监听
item
的点击,通过this.$router.push()
替换路由路径 - 通过
this.$router.path.includes(this.path)
来判断是否是active
- 监听
- 动态计算active样式
- 封装新的计算属性:
this.isActive ? {'color': 'red'}: {}
- 封装新的计算属性:
2. 具体实现
基本结构搭建
用vue-cli建一个新项目
vue create tabbar
在components
文件夹里建一个tabbar
文件夹,在里面建TabBar.vue
文件
(这里建文件夹是为了便于管理)
为了能显示,要在App.vue
中引入并注册
目前效果:
TabBar和TabBarItem组件封装
在assets
文件夹中放一些资源,创建img
文件夹、css
文件夹
放一些icon
图片也一起放进来
⚠️:虽然这样实现看起来没什么问题,但是目前我们的TabBar
和TabBarItem
耦合度太高了,我们的 TabBar.vue
文件中应该是只关心TabBar
的逻辑,而里面的TabBarItem
的标签、样式,不应该在这个文件中去实现
在tabbar
文件夹中新建一个TabBarItem.vue
文件
TabBarItem
相关的模版和样式转移过来
直接在App
组件中使用tab-bar-item
组件,记得注册和导入
这里TabBarItem
组件的模板暂时写死了,后面会改成能动态修改的
目前效果:
虽然看起来还不如刚才,但是结构清晰了很多
TabBarItem
组件中的图片和文字都应该由外界决定,不能写死,所以这里替换成两个具名插槽
App
组件中:<template>
中的内容都会被传入对应名字的插槽
目前效果:
给TabBarItem传入active图片
为了显示活跃状态的图片,再设置一个插槽
(这里因为我用的都是png格式的图片,不是很方便通过样式改变颜色)
这样会出现两个图标,所以还要加个判断
文字颜色也要变
⚠️:
<slot :class="{active: !isActive}" name="item-text"></slot>
.active {
color: #fe6b57;
}
这样是不会生效的,因为插槽部分会被替换掉,替换的元素上面没有active
类
<div :class="{active: isActive}"> <slot name="item-text"></slot></div>
外面再套一层 div
就ok
v-if
为什么成功渲染了,不是很清楚,所以保险起见还是都套一层div
<div class="tab-bar-item">
<div v-if="!isActive">
<slot name="item-icon"></slot>
</div>
<div v-else>
<slot name="item-icon-active"></slot>
</div>
<div :class="{ active: isActive }">
<slot name="item-text"></slot>
</div>
</div>
TabBarItem和路由结合
我们希望点击TabBar
的每个item
都能跳转到相应的页面,这里就要用到路由了
安装vue-router
npm install vue-router --save
在src
文件夹中建一个router
文件夹,在里面建index.js
文件来配置vue-router
前两天刚学的,就不多说啦
main.js
中导入,挂载路由实例
接下来要配置映射关系,我们需要配置4个映射关系,所以要先创建这4个组件
但是对于这种大的页面,一般不在components
里面创建了,components
放复用性比较高的组件
在src
文件夹下新建一个views
文件夹
配置路由映射关系
也采用了路由的懒加载
我们希望在点击TabBarItem
的时候完成切换,所以要监听它们的click
事件
不要在App
组件的<tab-bar-item>
监听,不然要监听4个,直接在TabBarItem
组件内部监听就好
<div class="tab-bar-item" @click="itemClick">
methods: {
itemClick() {
}
}
在点击事件发生的时候我们要执行的应该是路由的跳转,用到$router.push()
或$router.replace()
,但这里的路径也不能写死,所以定义一个props
,从App
组件中将路径传进TabBarItem
组件
(父子组件通信,父App
,子TabBarItem
)
(这里不用动态绑定,写固定的)
然后因为哈希模式的路径会让我获取不到正确的pathname
,所以我火速去改成history
模式了
(有很多别的方法也可以使其不报错,这里就先用这个了)
(history
模式个人也更喜欢)
const router = new VueRouter({
routes,
mode: 'history'
})
现在点击下方的TabBarItem
已经能够跳转对应的路由,但是什么都没有显示出来
因为,我们没有用<router-view>
!
现在已经能成功跳转并显示了
TabBarItem颜色动态控制
接下来解决TabBarItem
颜色问题
这里用计算属性解决了
$route.path
拿到当前活跃的路由的路径
这里判断用了includes
是因为后面可能还会有嵌套路由,如果直接用相等,不合适
成功了
还有一个需求,就是文字的颜色,希望能由外界决定,而不是被我们直接写死
但是这个activeColor
在css里拿不到,所以这里要动态绑定style
了
现在传的颜色是blue
结束啦