init
This commit is contained in:
35
uni_modules/nutui-uni/components/tabbar/index.scss
Normal file
35
uni_modules/nutui-uni/components/tabbar/index.scss
Normal file
@@ -0,0 +1,35 @@
|
||||
.nut-theme-dark {
|
||||
.nut-tabbar {
|
||||
background: $dark-background;
|
||||
border-color: $dark-background;
|
||||
}
|
||||
}
|
||||
|
||||
.nut-tabbar {
|
||||
box-sizing: content-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: $tabbar-height;
|
||||
background: $white;
|
||||
border: 0;
|
||||
border-top: $tabbar-border-top;
|
||||
border-bottom: $tabbar-border-bottom;
|
||||
box-shadow: $tabbar-box-shadow;
|
||||
|
||||
&:last-child {
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
&-bottom {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 888;
|
||||
}
|
||||
|
||||
&-safebottom {
|
||||
padding-bottom: constant(safe-area-inset-bottom);
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
}
|
||||
2
uni_modules/nutui-uni/components/tabbar/index.ts
Normal file
2
uni_modules/nutui-uni/components/tabbar/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from './tabbar'
|
||||
export * from './types'
|
||||
43
uni_modules/nutui-uni/components/tabbar/tabbar.ts
Normal file
43
uni_modules/nutui-uni/components/tabbar/tabbar.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import type { ExtractPropTypes, InjectionKey } from 'vue'
|
||||
import { UPDATE_MODEL_EVENT } from '../_constants'
|
||||
import { commonProps, isNumber, isString, makeNumericProp } from '../_utils'
|
||||
import type { TabbarContext } from './types'
|
||||
|
||||
export const tabbarProps = {
|
||||
...commonProps,
|
||||
/**
|
||||
* @description 选中标签的索引值或者名称
|
||||
*/
|
||||
modelValue: makeNumericProp(0),
|
||||
/**
|
||||
* @description 是否固定在页面底部
|
||||
*/
|
||||
bottom: Boolean,
|
||||
/**
|
||||
* @description icon激活的颜色
|
||||
*/
|
||||
activeColor: String,
|
||||
/**
|
||||
* @description icon未激活的颜色
|
||||
*/
|
||||
unactiveColor: String,
|
||||
/**
|
||||
* @description 是否开启iphone系列全面屏底部安全区适配
|
||||
*/
|
||||
safeAreaInsetBottom: Boolean,
|
||||
/**
|
||||
* @description 固定在底部时,是否在标签位置生成一个等高的占位元素
|
||||
*/
|
||||
placeholder: Boolean,
|
||||
}
|
||||
|
||||
export type TabBarProps = ExtractPropTypes<typeof tabbarProps>
|
||||
|
||||
export const tabbarEmits = {
|
||||
tabSwitch: (val: any, index: number | string) => (val instanceof Object) && (isNumber(index) || isString(index)),
|
||||
[UPDATE_MODEL_EVENT]: (val: string | number) => isString(val) || isNumber(val),
|
||||
}
|
||||
|
||||
export type TabBarEmits = typeof tabbarEmits
|
||||
|
||||
export const TABBAR_CONTEXT_KEY: InjectionKey<TabbarContext> = Symbol('TABBAR_CONTEXT')
|
||||
107
uni_modules/nutui-uni/components/tabbar/tabbar.vue
Normal file
107
uni_modules/nutui-uni/components/tabbar/tabbar.vue
Normal file
@@ -0,0 +1,107 @@
|
||||
<script lang="ts" setup>
|
||||
import type { CSSProperties } from 'vue'
|
||||
import { computed, defineComponent, getCurrentInstance, onMounted, provide, reactive, ref, watch } from 'vue'
|
||||
import { PREFIX, UPDATE_MODEL_EVENT } from '../_constants'
|
||||
import { useSelectorQuery } from '../_hooks'
|
||||
import { getMainClass } from '../_utils'
|
||||
import { TABBAR_CONTEXT_KEY, tabbarEmits, tabbarProps } from './tabbar'
|
||||
import type { TabbarContext } from './types'
|
||||
|
||||
const props = defineProps(tabbarProps)
|
||||
|
||||
const emit = defineEmits(tabbarEmits)
|
||||
|
||||
const instance = getCurrentInstance()!
|
||||
|
||||
const { getSelectorNodeInfo } = useSelectorQuery(instance)
|
||||
|
||||
const classes = computed(() => {
|
||||
return getMainClass(props, componentName, {
|
||||
'nut-tabbar-bottom': props.bottom,
|
||||
'nut-tabbar-safebottom': props.safeAreaInsetBottom,
|
||||
})
|
||||
})
|
||||
|
||||
const wrapperClasses = computed(() => {
|
||||
return {
|
||||
'nut-tabbar__placeholder': props.bottom && props.placeholder,
|
||||
}
|
||||
})
|
||||
|
||||
const trulyHeight = ref<number>()
|
||||
|
||||
const wrapperStyles = computed(() => {
|
||||
const value: CSSProperties = {}
|
||||
|
||||
if (trulyHeight.value != null) {
|
||||
value.height = `${trulyHeight.value}px`
|
||||
}
|
||||
|
||||
return value
|
||||
})
|
||||
|
||||
const parentData: TabbarContext = reactive({
|
||||
modelValue: props.modelValue,
|
||||
activeColor: props.activeColor,
|
||||
unactiveColor: props.unactiveColor,
|
||||
children: [],
|
||||
changeIndex,
|
||||
})
|
||||
|
||||
provide(TABBAR_CONTEXT_KEY, parentData)
|
||||
|
||||
watch(() => props.modelValue, (value) => {
|
||||
parentData.modelValue = value
|
||||
})
|
||||
|
||||
watch(() => [props.activeColor, props.unactiveColor], ([activeColor, unactiveColor]) => {
|
||||
parentData.activeColor = activeColor
|
||||
parentData.unactiveColor = unactiveColor
|
||||
})
|
||||
|
||||
function changeIndex(index: number, active: number | string) {
|
||||
parentData.modelValue = active
|
||||
|
||||
emit(UPDATE_MODEL_EVENT, active)
|
||||
emit('tabSwitch', parentData.children[index], active)
|
||||
}
|
||||
|
||||
async function fetchTrulyHeight() {
|
||||
const node = await getSelectorNodeInfo('.nut-tabbar')
|
||||
|
||||
trulyHeight.value = node.height
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (props.bottom && props.placeholder) {
|
||||
setTimeout(() => {
|
||||
fetchTrulyHeight()
|
||||
}, 500)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
const componentName = `${PREFIX}-tabbar`
|
||||
|
||||
export default defineComponent({
|
||||
name: componentName,
|
||||
options: {
|
||||
virtualHost: true,
|
||||
addGlobalClass: true,
|
||||
styleIsolation: 'shared',
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view :class="wrapperClasses" :style="wrapperStyles">
|
||||
<view :class="classes" :style="props.customStyle">
|
||||
<slot />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
@import "./index";
|
||||
</style>
|
||||
7
uni_modules/nutui-uni/components/tabbar/types.ts
Normal file
7
uni_modules/nutui-uni/components/tabbar/types.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export interface TabbarContext {
|
||||
modelValue: number | string
|
||||
activeColor: string | undefined
|
||||
unactiveColor: string | undefined
|
||||
children: any[]
|
||||
changeIndex: (index: number, active: number | string) => void
|
||||
}
|
||||
Reference in New Issue
Block a user