美文网首页
如何实现区域内展开收起和悬浮展示收起按钮功能

如何实现区域内展开收起和悬浮展示收起按钮功能

作者: Angrybird233 | 来源:发表于2023-09-06 15:03 被阅读0次

    应用场景

    • 当列表内容很长时,需要滑倒最底部才能查看下一条数据,这时可以使用该组件的交互来优化使用体验。收起当前一条,继续展开查看下一条数据。


      image.png

    组件思路

    判断同时满足以下两个条件时,悬浮展示收起按钮

    1. 展开的内容的盒子的左上角坐标的Y值即top + 收起按钮的高度 <= 当前浏览器窗口的可视区域高度clientHeight
    2. 展开的内容的盒子的右下角坐标的Y值即bottom > 当前浏览器窗口的可视区域高度clientHeight


      image.png
    <template>
      <div class="collapse-item">
        <div class="source">
          <slot name="source"></slot>
        </div>
        <div class="collapse-panel">
          <div class="panel">
            <div
              class="panel-content"
              ref="panel-content"
              :style="{ '--panelMinHeight': minHeight + 'px', '--panelHeight': panelHeight }"
              :class="isExpanded ? 'active' : ''"
            >
              <slot></slot>
            </div>
            <div
              class="expand-btn height-96 flex-center"
              @click="togglePanel"
              :class="{ 'is-fixed': fixedControl }"
              v-if="isExpandShow"
            >
              <span class="color-main">{{ isExpanded ? "收起" : "展开" }}</span>
              <img
                src="@/assets/databoard/arrow-fold.png"
                class="expand-icon width-24 height-22 m-l-10"
                :class="!isExpanded ? '' : 'icon-reverse'"
              />
            </div>
          </div>
        </div>
      </div>
    </template>
    <script>
    export default {
      name: "CollapseItem",
      props: {
        minHeight: {
          type: Number,
          default: 0
        },
        isExpandShow: {
          type: Boolean,
          default: false
        }
      },
      data() {
        return {
          isExpanded: false,
          panelHeight: 0, // 展开内容高度
          fixedControl: false, // 固定收起按钮控制
          scrollTop: 0 // 展开之前的滚动位置
        };
      },
      watch: {
        isExpanded(val) {
          if (!val) {
            this.fixedControl = false;
            this.removeScrollHandler();
            window.scrollTo({
              top: this.scrollTop
            });
            return;
          }
          const timer = setTimeout(() => {
            window.addEventListener("scroll", this.scrollHandler);
            this.scrollHandler();
            clearTimeout(timer);
          }, 100);
        }
      },
      methods: {
        // 切换展开收起状态
        togglePanel() {
          if (!this.panelHeight) {
            const panel = this.$refs["panel-content"];
            const panelHeight = panel.scrollHeight;
            this.panelHeight = panelHeight + "px";
          }
          this.isExpanded = !this.isExpanded;
          this.$nextTick(() => {
            this.scrollTop = document.documentElement.scrollTop;
          });
        },
        // 监听滚动事件,控制收起按钮展示和隐藏
        scrollHandler() {
          const { top, bottom } = this.$refs["panel-content"].getBoundingClientRect();
          const clientHeight = document.documentElement.clientHeight;
          this.fixedControl = bottom > clientHeight && top + 48 <= clientHeight;
        },
        // 移除滚动事件
        removeScrollHandler() {
          window.removeEventListener("scroll", this.scrollHandler);
        }
      },
      beforeDestroy() {
        this.removeScrollHandler();
      }
    };
    </script>
    <style lang="less" scoped>
    .collapse-panel {
      .panel-content {
        width: 100%;
        height: var(--panelMinHeight);
        overflow-y: hidden;
        overflow-x: visible;
        transition: height 0.2s;
      }
    
      .active {
        height: var(--panelHeight);
      }
      .expand-btn {
        .expand-icon {
          transition: all 0.2s;
        }
        .icon-reverse {
          transform: rotate(180deg);
        }
      }
      .is-fixed {
        position: fixed;
        bottom: 0px;
        background: #fff;
        width: 100%;
        left: 0;
        box-shadow: 0px -8px 24px 1px rgba(0, 0, 0, 0.1);
      }
    }
    </style>
    
    

    相关文章

      网友评论

          本文标题:如何实现区域内展开收起和悬浮展示收起按钮功能

          本文链接:https://www.haomeiwen.com/subject/pxikvdtx.html