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

news2024/11/14 7:14:06

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

  • 1、效果展示
  • 2、环境准备
    • 2.1 新建 uniapp 项目
    • 2.2. 安装 uView
    • 2.3 安装 pinia
  • 3. 配置环境
  • 4. 创建目录结构
  • 5、编写 pages.json 页面路由
  • 6、编写 tabbar.js 状态数据
  • 7、编写 tabbar.vue 组件

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>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2110282.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java-IDEA模拟一个Redis服务器,与Redis客户端进行一次简单的交互。默认端口号:6379

首先要了解Redis的交互协议。 摘抄&#xff1a; 简单字符串&#xff08;Simple Strings&#xff09;: 以 “” 开头&#xff0c;例如 “OK\r\n” 表示一个成功的响应。错误&#xff08;Errors&#xff09;: 以 “-” 开头&#xff0c;例如 “-ERR unknown command\r\n” 表示一…

操作系统概述及特征

&#xff08;较为浅显的了解操作系统&#xff0c;适合小白&#xff09;&#xff1b; 目录 1. 操作系统概述 1.1 操作系统 1.2 系统软件 1.3 主要作用 2. 操作系统的特征 ​编辑 2.1 并发性​编辑 2.2 并行​编辑 2.3 共享性 2.3.1 共享概述 2.3.2 共享与并发的关系…

【机器学习】朴素贝叶斯网络的基本概念以及朴素贝叶斯网络在python中的实例

引言 文章目录 引言一、朴素贝叶斯网络1.1 基本概念1.1.1 节点1.1.2 边&#xff08;Edges&#xff09;1.1.3 条件独立性 1.2 特点1.2.1 结构简单1.2.2 易于理解和实现1.2.3 计算效率高 1.3 应用1.4 数学表示1.5 局限性 二、朴素贝叶斯网络在python中的实例2.1 实例背景2.2 实现…

LangChain 最新版入门实战-v0.2

LangChain 基础入门文档 1. 认识 LangChain LangChain 是一个基于大型语言模型&#xff08;LLM&#xff09;的应用开发框架。它通过两种方式规范和简化了使用大型语言模型的方式&#xff1a; 集成&#xff1a;让语言模型能够使用更多的信息。 代理&#xff1a;让语言模型能够…

Linux 磁盘增加分区并挂载

说明 目的&#xff1a;该篇文章主要是实操后为了备忘 原因&#xff1a;为了方便&#xff0c;直接使用已有模板创建了虚拟机。没想到创建的新机器给了300G磁盘&#xff0c;实际只有2个分区且只使用了100G。以下为我实操后成功增加分区并挂载的步骤。 增加分区 指定操作对象&a…

如何快速写文献综述

真实参考文献的AI论文生成器&#xff1a;AIPaperDone - AI 万字论文生成 在本文中,你将学习如何为不同的学术领域撰写文献综述。 请注意: 文献综述并不是关于小说或诗歌等文学作品的。当我们说"文献",我们指的是某个领域的"研究"。撰写文献综述意味着收集…

【鸿蒙】HarmonyOS NEXT星河入门到实战3-ArkTS界面起步开发

目录 一、界面开发布局思路 二、组件的属性方法 三、字体颜色 四、文字溢出省略号、行高 五、Image图片组件 六、输入框与按钮 七、综合实战- 华为登录 八、设计资源-svg图标 前言&#xff1a;HarmonyOS NEXTArkTS界面开发起步。开发工具:仍然是 DevEco Studio 学习界面…

Android 使用JSON动画:Lottie框架基本使用

Lottie是什么? GitHub的一种跨平台动画解决方案三方框架 使用? 3步 1.引入最新的依赖:https://github.com/airbnb/lottie-android 我写文章时最新版本是6.5.2 添加到 app/build.gradle 文件的以下方法中dependencies {//lottie 动画implementation com.airbnb.android:l…

JavaScript DOM事件流之捕获与冒泡

DOM事件流——捕获与冒泡 网页是由一个一个元素组成的&#xff0c;正如我们肉眼所见&#xff0c;网页上的元素存在包含关系&#xff0c;简单的点击又怎么确定到底谁来触发响应呢&#xff1f;想象一下&#xff0c;在纸上画了两个大小不同的同心圆&#xff0c;然后用手指指向它里…

第45篇 汇编语言实现中断<一>

Q&#xff1a;DE2-115_Computer System的异常与中断有哪些特点呢&#xff1f; A&#xff1a;DE2-115 Computer系统中的Nios II处理器复位地址为0x00000000。用于处理其它所有普通异常&#xff0c;例如除0以及硬件IRQ中断的地址为0x00000020。Nios II处理器的异常和硬件IRQ中…

C++和OpenGL实现3D游戏编程【连载8】——纹理文字实现与优化

C++和OpenGL实现3D游戏编程【连载8】——纹理文字实现与优化 1、本节达到的效果 上一节课我们介绍了在opengl中文字的显示方法,但显示出来的文字无法旋转,在某些特定游戏要求下,文字是需要进行旋转的,那么这一节课我们介绍一下纹理文字的高级使用方法,将文字生成纹理,达…

一文搞懂性能测试

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 性能测试概念 我们经常看到的性能测试概念&#xff0c;有人或称之为性能策略&#xff0c;或称之为性能方法&#xff0c;或称之为性能场景分类&#xff0c;大概…

mysql和pg等数据库之间的数据迁移实战分享

mysql和pg等数据库之间的数据迁移是常见的问题&#xff1a;比如一开始使用Oracle&#xff0c;后来想使用mysql&#xff0c;而且需要把Oracle数据库的数据迁移到mysql里面&#xff1b;后期有想使用pg数据库&#xff0c;同时需要把Mysql数据库的数据迁移到pgl里面&#xff0c;等等…

shell脚本编写之函数

shell中的函数定义比较简单&#xff0c;定义函数名可以没有类型&#xff0c;函数返回值可有可无&#xff0c;如果有返回值&#xff0c;必须返回整数n&#xff08;0~255&#xff09;。同时&#xff0c;函数的定义必须放在shell脚本的开头部分&#xff0c;只有函数被shell解释器发…

【微机】DOSBox在windows上的安装和masm的配置

本文首发于 ❄️慕雪的寒舍 最近学校学习微型计算机原理与接口技术&#xff0c;需要用到DOSBox来模拟DOS环境进行汇编编程的学习。 本文记录了如何在windows11/10上安装DOSBox0.74并配置masm5 1.安装 这两个软件我打包上传到了百度云盘。放心&#xff0c;加起来也就2mb&…

【多线程】死锁

&#x1f970;&#x1f970;&#x1f970;来都来了&#xff0c;不妨点个关注叭&#xff01; &#x1f449;博客主页&#xff1a;欢迎各位大佬!&#x1f448; 文章目录 1. 死锁的三种情况1.1 一个线程一把锁&#xff08;同一个线程给同一个对象加两次锁的情况&#xff09;1.2 两…

Save OpenAI response in Azure function to Blob storage

题意&#xff1a;将 OpenAI 的响应保存在 Azure 函数中到 Blob 存储 问题背景&#xff1a; I used blob trigger template to create an Azure function that is triggered by new file updated in Azure blob storage. I am using python v2 to create Azure function in VSc…

SAP ABAP任意表数据查询+快速下载工具

背景&#xff1a; 项目上业务顾问有时候需要下载标准表大量的数据到Excel进行一些比对&#xff0c;但是标准SE16N&#xff0c;SE16的下载电子表格功能在遇到大批量数据的时候会非常慢&#xff0c;于是抽空写了个通用的查询下载工具&#xff0c;可以快速的下载数据。 工具界面&…

Linux - Linux安装部署xxl-job

一、下载源码 xxl-job源码地址&#xff1a; https://github.com/xuxueli/xxl-job 2.4.2版本为例&#xff1a;https://github.com/xuxueli/xxl-job/archive/refs/tags/2.4.1.tar.gz xxl-job文档地址&#xff1a; 分布式任务调度平台XXL-JOB 二、安装依赖环境 因为需要…

Go语言中的RPC协议原理解析

Go语言中的RPC协议原理解析 在分布式系统中&#xff0c;不同的服务或组件通常运行在不同的计算机或进程上。为了实现这些服务之间的通信&#xff0c;我们可以使用RPC&#xff08;Remote Procedure Call&#xff0c;远程过程调用&#xff09;协议。RPC允许我们像调用本地函数一…