移動端 彈窗-內容可滾動,背景不動


實際開發中,總免不了使用彈窗,如果彈窗比較短,內容不需要滑動,那還好處理,vue中直接阻止滑動就可以了,但是如果彈窗內的內容需要滑動,那就有點麻煩了,之前看到的方案都是給body設置fixed,但是事實上都不是很好,還好,網上找了一種解決方案,實現思路比較簡單直接,滑動的時候監聽touch事件,通過target來判斷滑動的是誰,如果是遮罩層,那么直接preventDefault(),當然,這還沒完,還需要處理滑動的邊界情況,在最頂部以及最底部,此時,如果繼續滑動的話,底部的內容依然會滑動,所以,在邊界情況下還是需要阻止滑動,下面以自己實現的mask組件為例來說明把,其實這基本就實現了需求

話不多說,下面附上自己寫的一個通用組件

<template>
  <div class="lo-mask" @touchstart="start" @touchmove="move" @touchend="end">
    <div class="mask-container" ref="container">
      <p v-for="val in 20">{{val}}</p>
      <div class="content">
        <slot name="title"></slot>
        <slot name="content"></slot>
      </div>
      <footer>
        <button v-if="cancel"  @click="cancelBtn" class="btn cancel">{{cancel}}</button>
        <span class="line" v-if="cancel&&confirm"></span>
        <button  v-if="confirm"  @click="successBtn" class="btn">{{confirm}}</button>
      </footer>
    </div>
  </div>

</template>

<script>
  export default {
    name: 'loMask',
    props: {
      cancel: {
        type: String,
        default: ''
      },
      confirm: {
        type: String,
        default: ''
      }
    },
    data() {
      return {
        startY: 0
      }
    },
    methods: {
      successBtn() {},
      cancelBtn() {},

      start(e) {
        // console.log(e.target);
        // let target = e.target;
        // console.log(target.className);
        console.log(e);
        this.startY = e.touches[0].clientY;
      },
      move(e) {
        // console.log(e.target);
        // e.preventDefault()
        let container = this.$refs.container;
        let target = e.target;

        let sTop = container.scrollTop,       // 滾動的高度    (滾動卷去的高度)
            sHeight = container.scrollHeight, // 可滾動的高度  (實際總高度)
            vHeight = container.offsetHeight; // 視窗的高度    (可視區域高度)
        if (target.className === 'lo-mask') {
          e.preventDefault()
        }
        let newY = e.touches[0].clientY;
        let dis = newY - this.startY;

        if (dis > 0) {
          // 向下
          if (sTop <= 0&& e.cancelable) { //是否是最上面
            e.preventDefault()
          }
        } else {
          // 向上
          if (sTop + vHeight >= sHeight&& e.cancelable) { //是否滑動到底了
            e.preventDefault()
          }
        }
      },
      end() {}
    }
  }
</script>

<style scoped lang="scss">
  .lo-mask{
    position: fixed;
    width: 100%;
    height: 100%;
    background:rgba(0, 0, 0, 0.7);
    z-index: 50;
    top: 0;
    left: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding-left: 0.2rem;
    padding-right: 0.2rem;
    overflow: auto;
  }
  .mask-container{
    position: relative;
    display: flex;
    flex-direction: column;
    width: 2.7rem;
    min-height: 1.5rem;
    max-height: 2rem;
    overflow-y: scroll;
    background-color: #fff;
    border-radius: 0.08rem;
    box-shadow: 0 3px 19px rgba(89, 89, 89, 0.85);
  }
  .content{
    flex: 1;
  }
  footer{
    display: flex;
    box-sizing: content-box;
    align-items: center;
    justify-content: space-around;
    width: 100%;
    height: 0.4rem;
    background-color: #f7f7f7;
    border-top: 1px solid #E2E2E2;
    border-radius: 0 0 0.08rem 0.08rem;
    .btn{
      flex: 1;
      height: 0.4rem;
      color: #E9327B;
      font-size: 0.17rem;
      font-weight: bold;
    }
    .line{
      width: 1px;
      height: 0.4rem;
      background-color: #E2E2E2;
    }
  }

</style>

直接復制過去就可以用,還是不錯的
自己測試了下,效果還行,不過vant-ui里面的popup組件就可以實現上述效果,大家可以引用vant-ui 的這個組件來使用


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM