整体问题应该是,在现有页面唤起输入框或是其他需要悬浮显示的 dom,如何将悬浮 dom 下面的那一层原有页面固定住,不被 touchmove 事件触发。

前因

原有页面在实现了前面的上拉加载后基本没什么大的问题了,但测试同学在测试输入框的时候发现,因为事先页面的 z-index 值问题,输入框唤起后,前面添加的 loading 会覆盖在输入框上面,这里我紧急调整了页面的层级对这个问题进行了修复。然后就进而有了固定背景层的需求了。。。

解决过程

事实上一开始我在该页面添加输入框的时候,就考虑到了背景层固定的问题,也引入了对应的 temporyRepair() 方法

但是我忽略了 IOS 这一问题。IOS 的稳定、封闭真让人脑壳大。

const temporaryRepair = () => {
    var currentPosition, timer;
    var speed = 1; //页面滚动距离
    timer = setInterval(function() {
        currentPosition = document.documentElement.scrollTop || document.body.scrollTop;
        // console.log(currentPosition, 'currentPosition');
        // 防止页面产生抖动
        currentPosition -= speed;
        window.scrollTo(0, currentPosition); //页面向上滚动
        currentPosition += speed; //speed变量
        window.scrollTo(0, currentPosition); //页面向下滚动
        clearInterval(timer);
    }, 1);
};

currentPosition ± 1 实测是为了让页面不产生撕裂般的抖动所添加。

对与 IOS,这里引入了下面的通用处理方法,因为以前的项目都是用这个方法处理的,我也就想当然的认为我这个页面用上后就不会出现问题,事实证明我想多了。

const ModalHelper = (function(bodyCls) {
    let scroll;
    return {
        afterOpen: function() {
            scroll = document.scrollingElement.scrollTop;
            setScrollTopFix(document.scrollingElement.scrollTop);
            document.body.classList.add(bodyCls);
            document.body.style.top = -scroll + 'px';

        },
        beforeClose: function() {
            document.body.classList.remove(bodyCls);
            document.scrollingElement.scrollTop = scrollTopFix;
            document.body.style.top = 0 + 'px';
        }
    };
})('modal-open');
.modal-open {
    overflow: hidden !important;
    height: 100%;
    position: fixed;

    &,
    body {
        overflow: hidden;
        height: 100%;
        position: fixed;
    }
}

我们在唤起输入框的时候就执行 afterOpen() 方法,将对应的 css 添加到 dom 上,在需要关闭输入框的时候执行 beforeClose() 方法将相应的 css 移除即可,是不是看起来没什么问题,然而真正应用的时候我发现效果并未达到。

多次对 dom 以及对应方法中的scrollTop 进行检查后才发现,存在了以下几个问题:

  1. 需要定位滚动的 dom,而不是随意监听 body
  2. 在 IOS 端有可能获取不到对应的高度
  3. afterOpen() 中的变量修改值无法传递到 beforeClose() 方法中

于是先开始修改页面各个层级的 dom css 吧,也是这时候我才发现,现有的页面 div 嵌套层级过多,对修改产生了不小的问题,当然后续也是在飞哥帮助下解决了。

对于 IOS 获取不到 dom 对应高度,后续页面定位好后这一问题也消失了,但是一开始我是使用了 dom.scrollTop || window.pageYOffset 多种条件去获取。

关于 afterOpen() 中的变量修改值无法传递到 beforeClose() 方法中,因为一直没有一个更好的解决方式,这里使用了 useState() 将方法触发时的值存入了 state,在关闭的时候就可以直接从 state 中获取。

结语

这次可以说是基本把该碰到的问题都试了一次,当然相应的后续如果再有同样的问题,可能不能说游刃有余的解决,但总归不会像现在这样慌慌张张,而是有条理,有方法的去一步步处理了。

Last modification:November 15th, 2020 at 05:42 pm
如果觉得我的文章对你有用,请随意赞赏