把H5问题记在本子上

844 阅读3分钟

时光不负,创作不停,本文正在参加2021年终总结征文大赛

总结了一些平时在开发H5的时候遇到的问题,和解决方案,还有一些自己用的比较多的js,如有不对的地方,请大佬们轻喷。如果jio的还可以的话,麻烦大佬们点个赞支持一下,蟹蟹!!!

1、修复点击无效问题

问题说明:在iOS系统上有些情况下非可点击元素监听click事件可能会无效
解决方案:

  • 换成<button>或者<a>标签来绑定click事件
  • 只需对不触发click事件的标签声明css属性 cursor: pointer

2、阻止默认滚动穿透

问题说明:在iOS系统中,如果使用第三方滚动组件的话,就会出现系统自带滚动和组件同时发生滚动,这个时候就会导致上拉或者下拉出现白边。 解决方案:

document.body.addEventListener('touchmove', function(e) {
  e.preventDefault();
}, {
  passive: false // 是否让 阻止默认行为(preventDefault()) 失效
});

3、iOS/Android中的浏览器(H5)中唤起本地APP解决方案

问题说明:在APP未安装情况下,引导用户下载后打开APP后,如何进入之前唤起时指定的页面或内容。用户点击了页面的对应唤起APP的操作,页面就会无任何的交互,用户体验就有一些不友好。

解决方案:

  • 设置比较小的运行间隔(< 30ms),在浏览器或者webview中,应用切换到后台,setInterval会被很明显的延迟执行,比如设置一个运行间隔20ms,总计运行100次的定时器,如果页面一直处于前台,则100次跑完,总耗时与100x20=2000ms不会有太大差异,但页面在后台运行时,此时间会明显超过2000ms。可以利用这一点来实现是否成功打开APP检测及回调。来自参考文章。代码如下:
// 模拟检测跳是否转到APP
let checkOpen = function (callBack) {
  let clickTime = +(new Date());
  function check(elsTime) {
    // 判断定时器是否大于3000ms or 浏览器是否切换到手机的后台
    if (elsTime > 3000 || document.hidden || document.webkitHidden) {
      callBack(1);
    } else {
      callBack(0);
    }
  }

  // 启动间隔20ms运行的定时器,并检测累计消耗时间是否超过3000ms,超过则结束
  let count = 0,
    timer;
  timer = setInterval(() => {
    count++;
    let elsTime = +(new Date()) - clickTime;
    if (count >= 100 || elsTime > 3000) {
      clearInterval(timer);
      check(elsTime);
    }
  }, 20);
}

checkOpen(function (opened) {
  if (opened === 0) {
    console.log("跳转失败!!!!");
  }
  else if(opened === 1){
    console.log("跳转成功!!!!");
  }
});

4、输入框设置属性type = number

问题说明:设置type = 'number'的时候,maxlength不起效,当设置这个属性,可以用以下的css去掉默认样式

// HTML5去掉输入框type为number时的上下箭头的实现方法
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  appearance: none;
  margin: 0;
}
input {
  -moz-appearance: textfield;
}

5、动态加载css

代码如下:

function loadCss(url) {
  var css = document.createElement('link');
  if (!url) {
    return;
  }
  css.type = 'text/css';
  css.rel = 'stylesheet';
  css.href = url;
  document.getElementsByTagName("head")[0].appendChild(css);
}

6、动态加载js

代码如下:

function loadJs(url, callback) {//链接、回调
  var done = false,
    script = document.createElement('script');
  if (!url) {
    return;
  }
  script.type = 'text/javascript';
  script.src = url;
  script.onload = script.onreadystatechange = function () {
    if (!done && (!script.readyState || script.readyState == 'loaded' || script.readyState == 'complete')) {
      done = true;
      script.onload = script.onreadystatechange = null;
      if (callback) {
        callback();
      }
    }
  };
  document.getElementsByTagName('head')[0].appendChild(script);
}

7、针对高德地图marker绑定点击事件

问题说明:在移动端中,通过请求动态渲染高德地图API标记的图标,并且绑定点击事件,触发不了里面的逻辑。 解决方案:在点击事件里面,添增一个setTimeout延迟处理

代码如下:

var marker = new AMap.Marker({
  title: 'default-marker-1',
  icon: new AMap.Icon({
    size: new AMap.Size(51, 59), //图标大小
    image: "/static/images/app-module/sticker/node-1.png",
    imageOffset: new AMap.Pixel(0, 0)
  }),
  position: [113.323816, 23.110288]
});
marker.setMap(map);
marker.on('click', markerClick);

function markerClick(e) {
  setTimeout(() => {
  // 业务逻辑
  }, 0);
}

如果想了解一些规则的css图案,请点击这里

如果想了解一些css知识点和小技巧,请点击这里