quanyawei
2024-07-04 1e71dd86f6d0c4fc7e5143600d4bc4b50992a2a7
uni_modules/uview-ui/components/u-read-more/u-read-more.vue
New file
@@ -0,0 +1,157 @@
<template>
   <view class="u-read-more">
      <view
          class="u-read-more__content"
          :style="{
            height: isLongContent && status === 'close' ? $u.addUnit(showHeight) : $u.addUnit(contentHeight),
            textIndent: textIndent
         }"
      >
         <view
             class="u-read-more__content__inner"
             ref="u-read-more__content__inner"
             :class="[elId]"
         >
            <slot></slot>
         </view>
      </view>
      <view
          class="u-read-more__toggle"
          :style="[innerShadowStyle]"
          v-if="isLongContent"
      >
         <slot name="toggle">
            <view
                class="u-read-more__toggle__text"
                @tap="toggleReadMore"
            >
               <u--text
                   :text="status === 'close' ? closeText : openText"
                   :color="color"
                   :size="fontSize"
                   :lineHeight="fontSize"
                   margin="0 5px 0 0"
               ></u--text>
               <view class="u-read-more__toggle__icon">
                  <u-icon
                      :color="color"
                      :size="fontSize + 2"
                      :name="status === 'close' ? 'arrow-down' : 'arrow-up'"
                  ></u-icon>
               </view>
            </view>
         </slot>
      </view>
   </view>
</template>
<script>
   // #ifdef APP-NVUE
   const dom = uni.requireNativePlugin('dom')
   // #endif
   import props from './props.js';
   /**
    * readMore 阅读更多
    * @description 该组件一般用于内容较长,预先收起一部分,点击展开全部内容的场景。
    * @tutorial https://www.uviewui.com/components/readMore.html
    * @property {String | Number}   showHeight   内容超出此高度才会显示展开全文按钮,单位px(默认 400 )
    * @property {Boolean}         toggle      展开后是否显示收起按钮(默认 false )
    * @property {String}         closeText   关闭时的提示文字(默认 '展开阅读全文' )
    * @property {String}         openText   展开时的提示文字(默认 '收起' )
    * @property {String}         color      提示文字的颜色(默认 '#2979ff' )
    * @property {String | Number}   fontSize   提示文字的大小,单位px (默认 14 )
    * @property {Object}         shadowStyle   显示阴影的样式
    * @property {String}         textIndent   段落首行缩进的字符个数 (默认 '2em' )
    * @property {String | Number}   name      用于在 open 和 close 事件中当作回调参数返回
    * @event {Function} open 内容被展开时触发
    * @event {Function} close 内容被收起时触发
    * @example <u-read-more><rich-text :nodes="content"></rich-text></u-read-more>
    */
   export default {
      name: 'u-read-more',
      mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
      data() {
         return {
            isLongContent: false, // 是否需要隐藏一部分内容
            status: 'close', // 当前隐藏与显示的状态,close-收起状态,open-展开状态
            elId: uni.$u.guid(), // 生成唯一class
            contentHeight: 100, // 内容高度
         }
      },
      computed: {
         // 展开后无需阴影,收起时才需要阴影样式
         innerShadowStyle() {
            if (this.status === 'open') return {}
            else return this.shadowStyle
         }
      },
      mounted() {
         this.init()
      },
      methods: {
         async init() {
            this.getContentHeight().then(height => {
               this.contentHeight = height
               // 判断高度,如果真实内容高度大于占位高度,则显示收起与展开的控制按钮
               if (height > uni.$u.getPx(this.showHeight)) {
                  this.isLongContent = true
                  this.status = 'close'
               }
            })
         },
         // 获取内容的高度
         async getContentHeight() {
            // 延时一定时间再获取节点
            await uni.$u.sleep(30)
            return new Promise(resolve => {
               // #ifndef APP-NVUE
               this.$uGetRect('.' + this.elId).then(res => {
                  resolve(res.height)
               })
               // #endif
               // #ifdef APP-NVUE
               const ref = this.$refs['u-read-more__content__inner']
               dom.getComponentRect(ref, (res) => {
                  resolve(res.size.height)
               })
               // #endif
            })
         },
         // 展开或者收起
         toggleReadMore() {
            this.status = this.status === 'close' ? 'open' : 'close'
            // 如果toggle为false,隐藏"收起"部分的内容
            if (this.toggle == false) this.isLongContent = false
            // 发出打开或者收齐的事件
            this.$emit(this.status, this.name)
         }
      }
   }
</script>
<style lang="scss" scoped>
@import "../../libs/css/components.scss";
.u-read-more {
   &__content {
      overflow: hidden;
      color: $u-content-color;
      font-size: 15px;
      text-align: left;
   }
   &__toggle {
      @include flex;
      justify-content: center;
      &__text {
         @include flex;
         align-items: center;
         justify-content: center;
         margin-top: 5px;
      }
   }
}
</style>