u-read-more.vue 4.5 KB

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