移动端模态窗口的滚动和橡皮筋问题解决方案

1、什么是模态窗口[浮层]?

    模态窗口就是用户只能与该窗口进行交互,而其他用户界面收不到输入信息。只有关闭该窗口后,其他界面才能与用户交互,且仍可以读取模态窗口中的信息。 
    其特点就是:
        a、用户的交互被锁定在该窗口[浮层]上;
        b、窗口关闭时,未被实际销毁,仍然可以读取窗口相关的信息。
    以vue组件为例子,实现一个模态窗口[浮层]~我们将使用v-show来控制窗口的展现,如此其变量[状态]都保存在内存当中,不被销毁;当关闭以后,再次打开,依然能保留上次的操作状态。这就初步创建了一个模态窗口。
 

2、移动端上web模态浮层的交互问题:滑屏联动、ios橡皮筋

  上例中创建的模态窗口可实现b特点,即保留状态,但无法实现交互的完全锁定。这里咱们来解决其中的两个交互问题:滑屏联动、ios橡皮筋。
  滚屏联动,就是在上层窗口[浮层]滚动,下层内容区域跟随一起滚动。如果在ios下,还会出现橡皮筋问题。这都违背了模态窗口的第一个特点,交互应被锁定在窗口上。这些问题实质上都是由touch事件触发,所以解决问题的关键就是如何处理touch事件。
  最终的解决方案如下,禁用全局touchmove,窗体内的touchmove自定义。具体操作如下:
    step1:窗口开启时,禁用全局touchmove事件;[防止触发滚动及橡皮筋这类touch事件]
    step2:对窗口内需要touchmove事件的部分进行功能自定义;[如窗口内的scroll]
    step3:窗口关闭时,解除全局touchmove事件的绑定。
 

3、实例:解决模态下的scroll及橡皮筋问题 

   step1:窗口开启时,禁用全局touchmove
// 模态弹窗模式下,禁止滚动及ios下的橡皮筋效果
document.addEventListener('touchmove', this.stopScroll, false)
stopScroll(event) {
  // 使用阻止默认事件,来阻止scroll和橡皮筋
  event.preventDefault()  
}

    通过设置event.preventDefault(),禁止touchmove事件的默认操作。将监听绑定在document上,实现全局禁止。[橡皮筋效果解决]

  

  step2:自定义窗口内的scroll事件

    由于全局touchmove事件禁用,窗体内的scroll也受其影响,无法滚动;所以需要自定义窗体内的scroll。    

  stopScroll(event) {
    // 使用阻止默认事件,来阻止scroll和橡皮筋  
    event.preventDefault()  
 
    // 对弹窗区域允许滚动,并自定义滚动方式
    // 判断触发touchmove的元素是否为滚动区域内的元素?如果是,则自定义scroll功能
    this.pElem = this.isInnerParents(event.target, 'aui-popup__bd')
    if (this.pElem) {
      this.movePosList.push(this.startPos - event.touches[0].pageY)
      let len = this.movePosList.length
      this.pElem.scrollTop += this.movePosList[len - 1] - this.movePosList[len - 2]  
    }
  } 

    其中的stopScroll函数与step1中相同,在阻止touchmove事件默认操作的同时,处理自定义功能。进入自定义功能的条件是,事件触发元素在scroll区域内。[滚屏联动解决]

  step3:窗口关闭时,解除全局touchmove事件的绑定

// 关闭弹窗时,释放touchmove
document.removeEventListener('touchmove', this.stopScroll, false)

 

4、关于web端模态窗口交互的几点思考

        a、禁用掉引发全局交互的事件,及窗体内受禁用影响的相应交互操作的抽象。如禁用touchmove事件,窗体内受禁用影响的内容滚动、滑屏轮播等的抽象。
        b、相应表单操作的处理。如表单项的聚焦,使用tab切换时,该切换操作应保留在窗体内;窗口打开时,聚焦应移动之模态窗口内等。

      

原文地址:https://www.cnblogs.com/hity-tt/p/7093637.html