目标
前文手写了TabBar的样式和功能,本篇我们用vant库重新实现这些功能。
代码和过程
Vant库引入
安装:
npm i vant
引入组件:
写个button试试:
说明引入成功。
注:这种引入组件的方式是:要用什么就注册什么,比较麻烦。本来用的是插件的方式,但它一直报错,博主想着这个项目的目的只是锻炼一下前端水平,重点不在怎么用vant,于是换了这种方式。
自定义样式初步修改
按文档方式引入组件:
显然我们要自定义图标,把它的代码复制一下,并了解它的功能:
为实现自己的目标,将UI库的代码改一下:
<!-- 用Vant库的代码 -->
<template>
<!-- 双向绑定currentIndex,则不用监听点击 -->
<van-tabbar v-model="currentIndex">
<van-tabbar-item v-for="(item,index) in tabbarData">
<span>{{item.text}}</span>
<template #icon>
<img :src="currentIndex===index?getAssetsUrl(item.item.imageActive):getAssetsUrl(item.image)" />
</template>
</van-tabbar-item>
</van-tabbar>
</template>
<script setup>
import tabbarData from '@/assets/data/tabbarData'
import { getAssetsUrl } from '@/utils/load_assets'
import { ref } from 'vue'
const currentIndex = ref(0)
</script>
效果:
显然有如下问题:
- 主题颜色不对:这里用的是Vant库的默认颜色
- 样式不对:字体图标的img要大
- 没有实现路由跳转
样式修改
修改active颜色
F12一下,看看主题颜色怎么设置的,可以得知是--van-tabbar-item-active-color
设置的主题颜色:
显然本项目的主题颜色是橙色,且一致,所以我们可以直接在common.css中自己设置--van-tabbar-item-active-color
的值。也可以直接修改样式color。这里我们用后者。
前者代码:直接写无法显示,要用!important
覆盖一下。
:root {
--van-tabbar-item-active-color: #ff9854 !important;
}
后者代码:
看一下文档,得知此功能已经被封装(一般都会封装):要放在van-tabbar中。
<van-tabbar v-model="currentIndex" active-color=var(--primary-color)>
icon调大
F12一下看看为什么icon这么小:
是这个.van-tabbar-item__icon img
的height
设置成了20px,这是库写好的样式。我们要修改它。
修改库的样式一般有四种方法:
- 如果用了插槽插入了自己的元素,那么在自己的作用域中直接修改这个元素。
- 全局定义一个变量,覆盖它默认变量的值(:root 里面修改),会影响整个文件的样式
- 局部定义一个变量,覆盖它默认变量的值
- 直接查找对应的子组件选择器,进行修改
:deep
(子组件中元素的选择器) {}
来自修改第三方UI组件库的样式(如element-plus或者vant)
这里我们用第四种方法。
这里直接修改.van-tabbar-item__icon
的样式无效,原因:
scoped
表示这里的css是局部的,只在本文件中生效。
本文件template中没有.van-tabbar-item,若是直接重写.van-tabbar-item的样式不会生效 。
解决方法:
本template中没有.van-tabbar-item,但本文件用的子组件中有。使用:deep()
,令写在其中的子组件 样式生效。
代码:
:deep(.van-tabbar-item) {
height: 50px;
img{
height: 30px;
}
}
效果:
实现路由跳转
再看一下文档:库为我们封装好了路由跳转的功能。
注意to是TabbarItem的属性。
代码:
<van-tabbar-item v-for="(item, index) in tabbarData" :to="item.path">
效果
完全一致。
总代码
修改的文件
将不用库的代码保存到copy中。
tab-bar.vue
用库果然代码简洁多了。
<!-- 用Vant库的代码 -->
<template>
<!-- 双向绑定currentIndex,则不用监听点击 -->
<van-tabbar v-model="currentIndex" active-color=var(--primary-color)>
<van-tabbar-item v-for="(item, index) in tabbarData" :to="item.path">
<span>{{ item.text }}</span>
<template #icon>
<img :src="currentIndex === index ? getAssetsUrl(item.imageActive) : getAssetsUrl(item.image)" />
</template>
</van-tabbar-item>
</van-tabbar>
</template>
<script setup>
import tabbarData from '@/assets/data/tabbarData'
import { getAssetsUrl } from '@/utils/load_assets'
import { ref } from 'vue'
const currentIndex = ref(0)
</script>
<style lang="less" scoped>
:deep(.van-tabbar-item) {
height: 50px;
img {
height: 30px;
}
}
</style>
main.js
import { createApp } from 'vue'
import App from './App.vue'
import "normalize.css"
import './assets/css/index.css'
import router from './router'
import pinia from './store'
// 以下是添加和修改的部分
// 引入vant组件
import { Button } from 'vant';
import { Tabbar, TabbarItem } from 'vant';
// 引入组件样式
import 'vant/lib/index.css';
const app = createApp(App)
app.use(router).use(pinia)
app.use(Button).use(Tabbar).use(TabbarItem)
app.mount('#app')