uniapp自定义tabBar

目录

目录

uniapp自定义tabBar方案

一、pages.json文件中添加tarBar

二、把原生的tabBar隐藏起来

三、自定义一个tabBar组件

四、全局引用组件

五、路由跳转

补充1:自定义switchTab跳转方法

补充2:在app中$route找不到的问题

六、相关代码


uniapp自定义tabBar方案

uniapp自定义tabBar_第1张图片

该方案,可以在切换tabBar的时候,路由也跟着变化,方便平时进行页面测试使用,不过有个缺点,第一次切换的时候会出现闪烁现象。

解决闪烁的问题:

1、可以把tabBar和页面组件都放在单页中用v-if判断,进行切换,单页切换的缺点是不能进行路由跳转(不能路由跳转)

 2、把组件注入App.vue中,实现全局引用,但是uniapp不建议在App.vue中使用页面组件,也不要使用,不然出现各种问题,uniapp不能像vue那样在App.vue使用router-view实现选项卡功能(不推荐)

3、 所以要同时实现首次不闪烁,而且可以进行路由切换的功能,目前不知道如何处理。(未知)

首次加载闪烁,严格意义上说,可以被认定为bug。小编在想能不能用vue的路由方式去实现router-view呢?因此尝试的去自定义router-view,却发现uniapp内置了路由,当想用vue插件方式,重写路由时,发现冲突了。

uniapp自定义tabBar_第2张图片

其实关于自定义,在uniapp中,官方目前不推荐大家去自定义的,如果业务场景需要根据不同权限,显示不同tabBar,我们可以去跟需求谈,换另外一方式,也是可以的。例如用下图的方式

uniapp自定义tabBar_第3张图片

(方案还有需要完善的地方,这里仅供大家参考)

一、pages.json文件中添加tarBar

因为需要用到tabBar跳转,因此可以往原来的tabBar.list中多添加几个,用于做判断是否tabBar切换(这里可以只添加路径,icon和text可以不需要)

uniapp自定义tabBar_第4张图片

二、把原生的tabBar隐藏起来

在App.vue中把原生的tabBar先隐藏起来

onLaunch: function() {
	console.log('App Launch')
	uni.hideTabBar()
},

三、自定义一个tabBar组件

uniapp自定义tabBar_第5张图片

在components中新建一个tabBar.vue的页面,用来封装组件

HTML代码,这里循环遍历自己定义的tabBar.list(可根据需求来定义)


   
			
				
						
						
						{{item.text}}
				
			
		
  

data里面定义变量和循环列表,list即是自己定义的tabBar,和pages.json的tabBar写法一样

data() {
			return {
				selectedIndex: 0, // 标记
				showselected: false, // 是否在页面使用tarBar
				tabBar: {
					list: [{
							"pagePath": "pages/index/index",
							"iconPath": "/static/tabIcon/icon1.png",
							"selectedIconPath": "/static/tabIcon/icon2.png",
							"text": "首页"
						}, {
							"pagePath": "pages/team/team",
							"iconPath": "/static/tabIcon/icon3.png",
							"selectedIconPath": "/static/tabIcon/icon4.png",
							"text": "团队"
						}, {
							"pagePath": "pages/promotion/promotion",
							"iconPath": "/static/tabIcon/icon5.png",
							"selectedIconPath": "/static/tabIcon/icon6.png",
							"text": "推广圈"
						},
						{
							"pagePath": "pages/my/my",
							"iconPath": "/static/tabIcon/icon7.png",
							"selectedIconPath": "/static/tabIcon/icon8.png",
							"text": "我的"
						}
					]
				},
			}
		},

如果需要根据不同用户来渲染不同tabBar,可用vuex来保存tabBar的list列表

const user_1 = [{
		"pagePath": "../pages/test/me",
		"iconPath": "../static/xxx.png",
		"selectedIconPath": "../static/xxx.png",
		"text": "me"
	}, {
		"pagePath": "../pages/test/you",
		"iconPath": "../static/xxx.png",
		"selectedIconPath": "../static/xxx.png",
		"text": "you"
	}, {
		"pagePath": "../pages/test/other",
		"iconPath": "../static/xxx.png",
		"selectedIconPath": "../static/xxx.png",
		"text": "other"
	},
	
]
const user_2 = [{
		"pagePath": "../pages/test/our",
		"iconPath": "../static/xxx.png",
		"selectedIconPath": "../static/xxx.png",
		"text": "our"
	}, {
		"pagePath": "../pages/test/his",
		"iconPath": "../static/xxx.png",
		"selectedIconPath": "../static/xxx.png",
		"text": "his"
	}, 
]
export default {
	user_1,
	user_1
}

四、全局引用组件

往main.js注入组件

// main.js
import tabBar from 'components/tab-bar/tabBar.vue'
Vue.component('tab-bar',tabBar) //挂载

在每一个页面中引入

五、路由跳转

tabBar定义成了组件,因此需要一个全局变量来判断它的切换和路由的跳转。

首先,进入到uniapp的官方tabBar源码中,可以看到这样一段代码,下面的这段代码,就是路由跳转的依据,把他复制到自己的组件中,进行改造。该监听方式只能在uniapp中有效,在app中无法监听,详情往下看【补充2】

 watch: {
    $route: {
      immediate: true,
      handler (to) {
        if (to.meta.isTabBar) { // 判断是否属于tarBar
          // this.__path__ = to.path
          // 判断路由的路径和tarBar.list的pagePath是否相同,来确定一个全局的index
          const index = this.list.findIndex(item => to.meta.pagePath === item.pagePath)
          if (index > -1) {
            this.selectedIndex = index // 标记是第几个tarBar
          }
        }
      }
    }
  },

 定义跳转的方法,这里用的是uni.switchTab进行跳转,不然url不会发生变化。注释掉的代码是官方的代码,这里是直接复制过来自己用。注:后续要使用switchTab进行跳转的话,就需要到自定义的方法,毕竟已经自定义了tabBar,跳转方式也需要自定义。自定义跳转方法请看文章后面的【补充1】

methods: {
			switchTab(index, item) {
				let url = '/' + item.pagePath
				let pagePath = url
				const detail = {
				  index,
				  pagePath
				}
				if (this.$route.path !== url) {
				  // this.__path__ = this.$route.path
				  uni.switchTab({
				    from: 'tabBar',
				    url,
				    detail
				  })
				} else {
				  // UniServiceJSBridge.emit('onTabItemTap', detail)
				}
				this.selectedIndex = index
				// this.$emit('switchTab', detail)
			}
		},

补充1:自定义switchTab跳转方法

由于在子组件中已经存在switchTab方法,现只需做一下调整即可,先调整一下switchTab方法,如下:

            /*   
			// 调整前
			methods: {
				switchTab(index, item) {
					let url = '/' + item.pagePath
					let pagePath = url
					const detail = {
						index,
						pagePath
					}
					if (this.$route.path !== url) {
						// this.__path__ = this.$route.path
						uni.switchTab({
							from: 'tabBar',
							url,
							detail
						})
					} else {
						// UniServiceJSBridge.emit('onTabItemTap', detail)
					}
					this.selectedIndex = index
					// this.$emit('switchTab', detail)
				}
			}, */
			// 调整后,1、调换入参顺序,方便传值,2、循环判断一下index,
			switchTab(item, index) {
				let url = '/' + item.pagePath
				let pagePath = url
				const detail = {
					index,
					pagePath
				}
				if (this.$route.path !== url) {
					// this.__path__ = this.$route.path
					let s = uni.switchTab({
						url,
						detail
					})
				} else {
					// UniServiceJSBridge.emit('onTabItemTap', detail)
				}
				this.tabBar.list.forEach((v, i) => {
					if (item.pagePath === v.pagePath) {
						this.selectedIndex = i
				   }
				})
				// this.$emit('switchTab', detail)
			}

这里的index和item也要调换一下位置 ,@click="switchTab(item,index)"

uniapp自定义tabBar_第6张图片

 index和item调换 

父组件中使用ref="tabBar"来获取子组件 

通过方法来触发子组件方法即可, 对象中的pagePath是与tabBar.list数组里面的pagePath是对应的。

toMY() {
	this.$refs.tabBar.switchTab({
	   pagePath:'pages/team/team'
	})
},

补充2:在app中$route找不到的问题

打包到小程序之后,$route会像下面图片那样显示undefined,即在小程序中,是没有像$route这样的路由方式。那么,就不能用这样的方式,来监听index的变化。

uniapp自定义tabBar_第7张图片

 如何解决?

利用uni.setStorageSync()全局保存一下点击tabBar的index即可,进入到tabBar.vue文件。

1、重写switchTab()方法

2、注释掉$route的监听。

3、调整data中定义的变量selectedIndex

最后进入App.vue文件中,清除一下selectedIndex的缓存,不在tabBar.vue的created生命周期清除selectedIndex的原因是:只希望,每次重新进入程序后重置,tabBar的高亮重新回到第一个,而不是每次进入页面的重置,而且每次进入页面重置,是有问题。

六、相关代码

在App.vue中把原生的tabBar先隐藏起来和清除index

onLaunch: function() {
	console.log('App Launch')
    uni.removeStorageSync('selectedIndex'); // 清除缓存
	uni.hideTabBar()
},

tabBar.vue






main.js注入组件

// main.js
import tabBar from 'components/tab-bar/tabBar.vue'
Vue.component('tab-bar',tabBar) //挂载

在每一个页面中引入

page/index.vue 首页






你可能感兴趣的:(vue,uni-app,vue.js,前端)