前段兼容性问题

PC端兼容性问题 Dom Bom ecma

1、 HTML对象获取问题

FireFox:document.getElementById("name");
ie:document.idname或者document.getElementById("name").

解决办法:统一使用 document.getElementById("name");
2、const问题
说明:Firefox下,可以使用const关键字或var关键字来定义常量;
IE下,只能使用var关键字来定义常量.
解决方法:统一使用var关键字来定义常量.
3. event.x与event.y问题
说明:IE下,event对象有x,y属性,但是没有pageX,pageY属性;
Firefox下,event对象有pageX,pageY属性,但是没有x,y属性.
解决方法:使用mX(mX = event.x ? event.x : event.pageX;)来代替IE下的event.x或者Firefox下的event.pageX.
4. window.location.href问题
说明:IE或者Firefox2.0.x下,可以使用window.location或window.location.href;
Firefox1.5.x下,只能使用window.location.
解决方法:使用window.location来代替window.location.href.
5. frame问题
以下面的frame为例:

<frame   src="xxx.html"   id="frameId"  name="frameName"   />

(1)访问frame对象:
IE:使用window.frameId或者window.frameName来访问这个frame对象. frameId和frameName可以同名。
Firefox:只能使用window.frameName来访问这个frame对象.
另外,在IE和Firefox中都可以使用window.document.getElementById("frameId")来访问这个frame对象.
(2)切换frame内容:
在 IE和Firefox中都可以使用window.document.getElementById("testFrame").src = "xxx.html"window.frameName.location = "xxx.html"来切换frame的内容.
如果需要将frame中的参数传回父窗口(注意不是opener,而是parent frame),可以在frame中使用parent来访问父窗口。例如:parent.document.form1.filename.value="Aqing";
6. 模态和非模态窗口问题
说明:IE下,可以通过showModalDialog和showModelessDialog打开模态和非模态窗口;Firefox下则不能.
解决方法:直接使用window.open(pageURL,name,parameters)方式打开新窗口。
如果需要将子窗口中的参数传递回父窗口,可以在子窗口中使用window.opener来访问父窗口.
例如:

var parWin = window.opener; 
parWin.document.getElementById("Aqing").value = "Aqing";

7. firefox与IE的父元素(parentElement)的区别
IE:obj.parentElement
firefox:obj.parentNode
解决方法: 因为firefox与IE都支持DOM,因此使用obj.parentNode是不错选择.
8. document.formName.item(”itemName”) 问题
问题说明:IE下,可以使用document.formName.item(”itemName”)或document.formName.elements["elementName"];Firefox 下,只能使用document.formName.elements["elementName"]
解决方法:统一使用document.formName.elements["elementName"]
9. 集合类对象问题
问题说明:IE下,可以使用 () 或 [] 获取集合类对象;Firefox下,只能使用 [ ]获取集合类对象。
解决方法:统一使用 [] 获取集合类对象。
10. 自定义属性问题
问题说明:IE下,可以使用获取常规属性的方法来获取自定义属性,也可以使用getAttribute() 获取自定义属性;Firefox下,只能使用getAttribute() 获取自定义属性。
解决方法:统一通过getAttribute() 获取自定义属性。
11. input.type属性问题
问题说明:IE下input.type属性为只读;但是Firefox下input.type属性为读写。
解决办法:不修改input.type属性。如果必须要修改,可以先隐藏原来的input,然后在同样的位置再插入一个新的input元素。
12.event.srcElement问题
问题说明:IE下,even对象有srcElement属性,但是没有target属性;Firefox下,even对象有target属性,但是没有srcElement属性。
解决方法:使用srcObj =event.srcElement ?event.srcElement : event.target;
13. body载入问题
问题说明:Firefox的body对象在body标签没有被浏览器完全读入之前就存在;而IE的body对象则必须在body标签被浏览器完全读入之后才存在。
[注] 这个问题尚未实际验证,待验证后再来修改。
[注] 经验证,IE6、Opera9以及FireFox2中不存在上述问题,单纯的JS脚本可以访问在脚本之前已经载入的所有对象和元素,即使这个元素还没有载入完成。
14. 事件委托方法
问题说明:IE下,使用document.body.onload= inject; 其中functioninject()在这之前已被实现;在Firefox下,使用document.body.onload= inject();
解决方法:统一使用document.body.onload=newFunction(’inject()’); 或者document.body.onload = function(){/* 这里是代码 */}
[注意] Function和function的区别。
15. Table操作问题
问题说明:ie、firefox以及其它浏览器对于 table 标签的操作都各不相同,在ie中不允许对table和tr的innerHTML赋值,使用js增加一个tr时,使用appendChild方法也不管用。
解决方法://向table追加一个空行:


```javascript
`var row = otable.insertRow(-1);
var cell =document.createElement("td");
cell.innerHTML ="";
cell.className = "XXXX";row.appendChild(cell);`

``
[注] 由于俺很少使用JS直接操作表格,这个问题没有遇见过。建议使用JS框架集来操作table,如JQuery。
16. 对象宽高赋值问题
问题说明:FireFox中类似obj.style.height =imgObj.height的语句无效。

移动端
viewport
先上模板

<meta charset="utf-8">
<!--主要I是强制让文档的宽度与设备宽度保持1:1,最大宽度1.0,禁止屏幕缩放。-->
<meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">
<!--这个也是iphone私有标签,允许全屏浏览。-->
<meta content="yes" name="apple-mobile-web-app-capable">
<!--iphone的私有标签,iphone顶端状态条的样式。-->
<meta content="black" name="apple-mobile-web-app-status-bar-style">
<!--禁止数字自动识别为电话号码,这个比较有用,因为一串数字在iphone上会显示成蓝色,样式加成别的颜色也是不生效的。-->
<meta content="telephone=no" name="format-detection">
<!--禁止email识别-->
<meta content="email=no" name="format-detection">

写背景图时最好加上top left 或者0 0 不然写运动效果时容易出现跳
禁止复制、选中文本

.el {
  -webkit-user-select: none;
  -moz-user-select: none;
  -khtml-user-select: none;
   user-select: none;
}

苹果手机固定定位有bug 检查html和body是不是设置了overflow-x:hidden;
给不同屏幕大小的手机设置特殊样式

@media only screen  and (min-device-width : 320px)  and (max-device-width : 375px){}

IOS中input键盘事件keyup、keydown、keypress支持不是很好, 用input监听键盘keyup事件,在安卓手机浏览器中是可以的,但是在ios手机浏览器中用输入法输入之后,并未立刻相应keyup事件,只有在通过删除之后才可以响应
方法:可以用html5的oninput事件去代替keyup

<input type="text" id="testInput">
<script type="text/javascript">
  document.getElementById('input').addEventListener('input', function(e){
    var value = e.target.value;
  });
</script>

ios 设置input 按钮样式会被默认样式覆盖
解决方式如下:

input,textarea {
  border: 0;
  -webkit-appearance: none;
}

消除 IE10 里面的那个叉号:input:-ms-clear{display:none;}
手机上的flex布局时会有兼容性问题,只用新版本的会出现安卓手机不识别的现象
flex布局对于低版本的安卓,不支持flex-wrap:wrap属性,但是ios系统支持换行属性,这个时候如何解决呢?当然是不使用换行,用其他方式代替。

.box{
    display: -webkit-box; 
    /* 老版本语法: Safari, iOS, Android browser, older WebKit browsers. */
    display: -moz-box; /* 老版本语法: Firefox (buggy) */
    display: -ms-flexbox; /* 混合版本语法: IE 10 */
    display: -webkit-flex; /* 新版本语法: Chrome 21+ */
    display: flex; /* 新版本语法: Opera 12.1, Firefox 22+ */
}

input 的placeholder属性会使文本位置偏上

line-height: (和input框的高度一样高)---pc端解决方法
line-height:normal ---移动端解决方法

input type=number之后,pc端出现上下箭头

input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
    -webkit-appearance: none !important;
    margin: 0;
}

实现android和ios系统手机打开相机并可选择相册功能

<input class="js_upFile cover1" type="file" name="cover" accept="image/*" capture="camera" multiple/>


$(function () {
    //获取浏览器的userAgent,并转化为小写
    var ua = navigator.userAgent.toLowerCase();
    //判断是否是苹果手机,是则是true
    var isIos = (ua.indexOf('iphone') != -1) || (ua.indexOf('ipad') != -1);
    if (isIos) {
        $("input:file").removeAttr("capture");
    };
})

移动端 HTML5 audio autoplay 失效问题
这个不是 BUG,由于自动播放网页中的音频或视频,会给用户带来一些困扰或者不必要的流量消耗,所以苹果系统和安卓系统通常都会禁止自动播放和使用 JS 的触发播放,必须由用户来触发才可以播放。
解决方法思路:先通过用户 touchstart 触碰,触发播放并暂停(音频开始加载,后面用 JS 再操作就没问题了)。
解决代码:

document.addEventListener('touchstart',function() {
  document.getElementsByTagName('audio')[0].play();
  document.getElementsByTagName('audio')[0].pause();
});

移动端 video在部分android机播放之后浮在最上层,设置z-index无效
这个目前没有好的办法解决
情景一:页面有视频,点击页面按钮显示弹出层(比如让用户输入用户信息),这时候视频会出现在弹出层上面,是不是很-d疼?
方案:点击按钮时候把video隐藏hide,关闭弹出层show,过程中视频声音还在
情景二:页面很长,往下翻滚时,视频在播放,脱离文档流
方案:页面滚动到某一合适位置把video隐藏hide,回滚到某一位置show,过程中视频声音还在
有些说position可以解决,我没有试
关于 iOS 系统中,中文输入法输入英文时,字母之间可能会出现一个六分之一空格

this.value = this.value.replace(/\u2006/g,'');

关于 iOS 与 OS X 端字体的优化(横竖屏会出现字体加粗不一致等)
iOS 浏览器横屏时会重置字体大小,设置 text-size-adjust 为 none 可以解决 iOS 上的问题,但桌面版 Safari 的字体缩放功能会失效,因此最佳方案是将 text-size-adjust 为 100% 。

-webkit-text-size-adjust:100%;
-ms-text-size-adjust:100%;
text-size-adjust:100%;

移动端点击300ms延迟
原因:浏览器兴起初期,为了判断用户是双击还是单击,就设置了一个时间段300ms,用户单击后300ms后做事件处理,如果在300ms内连续点击,就判断为双击,做双击处理事件。
所以现在用click绑定事件呢,就会有300ms延迟的问题。
300ms尚可接受,不过因为300ms产生的问题,我们必须要解决。300ms导致用户体验并不是很好,解决这个问题,我们一般在移动端用tap事件来取代click事件。
推荐两个js,一个是fastclick,一个是tap.js
移动端点透问题
案例如下:

<div id="haorooms">点头事件测试</div>
<a href="www.baidu.net">www.baidu.com</a>

div是绝对定位的蒙层,并且z-index高于a。而a标签是页面中的一个链接,我们给div绑定tap事件:

$('#haorooms').on('tap',function(){
    $(this).hide();
});

我们点击蒙层时 div正常消失,但是当我们在a标签上点击蒙层时,发现a链接被触发,这就是所谓的点透事件。
原因:
touchstart 早于 touchend 早于click。 亦即click的触发是有延迟的,这个时间大概在300ms左右,也就是说我们tap触发之后蒙层隐藏, 此时 click还没有触发,300ms之后由于蒙层隐藏,我们的click触发到了下面的a链接上。
解决:
尽量都使用touch事件来替换click事件。例如用touchend事件(推荐)。
用fastclick,https://github.com/ftlabs/fas…
用preventDefault阻止a标签的click
延迟一定的时间(300ms+)来处理事件 (不推荐)
以上一般都能解决,实在不行就换成click事件。
下面介绍一下touchend事件,如下:

$("#haorooms").on("touchend",function(event) {
   event.preventDefault();
 });

react 移动端 兼容性问题和一些小细节

  • 使用 ES6 的浏览器兼容性问题
  • react 对低版本的安卓webview 兼容性
  • iOS下 fixed与软键盘的问题
  • onClick 阻止冒泡
  • meta对于移动端的一些特殊属性
  • 页面禁止复制、选中文本
    1.使用 ES6 的浏览器兼容性问题

由于 Babel 默认只转换转各种 ES2015 语法,而不转换新的 API,比如 Promise,以及 Object.assignArray.from 这些新方法,这时我们需要提供一些 ployfill 来模拟出这样一个提供原生支持功能的浏览器环境。
主要有两种方式:babel-runtimebabel-polyfill
A.babel-runtime
1.babel-runtime 的作用是模拟 ES2015 环境,包含各种分散的 polyfill 模块,我们可以在自己的模块里单独引入,比如 promise

import 'babel-runtime/core-js/promise'

1、它们不会在全局环境添加未实现的方法,只是这样手动引用每个 polyfill 会非常低效,我们可以借助 Runtime transform 插件来自动化处理这一切。
2、 首先使用 npm 安装

npm install babel-plugin-transform-runtime --save-dev

3、然后在 webpack 配置文件的 babel-loader 增加选项:

loader : ["babel-loader"],
query:{
	plugins: [
		"transform-runtime"
	],
	presets:['es2015','stage-0']
}

B.babel-polyfill
babel-polyfill 是针对全局环境的,引入它浏览器就好像具备了规范里定义的完整的特性,一旦引入,就会跑一个 babel-polyfill 实例。用法如下:
1.安装 babel-polyfill

npm install babel-polyfill  --save

2、在入口文件中引用:

import "babel-polyfill"

其实做到这些,在大部分浏览器就可以正常跑了。
2.react 对低版本的安卓webview 兼容性
A.android较低版本webview不支持Object.assign改用var objectAssign = require('object-assign’) 这种情况上面方案可以解决
B.import React from 'react';import ReactDOM from 'react-dom'; //不可放在其他模块引入的后面,否则android5.0及以下版本webview报错
3.iOS下 fixed与软键盘的问题
1、 fixed失效是由于软键盘唤起后,页面的 fixed 元素将失效(ios认为用户更希望的是元素随着滚动而移动,也就是变成了 absolute 定位)
2、 既然变成了absolute,所以当页面超过一屏且滚动时,失效的 fixed 元素就会跟随滚动了。解决方案就是让整个页面处于一屏高度就能解决问题的根本

 <body> 
    <div class='warper'> 
        <div class='top'></div> 
        <div class='main'></div> 
    <div> 
    <div class="fix-bottom">
    </div> 
</body>
 
//样式:
warper{ 
    position: absolute; 
    width: 100%; 
    left: 0; 
    right: 0; 
    top: 0; 
    bottom: 0; 
    overflow-y: scroll; 
    -webkit-overflow-scrolling: touch;/* 解决ios滑动不流畅问题 */ }
.fix-bottom{
    position:fixed;
    bottom:0;
    width: 100%;
}

Vue适配
1,先看看网上关于移动端适配讲解
再聊移动端页面适配,rem和vw适配方案!
基础点:rem相对根节点字体的大小。所以不用px; 根字体:字体的大小px; px:你就当成cm(厘米)这样的东西吧; 基准:750设计稿;
这是方案的基础理论,在这个基础上,我们还要搞明白,到底要干一件什么事情!
目标一 、手机适配:就是页面上的尺寸,无论高度,还是宽度,还有字体,随屏幕的宽度变化!这里是屏幕宽度!是不是想到了vw,对,就是这个意思;——最大程度在各个尺寸屏幕上还原设计稿
目标二、px转换成rem:一般UI给的设计稿宽度大小是750,所以,我们想直接写上面UI标记的尺寸;——最大程度减少工作
为什么选择rem? 很久之前没有vw,怕vw的兼容问题,就用了rem;也就是:rem的兼容性>vw的兼容性; 还有一种就是自己写百分比很不优雅
一、理论基础!
实现目标一

用rem就可以了吧!因为rem就可以随根字体大小改变而改变,从而实现了自适应的功能。 但是,但是,重点来,如果,根字体的大小默认是16px;那么,我们的1rem;就永远是16px,懂么?也就是如果设计稿是750(放大了一倍,iphone是375pt),我们想要个50%的大小: 50%*357px/16=11.718rem 如果我们写一个11.718rem的宽度,然而这只能在能iphone6还原设计稿,也就是只有在iphone6上这样的宽度才刚好占一半; 那么问题来了,如果在每个屏幕上都是50%呢,直接改变根字体大小(16px)不就完了么!!;11.718rem永远还是那个11.718rem,不用担心;
实现目标二、
用工具,webpack,postcss,postcss-pxtorem
二、准备主要工具!

viewport: 建议自行百度;

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

vue-cli: 用这个主要是用webpack,这个构建工具大大降低了webpack的使用难度;快速构建出一个前端项目。
postcss: 官网解释:PostCSS is a tool for transforming styles with JS plugins,就是postcss用js插件帮你转换css样式的一个工具。比如,这里的把你的文件里面16px替换成1rem(根大小默认16px的情况);这样你就不用自己去算了!
postcss-pxtorem: postcss的一个插件,主要是帮你把px转换成对应的rem; 然后:还要用js代码去动态算根目录应该有的字体大小,反正就是一段js代码去动态获取屏幕宽度!
三、rem——开始干!
第一步,先用vue-cli快速构建出一个项目,然后,安装postcss,postcss-pxtorem,
postcss-loader,postcss-import,postcss-url;
第二步,在项目根目录下添加.postcssrc.js文件,在里面写上

module.exports = 
{ plugins: { 
	'postcss-pxtorem': { rootValue: 32, propList: ['*'], minPixelValue: 2 
   } }
};

rootValue,这里就是根目录的字体大小是32px,这里为啥设置成32呢,因为一般设计稿是750,比iphone6的大一倍,所以设置成16的两倍,就是32px;proplist就是那些属性需要转换成rem,这里是全部的意思; 比如你可选择设置; propList: ['font', 'font-size', 'line-height', 'letter-spacing'] minPixelValue就是最小转换单位,这是最小转换单位是2px的意思;
第三步,动态设置根字体大小!一段简单的js插入在head里面;

(function() {
    function autoRootFontSize() {
        document.documentElement.style.fontSize =        Math.min(screen.width,document.documentElement.getBoundingClientRect().width)  /  750 * 32 + 'px';
         // 取screen.width和document.documentElement.getBoundingClientRect().width的最小值;除以750,乘以32;懂的起撒,就是原本是750大小的32px;如果屏幕大小变成了375px,那么字体就是16px;也就是根字体fontSize大小和屏幕大小成正比变化!是不是很简单
    }
    window.addEventListener('resize', autoRootFontSize);
    autoRootFontSize();
})();
  • 这里,我想说的是完全可以用vw去设置根字体大小,26px/375px=4.267vw;就不用js去算了! html{font-size:4.267vw}; //因为这个字体大小完全是随屏幕正比变化;
    四、vw——开始干! vw的方案就简单多了,因为vw本来就相对屏幕的百分比,所以我们不用再去动态的改变根字体大小了,只需要把750上的px大小转换成对应的vw值就完了,这一步交给postcss工具就可以! 所以只需要两步! 第一步,先用vue-cli快速构建出一个项目,然后,安装postcss,postcss-pxtorem,postcss-loader,postcss-import,postcss-url
    第二步,在项目根目录下添加.postcssrc.js文件,在里面写上
module.exports = { "plugins": { "postcss-import": {}, "postcss-url": {}, "postcss-aspect-ratio-mini": {}, "postcss-write-svg": { utf8: false }, "postcss-cssnext": {}, "postcss-px-to-viewport": { viewportWidth: 750, unitPrecision: 3, viewportUnit: 'vw', selectorBlackList: ['.ignore', '.hairlines'], minPixelValue: 1, mediaQuery: false }, "postcss-viewport-units": {}, }}

viewportWidth是你设计稿的大小750,然后unitPrecision是vw值保留的小数点个数;
五、总结!
首先明白一件事:px就像cm一样,1px永远是1px;1cm永远是1cm; 那么我们从目标再反推一道逻辑: 我们想要的结果很简单: 一个元素的宽度(px) / 屏幕宽度(px) = 定值 (这个定值就是设计稿上面的值比例定值);
——所以要做就是:屏幕变宽,要让元素宽度就变宽。 然鹅,我们写的代码里面的px是不可能变的(取的750设计稿上面的尺寸);那么postcss编译出来的rem值也是不变的;
我们是怎么把设计稿里面的40px换算成相应rem的呢;你只要记住根字体大小的值(浏览器的默认是16px,现在设置成的32px)就是1rem;这交给工具同一去算; 得到:元素的宽度(px) = 元素的宽度(rem) ✖️32; 所以这个32是你必须要设置在postcss-pxtorem里面的;这样它就可以帮你算; 又因为: 元素的宽度(rem) ✖️ 根字体大小(px) = 元素的宽度(px) 元素的宽度(px) 变大, 元素的宽度(rem) 不变,那就只有改变根字体大小(px) ,变大;具体怎么变,上面的js代码已经解释了;
——所以我们做的就是:屏幕变宽,让根字体大小(px) 变宽,元素宽度就变宽。 750屏幕下是写的样式大小是1:1, 所以 又因为我们想要:根字体大小(px) / 屏幕宽度(px) = 32 / 750
所以: 根字体大小(px) = 32 / 750 ✖️ 屏幕宽度(px)
一个元素的宽度(px) / 屏幕宽度(px) = 定值 → 根字体大小(px) ✖️元素的宽度(rem)/ 屏幕宽度(px) → 32 / 750 ✖️ 屏幕宽度(px) ✖️元素的宽度(rem)/ 屏幕宽度(px) 等于什么?? 得到的的是一个与屏幕大小无关的定值!
化简: 元素的宽度(rem)✖️32 / 750 = 元素的宽度(px) / 750 ——不就是设计稿上面的比例么!!!

  • 验证以上操作出来的结果是否符合预期也很简单: 比如一个img的宽,高,在iphone6上的尺寸(审查元素的大小!px单位): 根字体:16px; postcss算出来的rem值是2.5rem; 2.516=40px; 实际上也是40px; ——得到元素实际大小 40✖️40(px), 屏宽是375;比例是40/375=0.10667; 在iphone5上的尺寸(审查元素的大小!px单位): 根字体:13.6533px; postcss算出来的rem值是2.5rem; 2.513.6533=34.13px; 实际上也是34.13px; ——得到元素实际大小 34.13✖️34.13(px), 屏宽是320;比例是34.13/320=0.10665;
    2,自己项目适配配置(实践)
    上的文章讲的理论和方法是可行的,自己项目的解决方案和他大同小异(主要用rem): 1,插件:amfe-flexible + postcss-px2rem amfe-flexible:自动根据不同设备改变data-dpr的值,这样就可以根据不同的data-dpr设置字体大小不变,仅放大相应倍数。
    postcss-px2rem:打包的时候把项目里面的px统一转换成rem,转换的基准值根据配置设置的(.postcssrc.js) /因为我是以750px(iphone6)宽度为基准,所以remUnit为37.5/
    经过试验结果:
    postcss-px2rem:只负责把项目里面的px按照基准值转换成rem,并不负责根节点动态font-size的计算。
    例如,代码里面有个高度固定:180px, 基准值是:37.5, 那最后界面上的rem=180/37.5=4.8rem 不管换不同客户端手机,不同分辨率,界面上都是固定4.8rem【rem的值是固定的,根据根节点的font-size不同,在界面显示的px也不同】,界面上显示的px = 16(没有设置font-size的话默认是16px)* 4.8rem = 76.8px
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    【那么这个基准值:37.5怎么来的:
    rem基准值计算 关于rem的基准值,也就是上面那个37.5px其实是根据我们所拿到的视觉稿来决定的,主要有以下几点原因: 1.由于我们所写出的页面是要在不同的屏幕大小设备上运行的,所以我们在写样式的时候必须要先以一个确定的屏幕来作为参考,这个就由我们拿到的视觉稿来定;假如我们拿到的视觉稿是以iphone6的屏幕width=375px为基准: ar docEl = document.documentElement; var width = docEl.getBoundingClientRect().width; var rem = width / 10; 这样计算出来的rem基准值就是37.5(iphone6的视觉稿),这里为什么要除以10呢,其实这个值是随便定义的,因为不想让html的font-size太大,当然也可以选择不除,只要在后面动态js计算时保证一样的值就可以

    上面的组件只负责转换rem,并没有根据不同设备设置font-size,下面再加入这个组件amfe-flexible:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    不同设备下的font-size不同。
发布了25 篇原创文章 · 获赞 10 · 访问量 1440

猜你喜欢

转载自blog.csdn.net/weixin_45077178/article/details/103304259