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.

157 lines
4.4 KiB

9 months ago
  1. <template>
  2. <view class="u-read-more">
  3. <view
  4. class="u-read-more__content"
  5. :style="{
  6. height: isLongContent && status === 'close' ? $u.addUnit(showHeight) : $u.addUnit(contentHeight),
  7. textIndent: textIndent
  8. }"
  9. >
  10. <view
  11. class="u-read-more__content__inner"
  12. ref="u-read-more__content__inner"
  13. :class="[elId]"
  14. >
  15. <slot></slot>
  16. </view>
  17. </view>
  18. <view
  19. class="u-read-more__toggle"
  20. :style="[innerShadowStyle]"
  21. v-if="isLongContent"
  22. >
  23. <slot name="toggle">
  24. <view
  25. class="u-read-more__toggle__text"
  26. @tap="toggleReadMore"
  27. >
  28. <u--text
  29. :text="status === 'close' ? closeText : openText"
  30. :color="color"
  31. :size="fontSize"
  32. :lineHeight="fontSize"
  33. margin="0 5px 0 0"
  34. ></u--text>
  35. <view class="u-read-more__toggle__icon">
  36. <u-icon
  37. :color="color"
  38. :size="fontSize + 2"
  39. :name="status === 'close' ? 'arrow-down' : 'arrow-up'"
  40. ></u-icon>
  41. </view>
  42. </view>
  43. </slot>
  44. </view>
  45. </view>
  46. </template>
  47. <script>
  48. // #ifdef APP-NVUE
  49. const dom = uni.requireNativePlugin('dom')
  50. // #endif
  51. import props from './props.js';
  52. /**
  53. * readMore 阅读更多
  54. * @description 该组件一般用于内容较长预先收起一部分点击展开全部内容的场景
  55. * @tutorial https://www.uviewui.com/components/readMore.html
  56. * @property {String | Number} showHeight 内容超出此高度才会显示展开全文按钮单位px默认 400
  57. * @property {Boolean} toggle 展开后是否显示收起按钮默认 false
  58. * @property {String} closeText 关闭时的提示文字默认 '展开阅读全文'
  59. * @property {String} openText 展开时的提示文字默认 '收起'
  60. * @property {String} color 提示文字的颜色默认 '#2979ff'
  61. * @property {String | Number} fontSize 提示文字的大小单位px 默认 14
  62. * @property {Object} shadowStyle 显示阴影的样式
  63. * @property {String} textIndent 段落首行缩进的字符个数 默认 '2em'
  64. * @property {String | Number} name 用于在 open close 事件中当作回调参数返回
  65. * @event {Function} open 内容被展开时触发
  66. * @event {Function} close 内容被收起时触发
  67. * @example <u-read-more><rich-text :nodes="content"></rich-text></u-read-more>
  68. */
  69. export default {
  70. name: 'u-read-more',
  71. mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
  72. data() {
  73. return {
  74. isLongContent: false, // 是否需要隐藏一部分内容
  75. status: 'close', // 当前隐藏与显示的状态,close-收起状态,open-展开状态
  76. elId: uni.$u.guid(), // 生成唯一class
  77. contentHeight: 100, // 内容高度
  78. }
  79. },
  80. computed: {
  81. // 展开后无需阴影,收起时才需要阴影样式
  82. innerShadowStyle() {
  83. if (this.status === 'open') return {}
  84. else return this.shadowStyle
  85. }
  86. },
  87. mounted() {
  88. this.init()
  89. },
  90. methods: {
  91. async init() {
  92. this.getContentHeight().then(height => {
  93. this.contentHeight = height
  94. // 判断高度,如果真实内容高度大于占位高度,则显示收起与展开的控制按钮
  95. if (height > uni.$u.getPx(this.showHeight)) {
  96. this.isLongContent = true
  97. this.status = 'close'
  98. }
  99. })
  100. },
  101. // 获取内容的高度
  102. async getContentHeight() {
  103. // 延时一定时间再获取节点
  104. await uni.$u.sleep(30)
  105. return new Promise(resolve => {
  106. // #ifndef APP-NVUE
  107. this.$uGetRect('.' + this.elId).then(res => {
  108. resolve(res.height)
  109. })
  110. // #endif
  111. // #ifdef APP-NVUE
  112. const ref = this.$refs['u-read-more__content__inner']
  113. dom.getComponentRect(ref, (res) => {
  114. resolve(res.size.height)
  115. })
  116. // #endif
  117. })
  118. },
  119. // 展开或者收起
  120. toggleReadMore() {
  121. this.status = this.status === 'close' ? 'open' : 'close'
  122. // 如果toggle为false,隐藏"收起"部分的内容
  123. if (this.toggle == false) this.isLongContent = false
  124. // 发出打开或者收齐的事件
  125. this.$emit(this.status, this.name)
  126. }
  127. }
  128. }
  129. </script>
  130. <style lang="scss" scoped>
  131. @import "../../libs/css/components.scss";
  132. .u-read-more {
  133. &__content {
  134. overflow: hidden;
  135. color: $u-content-color;
  136. font-size: 15px;
  137. text-align: left;
  138. }
  139. &__toggle {
  140. @include flex;
  141. justify-content: center;
  142. &__text {
  143. @include flex;
  144. align-items: center;
  145. justify-content: center;
  146. margin-top: 5px;
  147. }
  148. }
  149. }
  150. </style>