Uniapp + Vite + Vue3 + uView + Pinia 实现自定义底部 Tabbar(最新保姆级教程)
- 1、效果展示
- 2、环境准备
-
- [2.1 新建 uniapp 项目](#2.1 新建 uniapp 项目)
- [2.2. 安装 uView](#2.2. 安装 uView)
- [2.3 安装 pinia](#2.3 安装 pinia)
- [3. 配置环境](#3. 配置环境)
- [4. 创建目录结构](#4. 创建目录结构)
- [5、编写 pages.json 页面路由](#5、编写 pages.json 页面路由)
- [6、编写 tabbar.js 状态数据](#6、编写 tabbar.js 状态数据)
- [7、编写 tabbar.vue 组件](#7、编写 tabbar.vue 组件)
1、效果展示
2、环境准备
2.1 新建 uniapp 项目
新建普通 Vue3 项目即可
2.2. 安装 uView
官网
c
https://uiadmin.net/uview-plus/components/install.html
安装
c
npm install uview-plus
2.3 安装 pinia
官网
c
https://pinia.vuejs.org/zh/getting-started.html
安装
c
npm install pinia
3. 配置环境
- main.js
js
import App from './App'
// #ifndef VUE3
import Vue from 'vue'
import './uni.promisify.adaptor'
Vue.config.productionTip = false
App.mpType = 'app'
const app = new Vue({
...App
})
// #endif
import uviewPlus, {
setConfig
} from 'uview-plus'
// #ifdef VUE3
import {
createSSRApp
} from 'vue'
import { createPinia } from 'pinia'
export function createApp() {
const pinia = createPinia()
const app = createSSRApp(App);
app.use(pinia);
app.use(uviewPlus);
// 需要在app.use(uview-plus)之后执行
setConfig({
// 修改$u.config对象的属性
config: {
// 修改默认单位为rpx,相当于执行 uni.$u.config.unit = 'rpx'
unit: 'px'
},
// 修改$u.props对象的属性
props: {
// 修改radio组件的size参数的默认值,相当于执行 uni.$u.props.radio.size = 30
radio: {
// size: 20
}
// 其他组件属性配置
// ......
}
});
return {
app
}
}
// #endif
- App.vue
js
<script>
export default {
onLaunch: function() {
console.log('App Launch')
// 隐藏原生tarbar (这里因为用自定义tarbar跳转时闪白屏,所以这里用一种特殊的方式)
uni.hideTabBar()
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
}
}
</script>
<style lang="scss">
/* 注意要写在第一行,同时给style标签加入lang="scss"属性 */
@import "uview-plus/index.scss";
</style>
- vite.config.js(如果没有可以新建,主要用于配置@路径识别)
c
import { defineConfig } from "vite";
import uni from "@dcloudio/vite-plugin-uni";
import { resolve } from "path";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [uni()],
resolve: {
// 路径别名
alias: {
"@": resolve(__dirname, "./"),
},
},
});
4. 创建目录结构
5、编写 pages.json 页面路由
json
{
// uView 配置
"easycom": {
"autoscan": true,
// 注意一定要放在custom里,否则无效,https://ask.dcloud.net.cn/question/131175
"custom": {
"^u--(.*)": "uview-plus/components/u-$1/u-$1.vue",
"^up-(.*)": "uview-plus/components/u-$1/u-$1.vue",
"^u-([^-].*)": "uview-plus/components/u-$1/u-$1.vue"
}
},
"pages": [
{
"path": "pages/src/home/home",
"style": {
"navigationBarTitleText": "云尚社区"
}
},
{
"path": "pages/src/login/login",
"style": {
"navigationBarTitleText": "登录"
}
},
{
"path": "pages/src/community/community",
"style": {
"navigationBarTitleText": "社区"
}
},
{
"path": "pages/src/lookHous/lookHous",
"style": {
"navigationBarTitleText": "租房"
}
},
{
"path": "pages/src/message/message",
"style": {
"navigationBarTitleText": "消息"
}
},
{
"path": "pages/src/user/user",
"style": {
"navigationBarTitleText": "我的"
}
}
],
// 这里只配置路径
"tabBar": {
"list": [{
"pagePath": "pages/src/home/home"
},
{
"pagePath": "pages/src/lookHous/lookHous"
},
{
"pagePath": "pages/src/community/community"
},
{
"pagePath": "pages/src/message/message"
},
{
"pagePath": "pages/src/user/user"
}
],
// 高为 0px 不可见因为我们要自定义 tabbar
"height": "0px"
},
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "云尚社区",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#f8f9fb"
},
"uniIdRouter": {}
}
6、编写 tabbar.js 状态数据
- tabbar.js
js
import {
defineStore
} from "pinia"
export const useTabbar = defineStore("tabbar", { //js命名
state: () => {
return {
activeTab: 0 // 默认选中的索引
}
},
actions: {
//设置active的值
setActive(active) {
this.activeTab = active
}
}
})
7、编写 tabbar.vue 组件
js
<template>
<view>
<up-tabbar :value="activeTab" :fixed="true" :placeholder="true" :safeAreaInsetBottom="true">
<template v-for="(item, index) in tabbarList" :key="index">
<up-tabbar-item :text="item.name" @click="toPageFun(item)" :icon="getTabbarIcon(item, index)">
</up-tabbar-item>
</template>
</up-tabbar>
</view>
</template>
<script setup>
import { ref } from 'vue';
// 导入 tabbar.js 中暴露的方法
import { useTabbar } from "@/pages/store/tabbar/tabbar.js"
// 导入 pinia 中暴露的数据转换为响应式的方法
import { storeToRefs } from "pinia";
// 实例化 tabbar.js 中暴露的方法
const tabbar = useTabbar();
// 转换为响应式数据
const { activeTab } = storeToRefs(tabbar);
const tabbarList = ref([{
index: 0,
name: "首页",
url: "/pages/src/home/home",
icon: "/static/tabbar/home.png",
activeIcon: "/static/tabbar/active-home.png",
},
{
index: 1,
name: "租房",
url: "/pages/src/lookHous/lookHous",
icon: "/static/tabbar/look-hous.png",
activeIcon: "/static/tabbar/active-look-hous.png",
},
{
index: 2,
name: "社区",
url: "/pages/src/community/community",
icon: "/static/tabbar/community.png",
activeIcon: "/static/tabbar/active-community.png",
},
{
index: 3,
name: "消息",
url: "/pages/src/message/message",
icon: "/static/tabbar/massage.png",
activeIcon: "/static/tabbar/active-massage.png",
}, {
index: 4,
name: "我的",
url: "/pages/src/user/user",
icon: "/static/tabbar/user.png",
activeIcon: "/static/tabbar/active-user.png",
},
]);
// 页面跳转
const toPageFun = (item) => {
// 把当前点击索引更新到 tabbar.js 里面的 activeTab 状态数据
tabbar.setActive(item.index);
// 页面跳转
uni.switchTab({
url: item.url
})
}
//图标的切换
const getTabbarIcon = (item, index) => {
return activeTab.value === index ? item.activeIcon : item.icon
}
</script>
<style lang="scss" scoped>
.u-page {
padding: 0;
&__item {
&__title {
color: $u-tips-color;
background-color: $u-bg-color;
padding: 15px 15px 5px 15px;
font-size: 15px;
&__slot-title {
color: $u-primary;
font-size: 14px;
}
}
&__slot-icon {
width: 17px;
height: 17px;
}
}
}
</style>