Web兼容性笔记

关于懒狗开始记笔记的备注

在协助调试修改的过程中,某些兼容性问题不记录真的愧对摸鱼仔的称呼

一、區分ios & Android 環境


  function initForPhone() {

    var userAgent = navigator.userAgent.toLowerCase();
    var deviceBrand = "";
    var osVersion = "";

    // Judge whether to is ios device
    if (/iphone|ipod|ipad/i.test(userAgent)) {
      deviceBrand = "Apple";

      // Get the ios version
      var noarmalOs = userAgent.match(/os (\d+)[._](\d+)[._](\d+)?/);

      if (null != noarmalOs) {
        osVersion =
          noarmalOs[1] + "." + noarmalOs[2] + "." + (noarmalOs[3] || 0);
      } else {
        //for  ipad and ipad mini
        osVersion = userAgent.match(
          /\(ipad;\s[\w.]+\s[0-9_.a-z]+\s([0-9_]+)[\w\s]+\)/i
        )[1];
        deviceBrand = "ipad";
      }

      // Judge whether to is Andrioid device
    } else if (/android/i.test(userAgent)) {
      try {
        let normalBrand = userAgent.match(/(zh-cn;)?([\w\s-]+)\sbuild/i);
        if (null == normalBrand) {
          //For more advanced mobile phones
          deviceBrand = userAgent.match(/\(linux;[\s\w.]+;\s([\w-\s]+)\)/i)[1];
        } else {
          deviceBrand = normalBrand[2];
        }
        osVersion = userAgent.match(/android\s([0-9\.]*)/)[1];
      } catch (e) {
        deviceBrand = "android";
      }
    }
    let config = {}
    config.model = deviceBrand;
    config.osVersion = osVersion;
    return config;
  }

A、ios兼容性问题

1、 ios15 系列(网址栏下移问题)

ios15以及ios15.1新版优化,网址展示端移至最下端,约为52px

2、ios web端自动放大问题(点击输入框)

找meta方法,基本都是浪费时间,建议直接font-size 大于或等于16即可。

B、 Android兼容性问题

1、replaceAll not a function

是关于部分手机的webview 采用的内核版本过低的问题

   String.prototype.replaceAll = function (search, replacement) {
        let target = this;
        return target.replace(new RegExp(search, 'g'), replacement);
    };

三、无障碍兼容性问题

1、焦点问题(不按照tabindex移动)

采用手工管理的方式,控制所有需要流动的焦点
整体思路
①整理所有需要按需移动的元素
②监听需要截取的元素区域,切换至上一个或下一个时,为其手动匹配聚焦元素(同时忽略掉默认事件)

①初始化方法

使得所有需要监听的元素就位,初始化初始与结束节点,保证循环聚焦且不干扰区域外的聚焦动作

··· 预设全局参数···
//原有焦點(初始焦点)
var focusedElementBeforeModal;
//元素集合(若监听的元素为可增加,通常为变动的)
var focusElement = [];
//需要监听的元素选择器
var focusElementString = "div.cont,.chat-txt a";
//最开始的元素
var firstTabStart;
//最后的一个元素(若监听的元素为可增加,通常为变动的)
var lastTabStop;
//需要监听的内容外框,也就是只会监听这个元素下的内容焦点变化
var listenWindowSelector = ".chat-window";
··· 预设全局参数结束···
/**
*@todo 初始化方法,获取当前存在的元素
*/
function focuslistens() {
    focusmodal = document.querySelector(listenWindowSelector);
    //初始化当前焦点状态
    focusedElementBeforeModal = document.activeElement;
    focusmodal.addEventListener("keydown", trapTabKey);
    //获取
    focusElement = focusmodal.querySelectorAll(focusElementString)
    //初始化最开始的元素内容
    firstTabStart = focusElement[0];
    //更新最后一个元素的内容
    lastTabStop = focusElement[focusElement.length - 1];
    //需要监听的元素
	let listenWindow = $(".chat-window")[0];
	//焦点监听方法
   function trapTabKey(e) {
        //监听Tab键输入 ,同时判断是否处于监听内容之内
        if (e.keyCode === 9 && e.path.includes(listenWindow)) {
            // SHIFT + TAB
            if (e.shiftKey) {
            //滑动至最后一个时,更新到最开始的元素
                if (document.activeElement === firstTabStart) {
                    e.preventDefault();
                    lastTabStop.focus();
                   }
            // TAB
            } else {
                if (document.activeElement === lastTabStop) {
                    e.preventDefault();
                    firstTabStart.focus();
                }
            }
        }
    }
}
②更新元素方法

实际上元素总是动态增加的,固定的不常有,因此补充动态监听,放置在会触发更新元素的方法后即可。

function upgradeELement() {
	//重新获取元素内容,避免元素删除或增加导致聚焦点不符合预期
    focusElement = focusmodal.querySelectorAll(focusElementString)
    //更新末尾焦点
    lastTabStop = focusElement[focusElement.length - 1];
    //更新首位焦点(通常不会出现首位焦点变动,为保障,还是保留)
    firstTabStart = focusElement[0];
}

四、pc瀏覽器兼容性問題

1、第三方cookies即将退出历史舞台的问题

针对这个问题,通常只会影响嵌入的网站,若为自己的网站可以略过。
具体表现为: 浏览器会默认禁止第三方获取cookies内容。
等同于: 为cookies增加了httpOnly

①避免报错情况

利用自定义属性来避免调用到禁止第三方设置的浏览器爆出异常,无法运行。
但无法替代正常cookies来存储信息,相当于本地变量

    try {
        storage.item = window.localStorage
    } catch (e) {
        //unsupport  thrid cookies
        storage = {
            map: {},
            clean: function () {
                storage.map = {};
            },
            setItem: function (key, val) {
                storage.map[key] = val;
            },
            getItem: function (key) {
                let restult = storage.map[key];
                if (undefined == restult) {
                    return null;
                } else {
                    return restult;
                }
            }
        }
    }
②间接与主站操作cookies

可以采用如HTML自带postMessage处理:
可以不担心针对跨域问题,只需要有页面父子嵌套关系即可

整体使用两个方法:

一、 postMessage:
param1:传输内容,可以任意格式,当然建议结构化的数据
param2:iframe所绑定的url(协议、主机地址或端口三者匹配才可),当然也可以使用 *匹配任意origin,但是不安全所以不推荐。(摸鱼不要太过分)
————————————————
二、 window.addEventListener
param1:监听这个事件,只能使用message
param2

  • data
    从其他 window 中传递过来的对象。
  • origin
    调用 postMessage 时消息发送方窗口的 origin .可以简单认为是url
  • source
    对发送消息的窗口对象的引用,如果是iframe可以不需要使用

示例如下,父子页面为嵌套iframe模式

父页面

// 设嵌套的iframe 对应id为 demo
// 获取对象
var demoIframe = document.getElementById('demo');
var url = 'https://coffeeandice.cn';
function judge(event){
	let origin = event.origin;
	if(origin == window.location.origin){
		ifr.contentWindow.postMessage("连接好了", url );
	}else{
		ifr.contentWindow.postMessage("不是需要连接的origin", url );
	}
}
··· 初始化内容···

// 参数一:可以自定义数值
// 参数二:对应要传输消息的iframe绑定的url,也就是 demoIframe 对应的url
ifr.contentWindow.postMessage("{'type':'1','content':'hi','id':'ringo'}", url );
window.addEventListener('message',judge)

··· 初始化结束···

子页面

function judge(event){
	let origin = event.origin;
	if(origin == window.location.origin){
		//这里是top直接可以引用父页面
		//若非引用,则可以使用event.source
		top.contentWindow.postMessage("连接好了", url );
	}else{
	   //完全不回应
	}
}
··· 初始化内容···

window.addEventListener('message',judge)

··· 初始化结束···

五、脚本工具兼容性问题

1、jquery.autocomplete(自动补全)(缺少节流)

本人主要是使用 14.10版本
由于某些版本浏览器样式或功能有冲突导致无法展示,所以懒狗还是自己求自己。
节流功能:记得再补充

懒狗思路:

整体上采取倒序匹配的方式来匹配答案,利用全局变量避免重复请求的问题
主要分为以下注意点:
①全量匹配模式
②分段匹配模式
(1)从输入内容后面开始裁剪
(2)分段模式下但凡长度不为零都可裁减匹配
③匹配值存储
④避免拼音干扰

简单实现:

数据源

[
"你好呀",
"你好呀,吃饭没",
"你妈叫你吃饭""你爸叫你回家吃饭"
]
//定义最小匹配长度
let minLimit = 2;
/*
*@todo 利用类map来收集存储数据,整体结构为k-array
* eg: {'你好',["你好呀",”你好呀,吃饭没“]}
*/
let smartTipsGather ={};

/**
* @todo 定义处理方法
* @return 返回匹配值
*/
smartTipsMatchHandler(input=>{
//精准匹配内容
let accurateAnswer = "";
//检测本地变量种是否存在内容
let dataGather = smartTipsGather;
//匹配的内容
let matchAnswer = "";
//截取后待匹配的值
let vague = input;

//@todo 精准匹配,顾名思义全量匹配
accurateAnswer = dataGather[input];
	
/**
* @todo 分段匹配模式(取决实际,一般为前缀)
*    其实这里有很多玩法,各种匹配方式很爽
**/
if (!(Array.isArray(accurateAnswer))) {
	  //初始化截断匹配答案
     let vagueAnswer = "";
     //判断可截断长度
     let vagueLastIndex = param.length;
     //当未匹配且还可继续截断时,继续进入下一个循环
     while (!rematch(vague) && vague.length > minLimit) {
         if (!rematch(vague)) {
         	//截取提问,进入下一个循环
             vague = param.substring(0, vagueLastIndex--);
         }
     }
     //当匹配成功,返回数据
     vagueAnswer = rematch(vague);
     if (vagueAnswer.length > 0) {
         matchAnswer = vagueAnswer;
     }
 } else {
     matchAnswer = accurateAnswer;
 }

/**
* @todo 反向匹配
*/
function rematch(vague) {
    let vagueAnswer = "";
    for (let op in dataGather) {
        if (vague.indexOf(op) != -1) {
            vagueAnswer = op;
            break;
        }
    }
    return vagueAnswer;
};

/**
  * @todo network support
  * 判断匹配的值是否为数组,不为则没有匹配上
  */
 if (!(Array.isArray(matchAnswer))) {
     //本方法参照一般http请求即可(promise)
     smartTipsHandler(param).then(res => {
         let data = res.data;
         if (data) {
             matchAnswer = data;
			smartTipsGather[param] = data;
         } else {
         	//赋值默认为空值
         	matchAnswer = []
			smartTipsGather[param] = [];
         }
         return matchAnswer;
     }.fail(error=>{
		//赋值默认为空值
		smartTipsGather[param] = [];
		return [];
	})
 } else {
    return matchAnswer;
 }

})
避免拼音干扰:
/**
 * @todo listen the event of pinyin
 * @type {boolean}
 */
 //默认输入框id值:textArea
 //判断是否输入
var inputDoing = false;

//开始输入
document.getElementById('textArea').addEventListener('compositionstart', function (e) {inputDoing = true;}, false);

//输入中
document.getElementById('textArea').addEventListener('input', function (e) {if (!inputDoing){smartTipsMatchHandler(document.getElementById("textArea").innerText);
}}, false);

//输入结束
document.getElementById('textArea').addEventListener('compositionend', function (e) {
inputDoing = false;
smartTipsMatchHandler(document.getElementById("textArea").innerText);
}, false);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值