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

1、效果展示


在这里插入图片描述

2、环境准备


2.1 新建 uniapp 项目

新建普通 Vue3 项目即可

在这里插入图片描述

2.2. 安装 uView


官网

https://uiadmin.net/uview-plus/components/install.html

安装

npm install uview-plus

2.3 安装 pinia

官网

https://pinia.vuejs.org/zh/getting-started.html

安装

npm install pinia

3. 配置环境


  • main.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
<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(如果没有可以新建,主要用于配置@路径识别)
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 页面路由

{
	// 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
import {
	defineStore
} from "pinia"

export const useTabbar = defineStore("tabbar", { //js命名
	state: () => {
		return {
			activeTab: 0 // 默认选中的索引
		}
	},
	actions: {
		//设置active的值
		setActive(active) {
			this.activeTab = active
		}
	}
})

7、编写 tabbar.vue 组件

<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>
  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

她似晚风般温柔789

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值