前端开发遇到的坑 汇总

尽管要多加避免,但还别说,坑还真得常踩常有,不要以为手机端都是 Webkit 的天下就简单,不用处理浏览器之间的兼容问题,——其实不一致性的问题还是挺大的。

第一个

两个坑都是涉及 iframe 的——iframe 真是不好搞!

事情是这样的,一个内嵌于 iframe 的页面,因为需要从认证接口中返回 token 作为登录凭证,读取接口信息是没问题的,然后需要用 session 把登录信息保存起来。奇怪的是,session 无效,就像丢失了一样!脱离了 iframe 就是单独页面的话就没事。而且不是全部手机都这样,高版本安卓和苹果都这样(桌面和某些版本安卓正常)。我们知道一般用 cookies 一对一 session 的,估计 iframe 的 cookie 鉴于更完善的安全机制所以不能像低版本那样“愉快”地使用 cookies。

后来简直与甲方说出了我们“殚精竭虑”,无奈之下,只好使出最笨的方法,通过 url 参数传递认证数据。还好几个页面,加起来也没那么痛苦了……

第二个

第二个坑是苹果专属的,Safari 居然不能约束 iframe 内页面的宽度!安卓就 ok。简单说发现嵌入页面在移动端会出现变形,即使你加上

<meta name="viewport" content="width=320, initial-scale=1, user-scalable=yes" />

也无效。如果写死一个宽度那么就不能兼容苹果各种屏幕了。于是我居中正文,但有些人又不同意这种不符合美观的做法,于是我用 js 读取屏幕宽度然后写入 document.body.style.width。两行代码搞定,关键是思路。

第三个:遍历 DOM 注意点

在实现一个清理 HTML 冗余标签(word 粘贴过来的)功能,最简单的,莫过于:

// MSWordHtmlCleaners.js https://gist.github.com/ronanguilloux/2915995
cleanPaste : function(html) {
    // Remove additional MS Word content
    html = html.replace(/<(\/)*(\\?xml:|meta|link|span|font|del|ins|st1:|[ovwxp]:)((.|\s)*?)>/gi, ''); // Unwanted
                                                                                                        // tags
    html = html.replace(/(class|style|type|start)=("(.*?)"|(\w*))/gi, ''); // Unwanted
                                                                            // sttributes
    html = html.replace(/<style(.*?)style>/gi, '');   // Style tags
    html = html.replace(/<script(.*?)script>/gi, ''); // Script tags
    html = html.replace(/<!--(.*?)-->/gi, '');        // HTML comments
    
    return html;
},

不过,由于某些正则功能的缺失,网页的 JS 正则是不能完全匹配对应标签的。故所以这种通过正则过滤的办法是有潜在问题的。于是考虑另外一种方法,如老外写的这个 http://booden.net/ContentCleaner.aspx ,它是通过 DOM 方法删除标签的,——我觉得可行,就拿来改造。遇到的问题不少,记录如下。

首先,他依赖 jQuery,我希望是原生的,开始我以为修改下问题不大,但后来发现没那么容易,首当其冲的是 DOM 遍历。写一个遍历并递归 DOM 的代码不困难,麻烦在于,当你使用 for 遍历,集合的总数是固定的(length),而当你删除了一个元素,等于破坏了这个数组,数组下标也乱了。于是改为 while(firstChild) 循环的方法,有点链表那样的写法,总是会出现死循环的现象,可能是指针有误。

苦于没有办法快放弃之际,忽然想起老外那个代码有段函数 removeComments(),想想那正是原生的遍历方法,它是删除注释节点后而继续迭代的。于是拿来改造用,并得到成功!

后来想想,可能这就是迭代器与 for 的区别,因为集合里面的元素允许动态变化,用 for 遍历肯定有问题,这时就适宜用迭代器,诸如 hasNext()、getNextItem() 的 API,尽管会啰嗦点。

在删除 DOM 元素属性时,也遇到这种问题。例如下面代码,每次只能删除一个属性,而不是全部!

var attrs = el.attributes;
for (var i = 0; i < attrs.length; i++) {
    console.log(attrs[i]);
    el.removeAttribute(attrs[i].name);
}

解决方法是如 MDN 所说的,

for(var i = attrs.length - 1; i >= 0; i--) {
    var name = attrs[i].name;
    if (attributesAllowed[tag] == null || attributesAllowed[tag].indexOf("|" + name.toLowerCase() + "|") == -1){
        node.removeAttribute(name);
    }
}

最后,完整的清理 HTML 代码如下
 

// 清理冗余 HTML
cleanHTML() {
    // 类似于 白名单
    var tagsAllowed = "|h1|h2|h3|p|div|a|b|strong|br|ol|ul|li|pre|img|br|hr|font|";

    var attributesAllowed = {};
    attributesAllowed["div"] = "|id|class|";
    attributesAllowed["a"] = "|id|class|href|name|";
    attributesAllowed["img"] = "|src|";

    this.everyNode(this.iframeBody, node => {
        var isDelete = false;
        
        if (node.nodeType === 1) {
            var tag = node.tagName.toLowerCase();
            if (tagsAllowed.indexOf("|" + tag + "|") === -1)
                isDelete = true;
            
            if (!isDelete) { // 删除属性
                var attrs = node.attributes;

                for(var i = attrs.length - 1; i >= 0; i--) {
                    var name = attrs[i].name;
                    if (attributesAllowed[tag] == null || attributesAllowed[tag].indexOf("|" + name.toLowerCase() + "|") == -1){
                        node.removeAttribute(name);
                    }
                }
            }
        } else if (node.nodeType === 8) {// 删除注释
            isDelete = true;
        }
        
        return isDelete;
    });

},

everyNode (el, fn) {
    var objChildNode = el.firstChild;
    while (objChildNode) {
        if (fn(objChildNode)) { // 返回 true 则删除
            var next = objChildNode.nextSibling;
            el.removeChild(objChildNode);
            objChildNode = next;
        } else {
            if (objChildNode.nodeType === 1)
                this.everyNode(objChildNode, fn);

            objChildNode = objChildNode.nextSibling;
        }
    }
}

附:测试的标签

<!-- test -->
<h3>Some supported heading</h3>
<h6>non supported heading</h6>
<style type="text/css">
font {
font-family: arial;
font-size: 140%;
}
</style>
<pre id="script">dynamically added text.</pre>
<font color="red">RED</font>
<b onclick="alert('BOLD')">bold</b>
<!-- What to do with this? -->
<!--? test ?-->
<i>italic<script>$("#script").text('dynamically added text.');</script></i>
<span style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"><span style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">
<p class="MsoNormal"><b style="mso-bidi-font-weight: normal">
<span style="FONT-SIZE: 10pt; BACKGROUND: red; COLOR: #ff9900; mso-bidi-font-family: Arial; mso-highlight: red">Sample MS Word content</span></b>
<b style="mso-bidi-font-weight: normal"><span style="FONT-SIZE: 10pt; COLOR: #ff9900; mso-bidi-font-family: Arial">
<!--?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /--><o:p></o:p></span></b></p></span></span>

浏览器兼容问题

ie中a链接失效的问题

一个a链接里面放个table,即为:a>table>tr>td>链接文字。结果不能点击。原因是:a链接中有个块元素,块元素中才是img,顺序是 a>块元素>img。这种顺序不行,如果换成 块元素>a>img,就OK了。  结论就是:在ie6、7、8中,如果a中有块元素或者强制成块的元素的话就不能点击,要调换顺序,即为:块元素>a>img。

解决办法:用js绑定table的click事件。

针对IE6,7,8的CSS hack

body{
         color:red; //所有浏览器
         color:orange/0  // 只针对IE8
         color:yellow\9; //IE8及以下
         *color:blue; //IE7及以下
         _color:gray; //IE6
}

<!--[if IE 6]> body{ color:green; //IE6 } <![endif]-->

IE6 用户升级浏览器的提示如图:

插入 HTML:

<!--[if IE 6]>
<!--ie6弹出层显示信息-->
<style type="text/css">
#popDiv {
	width:412px;
	background: #f0f0f6;
	border: 10px solid #e0e0e0;
	padding:0 0 10px 0;
	border-top:none;
	text-alig: left;
	font-size: 12px;
	z-index:99;
	left:50%;/*FF IE7*/
	top: 50%;/*FF IE7*/
	margin-left:-200px!important;/*FF IE7 该值为本身宽的一半 */
	margin-top:-60px!important;/*FF IE7 该值为本身高的一半*/
	margin-top:0px;
	position:fixed!important;/*FF IE7*/
	position:absolute;/*IE6*/
	_top:expression(eval(document.compatMode && document.compatMode=='CSS1Compat') ? documentElement.scrollTop + (document.documentElement.clientHeight-this.offsetHeight)/2 :/*IE6*/ document.body.scrollTop + (document.body.clientHeight - this.clientHeight)/2);/*IE5 IE5.5*/
}
#popDiv a{text-decoration:none;color:#f00;}
#popDiv a:hover{color:#f60;}
#isclose{position:absolute;bottom:5px;right:6px;}
#isclose a{border:1px solid #e0e0e0;padding:2px 5px;background:#f0f0f6;}
#isclose a:hover{color:#f60;background:#fc6;}
#popDiv h1{font-size:12px;line-height:24px;background:#e0e0e0;line-height:30px;color:#333;}
#popDiv h2{font-size:12px;text-indent:24px;line-height:24px;color:#333;font-weight:normal;padding:10px;}
#popDiv p{line-height:24px;display:inline-block;text-indent:24px;}
</style>
<div id="popDiv" class="viewPhoto">
	<h1>中国物流商城网 友情提示:</h1>
	<h2>您使用的是较低版本浏览器,将导致无法使用本系统的部分功能。建议您使用 IE8.0 或其他较新版本浏览器,以便更好的感受本系统的各项特色功能及服务,感谢您对中国物流商城网的关心和支持。</h2>
	<p>技术支持热线:020-6996078</p>
	<p>更新 IE6 的原因,详见<a href="http://theie6countdown.cn/" target="_blank">《对Internet Explorer 6 说再见》</a>
	</p>
	<br /><br />
	<p id="isclose">
		<a href="http://www.microsoft.com/zh-cn/download/internet-explorer-8-details.aspx" target="_blank">下载 IE 8</a>
		<a href="#" onclick="document.getElementById('popDiv').style.display='none';" id="acontinue">继续使用</a>
		<a href="javascript:window.close();" id="aClose">关闭窗口</a>
	</p>
</div>
<![endif]--> 

隐藏元素 获取 高度 问题,for All browsers.

当一个元素处于 隐藏的状态,display:none
是不能获取其高度或者宽度的?
也就是 el.clientHeight=0/el.clientWidth=0,

IE 取得css属性的绝对像素值

for ie8 可以通过 offsetHeight 获取,
for ie7,要使元素大小发生变化,才能获取,如下例,要获取 父级 td 元素 的 高度,怎么获取绝对像素值?

    //导入iframe时获取高度并适应  
    function iFrameHeight(ifm) {    
        if(window.navigator.isFF || window.navigator.isIE8)  
            ifm.height  = document.getElementById('tdtd').offsetHeight;  
          
        if(window.navigator.isIE7){  
            // ie6, ie7 不能通过 offsetHeight 来直接获取绝对的高度,getComputed() 也是返回 ifm.style.height ="auto",于是……  
            document.getElementById('tdtd').height = "100%";  
            ifm.height  = document.getElementById('tdtd').offsetHeight - 30;  
            document.getElementById('tdtd').height = "";  
        }  
    }  

iOS 系统上传图片的一个问题

Safari 浏览器对自动剥离图片的 exif 信息!只要是从手机相册中选中了图片(唯一的途径)就已经剥离了exif 信息,图片大小也会发生变化!

参见:

http://stackoverflow.com/questions/13385585/ios-file-input-size

http://stackoverflow.com/questions/16297730/image-upload-from-iphone-strips-exif-data

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sp42a

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值