wd-navbar.vue 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. <template>
  2. <view :style="{ height: addUnit(height) }">
  3. <view :class="`wd-navbar ${customClass} ${fixed ? 'is-fixed' : ''} ${bordered ? 'is-border' : ''}`" :style="rootStyle">
  4. <view class="wd-navbar__content">
  5. <view class="wd-navbar__capsule" v-if="$slots.capsule">
  6. <slot name="capsule" />
  7. </view>
  8. <view :class="`wd-navbar__left ${leftDisabled ? 'is-disabled' : ''}`" @click="handleClickLeft" v-else-if="!$slots.left">
  9. <wd-icon v-if="leftArrow" name="arrow-left" custom-class="wd-navbar__arrow" />
  10. <view v-if="leftText" class="wd-navbar__text">{{ leftText }}</view>
  11. </view>
  12. <view v-else :class="`wd-navbar__left ${leftDisabled ? 'is-disabled' : ''}`" @click="handleClickLeft">
  13. <slot name="left" />
  14. </view>
  15. <view class="wd-navbar__title">
  16. <slot name="title" />
  17. <block v-if="!$slots.title && title">{{ title }}</block>
  18. </view>
  19. <view :class="`wd-navbar__right ${rightDisabled ? 'is-disabled' : ''}`" @click="handleClickRight" v-if="$slots.right || rightText">
  20. <slot name="right" />
  21. <view v-if="!$slots.right && rightText" class="wd-navbar__text" hover-class="wd-navbar__text--hover" :hover-stay-time="70">
  22. {{ rightText }}
  23. </view>
  24. </view>
  25. </view>
  26. </view>
  27. </view>
  28. </template>
  29. <script lang="ts">
  30. export default {
  31. name: 'wd-navbar',
  32. options: {
  33. virtualHost: true,
  34. addGlobalClass: true,
  35. styleIsolation: 'shared'
  36. }
  37. }
  38. </script>
  39. <script lang="ts" setup>
  40. import wdIcon from '../wd-icon/wd-icon.vue'
  41. import { type CSSProperties, computed, getCurrentInstance, nextTick, onMounted, ref, watch } from 'vue'
  42. import { getRect, addUnit, isDef, objToStyle } from '../common/util'
  43. import { navbarProps } from './types'
  44. const props = defineProps(navbarProps)
  45. const emit = defineEmits(['click-left', 'click-right'])
  46. const height = ref<number | ''>('') // 占位高度
  47. const { statusBarHeight } = uni.getSystemInfoSync()
  48. watch(
  49. [() => props.fixed, () => props.placeholder],
  50. () => {
  51. setPlaceholderHeight()
  52. },
  53. { deep: true, immediate: false }
  54. )
  55. const rootStyle = computed(() => {
  56. const style: CSSProperties = {}
  57. if (props.fixed && isDef(props.zIndex)) {
  58. style['z-index'] = props.zIndex
  59. }
  60. if (props.safeAreaInsetTop) {
  61. style['padding-top'] = addUnit(statusBarHeight || 0)
  62. }
  63. return `${objToStyle(style)}${props.customStyle}`
  64. })
  65. onMounted(() => {
  66. if (props.fixed && props.placeholder) {
  67. nextTick(() => {
  68. setPlaceholderHeight()
  69. })
  70. }
  71. })
  72. function handleClickLeft() {
  73. if (!props.leftDisabled) {
  74. emit('click-left')
  75. }
  76. }
  77. function handleClickRight() {
  78. if (!props.rightDisabled) {
  79. emit('click-right')
  80. }
  81. }
  82. const { proxy } = getCurrentInstance() as any
  83. function setPlaceholderHeight() {
  84. if (!props.fixed || !props.placeholder) {
  85. return
  86. }
  87. getRect('.wd-navbar', false, proxy).then((res) => {
  88. height.value = res.height as number
  89. })
  90. }
  91. </script>
  92. <style lang="scss">
  93. @import './index.scss';
  94. </style>