Uniapp + Vite + Vue3 + uView + Pinia 实现自定义底部 Tabbar(最新保姆级教程)

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>
相关推荐
aPurpleBerry18 分钟前
JS常用数组方法 reduce filter find forEach
javascript
GIS程序媛—椰子1 小时前
【Vue 全家桶】7、Vue UI组件库(更新中)
前端·vue.js
ZL不懂前端1 小时前
Content Security Policy (CSP)
前端·javascript·面试
乐闻x1 小时前
ESLint 使用教程(一):从零配置 ESLint
javascript·eslint
我血条子呢2 小时前
[Vue]防止路由重复跳转
前端·javascript·vue.js
半开半落2 小时前
nuxt3安装pinia报错500[vite-node] [ERR_LOAD_URL]问题解决
前端·javascript·vue.js·nuxt
麦麦大数据2 小时前
基于vue+neo4j 的中药方剂知识图谱可视化系统
vue.js·知识图谱·neo4j
customer082 小时前
【开源免费】基于SpringBoot+Vue.JS医院管理系统(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·开源·intellij-idea