提交 f29da380 编写于 作者: fxy060608's avatar fxy060608

feat(h5): add custom-tab-bar

上级 70aef348
<template>
<uni-tabbar
v-if="hasTabBar"
v-show="showTabBar"
>
<div
:style="{'flex-direction':direction==='vertical'?'column':'row',backgroundColor:tabBarOptions.backgroundColor}"
class="uni-tabbar"
>
<div
v-for="(item,index) in tabBarOptions.list"
:key="item.pagePath"
class="uni-tabbar__item"
@click="_switchTab(item,index)"
>
<div class="uni-tabbar__bd">
<div
v-if="showIcon && item.iconPath"
:class="{'uni-tabbar__icon__diff':!item.text}"
class="uni-tabbar__icon"
>
<img :src="_getRealPath(selectedIndex===index?item.selectedIconPath:item.iconPath)">
<div
v-if="item.redDot"
:class="{'uni-tabbar__badge':!!item.badge}"
class="uni-tabbar__reddot"
>
{{ item.badge }}
</div>
</div>
<div
v-if="item.text"
:style="{color:selectedIndex===index?tabBarOptions.selectedColor:tabBarOptions.color,fontSize:showIcon&&item.iconPath?'10px':'14px'}"
class="uni-tabbar__label"
>
{{ item.text }}
<div
v-if="item.redDot&&(!showIcon || !item.iconPath)"
:class="{'uni-tabbar__badge':!!item.badge}"
class="uni-tabbar__reddot"
>
{{ item.badge }}
</div>
</div>
</div>
</div>
</div>
</uni-tabbar>
</template>
<script>
import getRealPath from 'uni-platform/helpers/get-real-path'
import {
tabBar
} from './observable'
export default {
name: 'CustomTabBar',
props: {
selected: {
type: Number,
default: 0
},
showIcon: {
type: Boolean,
default: true
},
direction: {
type: String,
default: 'horizontal'
}
},
data () {
return {
selectedIndex: this.selected
}
},
computed: {
tabBarOptions () {
return tabBar
},
hasTabBar () {
return tabBar.list && tabBar.list.length
},
showTabBar () {
const app = getApp()
if (app) {
return !app.$children[0].hideTabBar
}
return true
}
},
methods: {
_getRealPath (filePath) {
if (filePath.indexOf('/') !== 0) {
filePath = '/' + filePath
}
return getRealPath(filePath)
},
_switchTab ({
text,
pagePath
}, index) {
this.selectedIndex = index
let url = '/' + pagePath
if (url === __uniRoutes[0].alias) {
url = '/'
}
const detail = {
index,
text,
pagePath
}
this.$emit('onTabItemTap', detail)
if (this.$route.path === url) {
UniServiceJSBridge.emit('onTabItemTap', detail)
}
}
}
}
</script>
<style>
</style>
......@@ -9,7 +9,7 @@
<tab-bar
v-if="hasTabBar"
v-show="showTabBar"
v-bind="tabBar"
v-bind="tabBarOptions"
/>
<toast
v-if="$options.components.Toast"
......@@ -47,6 +47,10 @@ import components from './components'
import mixins from 'uni-h5-app-mixins'
import {
tabBar
} from './observable'
export default {
name: 'App',
components,
......@@ -63,7 +67,6 @@ export default {
return {
transitionName: 'fade',
hideTabBar: false,
tabBar: __uniConfig.tabBar || {},
sysComponents: this.$sysComponents,
showMaxWidth: false
}
......@@ -72,8 +75,11 @@ export default {
key () {
return this.$route.meta.name + '-' + this.$route.params.__id__ + '-' + (__uniConfig.reLaunch || 1)
},
tabBarOptions () {
return tabBar
},
hasTabBar () {
return __uniConfig.tabBar && __uniConfig.tabBar.list && __uniConfig.tabBar.list.length
return tabBar.list && tabBar.list.length
},
showTabBar () {
return this.$route.meta.isTabBar && !this.hideTabBar
......
import Vue from 'vue'
__uniConfig.tabBar = Vue.observable(__uniConfig.tabBar || {})
export const tabBar = __uniConfig.tabBar
<template>
<uni-tabbar>
<div
:style="{backgroundColor:backgroundColor}"
<uni-tabbar :class="['uni-tabbar-'+position]">
<div
:style="{backgroundColor:backgroundColor}"
class="uni-tabbar"
>
<div
:style="{backgroundColor:borderColor}"
<div
:style="{backgroundColor:borderColor}"
class="uni-tabbar-border"
/>
<div
v-for="(item,index) in list"
:key="item.pagePath"
class="uni-tabbar__item"
@click="_switchTab(item,index)"
<div
v-for="(item,index) in list"
:key="item.pagePath"
class="uni-tabbar__item"
@click="_switchTab(item,index)"
>
<div class="uni-tabbar__bd">
<div
v-if="item.iconPath"
:class="{'uni-tabbar__icon__diff':!item.text}"
class="uni-tabbar__icon"
<div
v-if="item.iconPath"
:class="{'uni-tabbar__icon__diff':!item.text}"
class="uni-tabbar__icon"
>
<img
:src="_getRealPath($route.meta.pagePath===item.pagePath?item.selectedIconPath:item.iconPath)"
<img :src="_getRealPath($route.meta.pagePath===item.pagePath?item.selectedIconPath:item.iconPath)">
<div
v-if="item.redDot"
:class="{'uni-tabbar__badge':!!item.badge}"
class="uni-tabbar__reddot"
>
<div
v-if="item.redDot"
:class="{'uni-tabbar__badge':!!item.badge}"
class="uni-tabbar__reddot"
>
{{ item.badge }}
{{ item.badge }}
</div>
</div>
<div
v-if="item.text"
<div
v-if="item.text"
:style="{color:$route.meta.pagePath===item.pagePath?selectedColor:color,fontSize:item.iconPath?'10px':'14px'}"
class="uni-tabbar__label"
class="uni-tabbar__label"
>
{{ item.text }}
<div
v-if="item.redDot&&!item.iconPath"
:class="{'uni-tabbar__badge':!!item.badge}"
class="uni-tabbar__reddot"
>
{{ item.badge }}
<div
v-if="item.redDot&&!item.iconPath"
:class="{'uni-tabbar__badge':!!item.badge}"
class="uni-tabbar__reddot"
>
{{ item.badge }}
</div>
</div>
</div>
......@@ -53,125 +51,130 @@
</template>
<style>
uni-tabbar {
display: block;
box-sizing: border-box;
position: fixed;
left: 0;
bottom: 0;
width: 100%;
z-index: 998;
}
uni-tabbar {
display: block;
box-sizing: border-box;
width: 100%;
z-index: 998;
}
uni-tabbar .uni-tabbar {
display: flex;
position: fixed;
left: var(--window-left);
right: var(--window-right);
bottom: 0;
z-index: 998;
box-sizing: border-box;
padding-bottom: 0;
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}
uni-tabbar .uni-tabbar {
display: flex;
z-index: 998;
box-sizing: border-box;
}
uni-tabbar .uni-tabbar ~ .uni-placeholder {
width: 100%;
height: 50px;
margin-bottom: 0;
margin-bottom: constant(safe-area-inset-bottom);
margin-bottom: env(safe-area-inset-bottom);
}
uni-tabbar.uni-tabbar-top,
uni-tabbar.uni-tabbar-bottom,
uni-tabbar.uni-tabbar-top .uni-tabbar,
uni-tabbar.uni-tabbar-bottom .uni-tabbar {
position: fixed;
left: var(--window-left);
right: var(--window-right);
}
uni-tabbar .uni-tabbar * {
box-sizing: border-box;
}
uni-tabbar.uni-tabbar-bottom .uni-tabbar {
bottom: 0;
padding-bottom: 0;
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}
uni-tabbar .uni-tabbar__item {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
flex: 1;
font-size: 0;
text-align: center;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
uni-tabbar .uni-tabbar~.uni-placeholder {
width: 100%;
height: 50px;
margin-bottom: 0;
margin-bottom: constant(safe-area-inset-bottom);
margin-bottom: env(safe-area-inset-bottom);
}
uni-tabbar .uni-tabbar__bd {
position: relative;
height: 50px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
cursor: pointer;
}
uni-tabbar .uni-tabbar * {
box-sizing: border-box;
}
uni-tabbar .uni-tabbar__icon {
position: relative;
display: inline-block;
margin-top: 5px;
width: 24px;
height: 24px;
}
uni-tabbar .uni-tabbar__item {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
flex: 1;
font-size: 0;
text-align: center;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
uni-tabbar .uni-tabbar__icon.uni-tabbar__icon__diff {
margin-top: 0px;
width: 34px;
height: 34px;
}
uni-tabbar .uni-tabbar__bd {
position: relative;
height: 50px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
cursor: pointer;
}
uni-tabbar .uni-tabbar__icon img {
width: 100%;
height: 100%;
}
uni-tabbar .uni-tabbar__icon {
position: relative;
display: inline-block;
margin-top: 5px;
width: 24px;
height: 24px;
}
uni-tabbar .uni-tabbar__label {
position: relative;
text-align: center;
font-size: 10px;
line-height: 1.8;
}
uni-tabbar .uni-tabbar__icon.uni-tabbar__icon__diff {
margin-top: 0px;
width: 34px;
height: 34px;
}
uni-tabbar .uni-tabbar-border {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 1px;
transform: scaleY(0.5);
}
uni-tabbar .uni-tabbar__icon img {
width: 100%;
height: 100%;
}
uni-tabbar .uni-tabbar__reddot {
position: absolute;
top: 0;
right: 0;
width: 12px;
height: 12px;
border-radius: 50%;
background-color: #f43530;
color: #ffffff;
transform: translate(40%, -20%);
}
uni-tabbar .uni-tabbar__label {
position: relative;
text-align: center;
font-size: 10px;
line-height: 1.8;
}
uni-tabbar .uni-tabbar__badge {
width: auto;
height: 16px;
line-height: 16px;
border-radius: 16px;
min-width: 16px;
padding: 0 2px;
font-size: 12px;
text-align: center;
white-space: nowrap;
}
uni-tabbar .uni-tabbar-border {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 1px;
transform: scaleY(0.5);
}
uni-tabbar .uni-tabbar__reddot {
position: absolute;
top: 0;
right: 0;
width: 12px;
height: 12px;
border-radius: 50%;
background-color: #f43530;
color: #ffffff;
transform: translate(40%, -20%);
}
uni-tabbar .uni-tabbar__badge {
width: auto;
height: 16px;
line-height: 16px;
border-radius: 16px;
min-width: 16px;
padding: 0 2px;
font-size: 12px;
text-align: center;
white-space: nowrap;
}
</style>
<script>
import getRealPath from 'uni-platform/helpers/get-real-path'
export default {
name: 'TabBar',
props: {
......@@ -256,4 +259,4 @@ export default {
}
}
}
</script>
</script>
......@@ -4,6 +4,7 @@ import App from './app'
import Page from './page'
import AsyncError from './async-error'
import AsyncLoading from './async-loading'
import CustomTabBar from './app/customTabBar'
import SystemRouteComponents from 'uni-h5-system-routes'
......@@ -11,6 +12,7 @@ Vue.component(App.name, App)
Vue.component(Page.name, Page)
Vue.component(AsyncError.name, AsyncError)
Vue.component(AsyncLoading.name, AsyncLoading)
Vue.component(CustomTabBar.name, CustomTabBar)
Object.keys(SystemRouteComponents).forEach(name => {
const Component = SystemRouteComponents[name]
......
......@@ -30,7 +30,7 @@ function setTabBar (type, args = {}) {
const {
index
} = args
const tabBar = app.$children[0].tabBar
const tabBar = __uniConfig.tabBar
if (index >= __uniConfig.tabBar.list.length) {
return {
errMsg: `${type}:fail tabbar item not found`
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册