u-read-more.vue 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. <template>
  2. <view class="">
  3. <view class="u-content" :class="[elId]" :style="{
  4. height: isLongContent && !showMore ? showHeight + 'rpx' : 'auto',
  5. textIndent: this.textIndent
  6. }">
  7. <slot></slot>
  8. </view>
  9. <view @tap="toggleReadMore" v-if="isLongContent" class="u-content__showmore-wrap"
  10. :class="{ 'u-content__show-more': showMore }"
  11. :style="[innerShadowStyle]">
  12. <text class="u-content__showmore-wrap__readmore-btn" :style="{
  13. fontSize: fontSize + 'rpx',
  14. color: color
  15. }">
  16. {{ showMore ? openText : closeText }}
  17. </text>
  18. <view class="u-content__showmore-wrap__readmore-btn__icon u-flex">
  19. <u-icon :color="color" :size="fontSize" :name="showMore ? 'arrow-up' : 'arrow-down'"></u-icon>
  20. </view>
  21. </view>
  22. </view>
  23. </template>
  24. <script>
  25. /**
  26. * readMore 阅读更多
  27. * @description 该组件一般用于内容较长,预先收起一部分,点击展开全部内容的场景。
  28. * @tutorial https://www.uviewui.com/components/readMore.html
  29. * @property {String Number} show-height 内容超出此高度才会显示展开全文按钮,单位rpx(默认400)
  30. * @property {Boolean} toggle 展开后是否显示收起按钮(默认false)
  31. * @property {String} close-text 关闭时的提示文字(默认“展开阅读全文”)
  32. * @property {String Number} font-size 提示文字的大小,单位rpx(默认28)
  33. * @property {String} text-indent 段落首行缩进的字符个数(默认2em)
  34. * @property {String} open-text 展开时的提示文字(默认“收起”)
  35. * @property {String} color 提示文字的颜色(默认#2979ff)
  36. * @example <u-read-more><rich-text :nodes="content"></rich-text></u-read-more>
  37. */
  38. export default {
  39. name: "u-read-more",
  40. props: {
  41. // 默认的显示占位高度,单位为rpx
  42. showHeight: {
  43. type: [Number, String],
  44. default: 400
  45. },
  46. // 展开后是否显示"收起"按钮
  47. toggle: {
  48. type: Boolean,
  49. default: false
  50. },
  51. // 关闭时的提示文字
  52. closeText: {
  53. type: String,
  54. default: '展开阅读全文'
  55. },
  56. // 展开时的提示文字
  57. openText: {
  58. type: String,
  59. default: '收起'
  60. },
  61. // 提示的文字颜色
  62. color: {
  63. type: String,
  64. default: '#2979ff'
  65. },
  66. // 提示文字的大小
  67. fontSize: {
  68. type: [String, Number],
  69. default: 28
  70. },
  71. // 是否显示阴影
  72. shadowStyle: {
  73. type: Object,
  74. default () {
  75. return {
  76. backgroundImage: "linear-gradient(-180deg, rgba(255, 255, 255, 0) 0%, #fff 80%)",
  77. paddingTop: "300rpx",
  78. marginTop: "-300rpx"
  79. }
  80. }
  81. },
  82. // 段落首行缩进的字符个数
  83. textIndent: {
  84. type: String,
  85. default: '2em'
  86. },
  87. // open和close事件时,将此参数返回在回调参数中
  88. index: {
  89. type: [Number, String],
  90. default: ''
  91. }
  92. },
  93. watch: {
  94. paramsChange(val) {
  95. this.init();
  96. }
  97. },
  98. computed: {
  99. paramsChange() {
  100. return `${this.toggle}-${this.showHeight}`;
  101. },
  102. // 展开后无需阴影,收起时才需要阴影样式
  103. innerShadowStyle() {
  104. if (this.showMore) return {};
  105. else return this.shadowStyle
  106. }
  107. },
  108. data() {
  109. return {
  110. isLongContent: false, // 是否需要隐藏一部分内容
  111. showMore: false, // 当前隐藏与显示的状态,true-显示,false-收起
  112. elId: this.$u.guid(), // 生成唯一class
  113. };
  114. },
  115. mounted() {
  116. this.$nextTick(function() {
  117. this.init();
  118. })
  119. },
  120. methods: {
  121. init() {
  122. this.$uGetRect('.' + this.elId).then(res => {
  123. // 判断高度,如果真实内容高度大于占位高度,则显示收起与展开的控制按钮
  124. if (res.height > uni.upx2px(this.showHeight)) {
  125. this.isLongContent = true;
  126. this.showMore = false;
  127. }
  128. })
  129. },
  130. // 展开或者收起
  131. toggleReadMore() {
  132. this.showMore = !this.showMore;
  133. // 如果toggle为false,隐藏"收起"部分的内容
  134. if (this.toggle == false) this.isLongContent = false;
  135. // 发出打开或者收齐的事件
  136. this.$emit(this.showMore ? 'open' : 'close', this.index);
  137. }
  138. }
  139. };
  140. </script>
  141. <style lang="scss" scoped>
  142. @import "../../libs/css/style.components.scss";
  143. .u-content {
  144. font-size: 30rpx;
  145. color: $u-content-color;
  146. line-height: 1.8;
  147. text-align: left;
  148. overflow: hidden;
  149. &__show-more {
  150. padding-top: 0;
  151. background: none;
  152. margin-top: 20rpx;
  153. }
  154. &__showmore-wrap {
  155. position: relative;
  156. width: 100%;
  157. padding-bottom: 26rpx;
  158. @include vue-flex;
  159. align-items: center;
  160. justify-content: center;
  161. &__readmore-btn {
  162. @include vue-flex;
  163. align-items: center;
  164. justify-content: center;
  165. line-height: 1;
  166. &__icon {
  167. margin-left: 14rpx;
  168. }
  169. }
  170. }
  171. }
  172. </style>