详情小程序
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

258 lines
6.6 KiB

  1. <template>
  2. <view ref="item"
  3. :class="[
  4. 'lb-tabbar-item',
  5. 'animate__animated',
  6. isActive ? 'lb-tabbar-item--active' : ''
  7. ]"
  8. :style="{
  9. paddingTop: paddingBT + raisedeHeight + 'px',
  10. paddingBottom: paddingBT + 'px',
  11. width: '100%'
  12. }"
  13. @tap="handleTap">
  14. <view :class="[
  15. 'lb-tabbar-item__icon',
  16. `lb-tabbar-item__icon--${raisede ? 'raisede' : 'default'}`,
  17. isAnimate ? `animate__animated animate__${tabbarInfo.animate}` : '',
  18. isActive ? 'lb-my-active' : ''
  19. ]"
  20. :style="{
  21. height: tabbarInfo.iconSize,
  22. lineHeight: tabbarInfo.iconSize,
  23. transform: raisede ? `translateY(-${ty}px) scale(${tabbarInfo.raisedeScale})` : ''
  24. }">
  25. <!-- 图片图标 -->
  26. <image v-if="isImage"
  27. class="lb-tabbar-item__image"
  28. :src="icon"
  29. :style="{
  30. width: tabbarInfo.iconSize,
  31. height: tabbarInfo.iconSize
  32. }">
  33. </image>
  34. <!-- icon图标 -->
  35. <text v-else
  36. :class="[
  37. 'le',
  38. iconPrefix,
  39. `${iconPrefix}-${icon}`,
  40. isActive ? 'lb-tabbar-item__icon--active' : ''
  41. ]"
  42. :style="{
  43. width: tabbarInfo.iconSize,
  44. height: tabbarInfo.iconSize,
  45. lineHeight: tabbarInfo.iconSize,
  46. fontSize: tabbarInfo.iconSize,
  47. color: isActive ? tabbarInfo.activeColor : tabbarInfo.inactiveColor
  48. }">{{ iconCode }}</text>
  49. <!-- 非nvue dot info显示 -->
  50. <!-- #ifndef APP-NVUE -->
  51. <text v-if="dot || hasInfo"
  52. :class="[
  53. dot && !hasInfo ? 'lb-tabbar-item__dot' : '',
  54. hasInfo ? 'lb-tabbar-item__dot--info' : '',
  55. 'lb-tabbar-item__dot--style'
  56. ]"
  57. :style="{
  58. backgroundColor: tabbarInfo.dotColor
  59. }">{{ hasInfo ? info : '' }}</text>
  60. <!-- #endif -->
  61. </view>
  62. <!-- nvue dot info 显示 -->
  63. <!-- #ifdef APP-NVUE -->
  64. <text v-if="dot || hasInfo"
  65. :class="[
  66. 'lb-tabbar-item__dot--nvue',
  67. 'lb-tabbar-item__dot--style',
  68. dot && !hasInfo ? 'lb-tabbar-item__dot' : '',
  69. hasInfo ? 'lb-tabbar-item__dot--info' : '',
  70. hasInfo ? 'lb-tabbar-item__dot--info' : '',
  71. nvueDotShow ? 'lb-tabbar-item__dot--show' : ''
  72. ]"
  73. :style="{
  74. backgroundColor: tabbarInfo.dotColor,
  75. top: paddingBT + raisedeHeight + 'px',
  76. right: dotLeft + 'px'
  77. }">{{ hasInfo ? info : '' }}</text>
  78. <!-- #endif -->
  79. <!-- 非nvue图标文字 -->
  80. <!-- #ifndef APP-NVUE -->
  81. <view :class="[
  82. 'lb-tabbar-item__text',
  83. isActive ? 'lb-tabbar-item__text--active' : ''
  84. ]"
  85. :style="{
  86. fontSize: tabbarInfo.textSize,
  87. lineHeight: tabbarInfo.textSize,
  88. maxHeight: tabbarInfo.textSize,
  89. marginTop: tabbarInfo.textTop,
  90. color: isActive
  91. ? tabbarInfo.activeTextColor || tabbarInfo.activeColor
  92. : tabbarInfo.inactiveTextColor || tabbarInfo.inactiveColor
  93. }">
  94. <slot></slot>
  95. <view v-if="raisede"
  96. class="lb-tabbar-item__text--block"
  97. :style="{
  98. height: tabbarInfo.textSize
  99. }">
  100. </view>
  101. </view>
  102. <!-- #endif -->
  103. <!-- nvue图标文字 -->
  104. <!-- #ifdef APP-NVUE -->
  105. <text v-if="text || raisede"
  106. :class="[
  107. 'lb-tabbar-item__text',
  108. isActive ? 'lb-tabbar-item__text--active' : ''
  109. ]"
  110. :style="{
  111. fontSize: tabbarInfo.textSize,
  112. height: tabbarInfo.textSize,
  113. lineHeight: tabbarInfo.textSize,
  114. marginTop: tabbarInfo.textTop,
  115. color: isActive
  116. ? tabbarInfo.activeTextColor || tabbarInfo.activeColor
  117. : tabbarInfo.inactiveTextColor || tabbarInfo.inactiveColor
  118. }">{{ text || '' }}</text>
  119. <!-- #endif -->
  120. </view>
  121. </template>
  122. <script>
  123. // #ifdef APP-NVUE
  124. const dom = uni.requireNativePlugin('dom')
  125. // #endif
  126. import { getPx } from './utils'
  127. export default {
  128. props: {
  129. name: [String, Number],
  130. text: [String, Number],
  131. icon: String,
  132. iconPrefix: String,
  133. dot: Boolean,
  134. info: [String, Number],
  135. raisede: Boolean
  136. },
  137. inject: ['tabbar'],
  138. data () {
  139. return {
  140. tabbarInfo: {},
  141. itemWidth: 0,
  142. dotLeft: 0,
  143. nvueDotShow: false
  144. }
  145. },
  146. computed: {
  147. isImage () {
  148. return this.icon && this.icon.indexOf('/') > -1
  149. },
  150. isActive () {
  151. return this.tabbarInfo.value === this.name
  152. },
  153. isAnimate () {
  154. return (
  155. this.isActive &&
  156. this.tabbarInfo.animate &&
  157. !(this.raisede && this.tabbarInfo.closeAnimateOnRaisede)
  158. )
  159. },
  160. height () {
  161. return getPx(this.tabbarInfo.height)
  162. },
  163. iconHeight () {
  164. return getPx(this.tabbarInfo.iconSize)
  165. },
  166. textSize () {
  167. return getPx(this.tabbarInfo.textSize)
  168. },
  169. textTop () {
  170. return getPx(this.tabbarInfo.textTop)
  171. },
  172. ty () {
  173. return this.height / 2 - (this.textSize + this.textTop) / 2
  174. },
  175. iconCode () {
  176. let code = ''
  177. // #ifdef APP-NVUE
  178. code = this.icon
  179. // #endif
  180. return code
  181. },
  182. hasInfo () {
  183. return this.info || this.info === 0
  184. },
  185. paddingBT () {
  186. return (this.height - this.iconHeight - this.textSize - this.textTop) / 2
  187. },
  188. hasRaisede () {
  189. return this.tabbar.hasRaisede
  190. },
  191. raisedeHeight () {
  192. return this.hasRaisede ? this.iconHeight * this.tabbarInfo.raisedeScale / 2 : 0 // 凸起高度
  193. },
  194. infoLength () {
  195. return this.hasInfo ? (this.info + '').length : 0
  196. }
  197. },
  198. created () {
  199. this.tabbarInfo = this.tabbar._props
  200. this.tabbar.tabbarItems.push(this._props)
  201. },
  202. mounted() {
  203. // #ifdef APP-NVUE
  204. this.setNvueDot()
  205. // #endif
  206. },
  207. methods: {
  208. handleTap () {
  209. this.tabbar.active = this.name
  210. this.$emit('click', this._props)
  211. },
  212. // #ifdef APP-NVUE
  213. setNvueDot () {
  214. if (this.dot || this.hasInfo) {
  215. this.$nextTick(() => {
  216. const $el = this.$refs.item
  217. dom.getComponentRect($el, res => {
  218. this.itemWidth = res.size.width
  219. const halfWidth = this.itemWidth / 2
  220. if (this.dot) {
  221. this.dotLeft = halfWidth - 8
  222. }
  223. if (this.hasInfo) {
  224. const length = this.infoLength > 1 ? this.infoLength -1 : this.infoLength
  225. this.dotLeft = halfWidth - 8 * length
  226. }
  227. this.nvueDotShow = true
  228. })
  229. })
  230. }
  231. }
  232. // #endif
  233. },
  234. // #ifdef APP-NVUE
  235. watch: {
  236. dot () {
  237. this.setNvueDot()
  238. },
  239. info () {
  240. this.setNvueDot()
  241. }
  242. }
  243. // #endif
  244. }
  245. </script>
  246. <style lang="scss" scoped>
  247. @import "./style.scss";
  248. /* #ifndef APP-NVUE */
  249. @import "./animate.scss";
  250. /* #endif */
  251. </style>