zhongxia245 / blog

这是一个Blog, 如果喜欢可以订阅,是Watch, 不是 Star 哈。。。
https://zhongxia245.github.io/blog/
160 stars 33 forks source link

【20190911】微信浏览器禁止页面下拉查看网址 #110

Open zhongxia245 opened 5 years ago

zhongxia245 commented 5 years ago

时间:2019-09-11 15:19:36

作者:zhongxia

正常情况下,微信浏览器页面下拉后可以看到一个 『该网页由 xxxx 提供』,因为页面会提供给第三方使用,因此有一个需求是隐藏该网址。

因为页面都是已经存在的,并且有很多个页面,因此想要的解决方案是一个通用的解决方案(至少也得90%页面通用),不去修改具体每个页面的代码。

时间:2019-09-11 16:43:48

突然想了下,觉得需要 一个线上 DEMO,这样后面在看到这个问题,可以找到这个文章的解决方案是否能真的解决这个问题。

线上DEMO 地址,点下面连接。(如果打不开,可能是因为使用 github pages 部署,被微信浏览器给屏蔽了)

https://zhongxia245.github.io/demo/pages/page-scroll/

完整案例源码:点这里 Github

零、补充一点

时间:2019-09-11 22:50:10 根据 @True不想说话 同学的方法,亲测有效,简单粗暴。

可以使用 CSS 来实现这个需求

body:before {
  width: 100%;
  height: 100%;
  content: ' ';
  position: fixed;
  z-index: -1;
  top: 0;
  left: 0;
  background: #fff;
}

线上案例

Iphone7 IOS12 微信浏览器下,亲测有效,其他设备没有测试过

一、思路

解决这个问题,直接 google 一顿搜索,得出下面的结论。

1.1、看微信开发者文档

首先需要查一下微信开发者的文档,看下是JS SDK 有方法可以用来控制这个网址的显示隐藏,遗憾的是,并没有提供这类方法。

1.2、禁止 touchmove 滚动

既然『该网页由 xxxx 提供』是页面已经滑到顶部了继续下拉才出现的,那么禁止页面下拉不就可以解决问题了嘛,小菜一碟。

// 禁止页面滚动
document.body.addEventListener('touchmove', function(e) {
    e.preventDefault()
  }, false)

too young too simple , addEventListener 方法的第三个参数有兼容性问题。

function preventDefault(e) {
    e.preventDefault();
}

// Chrome 51、Firefox 49及以上
// 禁用触摸滚动页面
document.addEventListener('touchmove', preventDefault, {passive: false});
// 恢复触摸滚动页面
document.removeEventListener('touchmove', preventDefault, {passive: false});

// Chrome 51、 Firefox 49以下
document.addEventListener('touchmove', preventDefault, false);
document.removeEventListener('touchmove', preventDefault, false);

现在这个时间点,chrome 78 已经出来了, 因此禁止页面滚动就成了这样。

// 禁止页面滚动
document.body.addEventListener('touchmove', function(e) {
    e.preventDefault()
  }, {passive: false})

这个时候,你会发现,页面的确不能下拉,那么 『该网页由 xxxx 提供』 不就看不到了吗,完美。

1.3、body 不滚动,单需要让 div 容器内部滚动

不过改出新问题了,页面不能滚动了,超过一屏的页面,只能看一半,这谁能忍。因此还需要解决 禁止 touchmove 后,页面滚动的问题。

解决这个问题可以用下面代码,指定的 DIV 容器可以内部滚动,这里就让 react 组件渲染的 DOM 节点 去支持滚动为例。

let overscroll = function(el) {
  el.addEventListener('touchstart', function() {
    let top = el.scrollTop
    let totalScroll = el.scrollHeight
    let currentScroll = top + el.offsetHeight
    //If we're at the top or the bottom of the containers
    //scroll, push up or down one pixel.
    //
    //this prevents the scroll from "passing through" to
    //the body.
    if (top === 0) {
      el.scrollTop = 1
    } else if (currentScroll === totalScroll) {
      el.scrollTop = top - 1
    }
  })
  el.addEventListener('touchmove', function(evt) {
    //if the content is actually scrollable, i.e. the content is long enough
    //that scrolling can occur
    if (el.offsetHeight < el.scrollHeight) evt._isScroller = true
  })
}
overscroll(document.querySelector('#app'))
document.body.addEventListener(
  'touchmove',
  function(evt) {
    console.log(evt._isScroller)
    //In this case, the default behavior is scrolling the body, which
    //would result in an overflow.  Since we don't want that, we preventDefault.
    if (!evt._isScroller) {
      evt.preventDefault()
    }
  },
  { passive: false }
)

只有这个 js 还是有问题的,需要设置一下 #app 的高度,并且超出长度则滚动。

因为div 容器内的滚动效果不太好,没有弹性滚动,就是手指停止滑动,页面就停止滑动了。因为增加了 -webkit-overflow-scrolling: touch; 来加一个弹性滚动效果。

这里在Iphone7 IOS12 下,和一加7 (应该是这个型号) 感觉没有什么问题,体验还可以。但是网上看,使用 这个属性会引发 BUG。

#app {
  height: 100vh;
  overflow: auto;
  -webkit-overflow-scrolling: touch;
}

1.4、注意 -webkit-overflow-scrolling: touch 的 Bug

解决这些问题,可以参考这个文章,文章写的还是比较详细了的,给作者点个赞。 《深入研究-webkit-overflow-scrolling:touch及ios滚动》

Bug 的表现就是:偶尔卡住或不能滑动。

Iphone7, IOS12 下,一直没有复现出来,不知道是不是特定的手机和系统版本才会有这个问题。

解决方案:就是在webkit-overflow-scrolling:touch属性的下一层子元素上,将height加1%或1px。从而主动触发scrollbar

main:after {
    min-height: calc(100% + 1px)
}

当然偶尔卡住了只是其中一个问题, 除此之外,这个属性还有很多bug,包括且不限于以下几种:

1、滚动中 scrollTop 属性不会变化

2、手势可穿过其他元素触发元素滚动

3、滚动时暂停其他 transition

【引用文章作者的原话】

所以目前来看,如果不想那么费心,直接上iScroll或者better-scroll吧,我觉得 better-scroll 还是挺好用的。如果你喜欢偷懒,那么接着用-webkit-overflow-scrolling:touch也没什么问题。

毕竟移动端的水太深了,你永远不知道下一个问题是发生在safari还是x5内核浏览器上。

二、总结一下

PC Web 的时候,开发最苦逼的是 IE 兼容性,现在 Mobile Web 开发,最苦逼的各个手机的兼容性问题。兼容性是前端开发避不开的深坑呀。

解决一个问题,又引发了更多的问题出来,生生不息,无穷尽也。

没有代码就没有 BUG。

这篇文章的内容,就大概下面这些了。

  1. 要解决下拉显示『该网页由 xxxx 提供』
  2. 使用禁止 touchmove 方案
  3. 指定特定 DIV 元素不禁止 touchmove 滚动,让页面可以滚动
  4. div 内部滚动增加弹性滚动
  5. 了解下弹性滚动可能引发的 bug

终、参考文章

1、《微信浏览器禁止页面下拉查看网址(不影响页面内部scroll)》

2、《深入研究-webkit-overflow-scrolling:touch及ios滚动》

3、《[移动端新特性] Passive Event Listeners》

4、《passive 的事件监听器》

5、《移动端禁用及恢复触摸页面滚动》

zhongxia245 commented 5 years ago

建议直接采用 CSS 的解决方案,简单粗暴。不影响页面逻辑。