ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

高扩展弹出层组件设计实现

2022-07-11 12:36:38  阅读:190  来源: 互联网

标签:body 扩展 event huoli 弹出 组件 overflow hidden 弹窗


背景

随着业务的发展,弹窗逐渐替代翻页,承载越来越多的用户需求。由于没有统一、好用的公共弹窗组件,业务同学通常会编写属于自己的弹窗,这造成了一些问题:

  • 用户体验不一致
  • 大量重复代码,不易维护和升级
  • 弹窗滚动穿透
  • 未设置 iPhone 手机底部安全区域

我们急切的需要提供一个公共的弹窗组件,不仅要解决以上问题,还必须满足各种业务需求。

设计分析

分析过往的 UI,最常用的弹窗有下面两种:


由此可以得出如下结论:

  • 组成:弹窗由蒙层和容器组成
  • 位置:容器集中在底部和中间位置,可扩展为:上、右、下、左、中五个位置
  • 容器内容:标题区、内容区、底部区组成
    • 标题:可选,允许显示关闭按钮
    • 内容:自定义,允许滚动
    • 底部:可选

设计实现

解决滚动穿透问题

打开弹窗,给body设置类名hl-overflow-hidden,关闭弹窗则移除。

document.body.classList.add('hl-overflow-hidden');
document.body.classList.remove('hl-overflow-hidden');


.hl-overflow-hidden {
  overflow: hidden!important;
}

解决蒙层滚动穿透,核心在于设置touchmove

<div @touchmove="preventDefault"></div>
function preventDefault(event) {
  if (typeof event.cancelable !== 'boolean' || event.cancelable) {
    event.preventDefault();
  }
  event.stopPropagation()
}

高度自定义容器设计

将容器从上到下分为三个部分:head/body/foot。

head 区既可以便捷设置title,也可完全自定义。

body 区设置为默认插槽,根据内容高度自动设置滚动,并emit滚动事件。

foot 区由用户自定义,默认不展示。

<div class="huoli-popup fx-col" :style="{ height }">
  <div class="huoli-popup-hd">
    <template v-if="title">{{title}}</template>
    <slot v-else name="title"></slot>
    <img v-if="closable" 
    src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAMAAACBVGfHAAAAElBMVEVHcEw0N0o0OEouLkY0N0kwMFAuyLj8AAAABnRSTlMAT4ALcBBngfhBAAAAZUlEQVQoz2NgoA4wgDGYIRSrI0xAJABMmSgJQPiMSs5QWhEiIASTgTLgEjAWXAGUiVAAZSMpAHOQFYCVoCgAKUFRAFKCqgBTAF0LhqHo1mI4DN3pGJ5D9z5GAGEEIUYgY0QDxQAAIDoMW2GxKeQAAAAASUVORK5CYII="
    @click="onClickClose" />
  </div>

  <div class="huoli-popup-bd" @scroll="onScroll">
    <slot></slot>
  </div>

  <div class="huoli-popup-foot"><slot name="foot"></slot></div>
</div>

无依赖简单实现

详见

结合 vant 使用

<template>
  <Popup 
    v-model="show"
    position="bottom"
    round
    :style="{ height, overflow: 'hidden' }"
    get-container="body"
    @close="onClickClose"
  >
    <div class="huoli-popup fx-col">
      <div class="huoli-popup-hd">
        <slot v-else name="title"></slot>
        <img v-if="closable" src="./img/close@2x.png" class="huoli-popup-close-icon" @click="onClickClose" />
      </div>
      <div class="huoli-popup-bd" @scroll="onScroll">
        <slot></slot>
      </div>
      <div class="huoli-popup-foot"><slot name="foot"></slot></div>
    </div>
  </Popup>
</template>

<script>
import { Popup } from "huoli-ui"
export default {
  name: 'huoli-popup',
  props: {
    show: {
      type: Boolean,
      default: false,
    },
    closable: {
      type: Boolean,
      default: false,
    },
    height: {
      type: String,
      default: ',
    },
  },
  components: {
    Popup
  },
  methods: {
    onClickClose() {
      this.$emit('hide');
    },
    onScroll: throttle(function(e) {
      this.$emit('scroll', e)
    })
  }
}
function throttle(func, wait = 50, immediate) {
  let timeout
  return function() {
    const context = this;
    const args = arguments;
    if (immediate) {
      func.apply(context, args);
      immediate = false
    }

    if (timeout) return

    timeout = setTimeout(function() {
      timeout = null;
      func.apply(context, args)
    }, wait);
  }
}
</script>

<style lang="scss">
.huoli-popup {
  height: 100%;
  .huoli-popup-hd {
    min-height: 48px;
    width: 100%;
    background: inherit;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: center;

    font-size: 16px;
    font-weight: 400;
    color: #262626;
    line-height: 20px;
  }
  .huoli-popup-close-icon {
    position: absolute;
    width: 16px;
    height: 16px;
    right: 16px;
    top: 16px;
  }
  .huoli-popup-bd {
    flex: 1;
    box-sizing: border-box;
    overflow-y: auto;
  }
}
</style>

标签:body,扩展,event,huoli,弹出,组件,overflow,hidden,弹窗
来源: https://www.cnblogs.com/fayin/p/16465973.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有