原生DOM兼容特性
浏览器主要也就是IE有点独特,所以把IE重点区分开
名称 | 主流 | IE | |
---|---|---|---|
内文本 | innerText | textContent | |
请求对象 | XMLHttpRequest | ActiveXObject ["MSXML2.XMLHttp.6.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp"] |
|
监听事件添加 | addEventListener(DOM2), ["on"+eventName](DOM0) |
attachEvent | |
监听事件移除 | removeEventListener(DOM2), ["on"+eventName]=null(DOM0) |
detachEvent | |
事件对象 | function(e) e | window.event(IE7之前) | |
阻止默认事件 | preventDefault | e.returnValue=false | |
阻止冒泡 | stopPropagation | e.cancelBubble=true | |
键盘事件键盘编码 | e.charCode | e.keyCode | |
获取剪贴板的文本 | e.clipboardData | window.clipboardData | |
设置剪贴板文本 | e.clipboardData.setData("text/plain",value); | window.clipboardData.setData("text",value); | |
触发事件的元素 | e.target | e.srcElement | |
获取样式 | getComputedStyle(obj,false)[attr];(Firefox浏览器) obj.style.attr(只对filter,opacity等有效) obj.style[attr] |
obj.currentStyle[attr]; | |
窗口左边的位置 | window.screenLeft | window.screenX | |
页面视口大小 | window.innerHeight | if(document.compatMode=="CSS1Compat")window.documentElement.clientHeight; if(document.compatMode=="BackCompat")window.body.clientHeight |
|
获取元素 | document.getElementById(id); | document.all[id];(IE5) | |
返回指定的属性 | ele.getAttribute(attr) | ele.attribute[attr] | |
ele是否存在指定属性 attr | ele.hasAttribute(attr) | ele.attributes[attr].specified; | |
鼠标滚动,正数表示向上滚动 | function getWheelDelta(e){ if(e.wheelData){ return (client.engine.opera&&client.engine.opera<9.5)? -e.wheelData:e.wheelData; }else { return -e.detail*40;//firefox } } |
||
提取选中的文本 | textbox.value.subString(textbox.selectionStart,textbox.selectionEnd); | document.selection.createRange().text; (IE8之前没有selectionStart,selectionEnd属性 |
|
设置文本选中 | textbox.setSelectionRange(startIndex,stopIndex); | var range=textbox.createTextRange(); range.collapse(true); range.moveStart("character",0); range.moveEnd("character",stopIndex-startIndex); range.select() |
下面是积累下来的一些兼容函数,可以当做模板用
添加多个onload事件
处理ActiveXObject/XMLHttpRequest问题
请求对象的属性和方法设置
发送表单数据
跨浏览器的CORS
跨浏览器事件处理程序
处理target/srcelemnt问题,代替this
实现insertAfter
给element加上类名
判断是不是数组
IE10之前不支持docunment.getElementByClassName
获取css样式
手写动画
取得窗口左边和上边的位置
取得页面视口大小
检测插件方法
获取元素
检查对象的某个特性是否存在
对象转换成数组
返回指定的属性
ele是否存在指定属性
ele是否符合选择器selector
获取内文本
获取鼠标事件的父元素
探测按的是鼠标的哪个键
鼠标滚动事件
提取选中的文本
设置文本选中
bind方法对老版本的浏览器不起作用
包装cookie
包装子cookie
indexedDB
手写typeof
深度克隆
组合使用构造函数模式和原型模式创建对象
组合继承
观察者模式
分享一个题目
添加多个onload事件function addLoadEvent(func){ var oldonload=window.onload; if(typeof window.onload!= "function"){ window.onload=func; } else{ window.onload=function(){ oldonload(); func(); } } }处理ActiveXObject/XMLHttpRequest问题
//第一种写法,《js高级程序设计》的写法 惰性载入技巧 function createXHR(){ if(typeof XMLHttpRequest!="undefined"){//XMLHttpRequest createXHR=function(){ return new XMLHttpRequest(); }; }else if(typeof ActiveXObject!="undefined"){//IE ActiveXObject createXHR=function(){ if(typeof arguments.callee.activeXString!="string"){ var versions=["MSXML2.XMLHttp.6.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp"],//IE i,len; for(i=0,len=versions.length;i请求对象的属性和方法设置 var xhr=createXHR(); xhr.onreadystatechange=function(){//firfox引入onlaod,readyState==4时触发,代替onreadystatechange if(xhr.readyState==4){ try{ if((xhr.status>=200&&xhr.status<300)||xhr.status==304){ alert(xhr.responseText); }else { alert("unsuccessful"); } }catch(ex){} } } xhr.onload=function(){ if((xhr.status>=200&&xhr.status<300)||xhr.status==304){ alert(xhr.responseText); }else { alert("unsuccessful"); } } xhr.onprogress=function(event){ if(event.lengthComputable){//进度信息是否可用 console.log("Received"+event.position+"of"+event.totalSize); } } xhr.onerror=function(){ alert("error"); } xhr.timeout=1000; xhr.ontimeout=function(){ alert("timeout"); } xhr.open("get","example.php",true); xhr.overrideMimeType("text/xml"); xhr.send(null);//GET发送表单数据var form=document.getElementById("info"); xhr.send(serialize(form));//第一种写法 xhr.send(new FormData(form));//第二种写法跨浏览器的CORSfunction createCORSRequest(method,url){ var xhr=new XMLHttpRequest(); if("withCredentials" in xhr){ xhr.open(method,url,true); }else if(typeof XDomainRequest !="undefined"){ xhr=new XDomainRequest(); xhr.open(method,url); }else { xhr=null; } return xhr; } var request=createCORSRequest("get","http://www.somewhere"); if(request){ request.onload=function(){}; request.send(); }跨浏览器事件处理程序var eventUtil={ // 页面加载完成后 readyEvent : function(fn) { if (fn==null) { fn=document; } var oldonload = window.onload; if (typeof window.onload != "function") { window.onload = fn; } else { window.onload = function() { oldonload(); fn(); }; } }, addEventHandler: function (obj, eventName, handler) { if (document.attachEvent) {//IE obj.attachEvent("on" + eventName, handler); } else if (document.addEventListener) {//DOM2级 obj.addEventListener(eventName, handler, false);//false- 默认。事件句柄在冒泡阶段执行 } else{//DOM0级 obj["on"+eventName]=handler; } }, removeEventHandler:function(obj, eventName, handler){ if (document.attachEvent) {//IE obj.detachEvent("on" + eventName, handler); } else if (document.addEventListener) {//DOM2级 obj.removeEventListener(eventName, handler, false); } else{//DOM0级 obj["on"+eventName]=null; } }, //获取event对象的引用,取到事件的所有信息,确保随时能使用event; getEvent: function (e) { var ev = e || window.event; if (!ev) { var c = this.getEvent.caller; while (c) { ev = c.arguments[0]; if (ev && Event == ev.constructor) { break; } c = c.caller; } } return ev; }, //事件类型 getType: function (e) { return e.type; }, //调用事件的元素 getElement: function (e) { return e.target|| e.srcElement; }, //阻止默认事件 preventDefault: function (e) { e= this.getEvent(e); if(e.preventDefault){ e.preventDefault(); } else { return e.returnValue=false;//IE } }, //阻止冒泡 stopPropagation:function(e) { if(e.stopPropagation){ e.stopPropagation(); } else { e.cancelBubble=true;//IE } }, //键盘事件键盘的编号 getCharCode:function (e){ if(typeof e.charCode=="number")return e.charCode; else return e.keyCode; }, //获取剪贴板的文本 getClipbordText:function(e){ var clipboardData=(e.clipboardData||window.clipboardData); return clipboardData.getData("text"); }, //设置剪贴板文本 setClipboardText:function(e,value){ if(e.clipboardData){ return e.clipboardData.setData("text/plain",value); }else if(window.clipboardData){ return window.clipboardData.setData("text",value); } }, }处理target/srcelemnt问题,代替thisfunction getActivatedObject(e) { var obj; if (!e) { // early version of IE obj = window.event.srcElement; } else if (e.srcElement) { // IE 7 or later obj = e.srcElement; } else { // DOM Level 2 browser obj = e.target; } return obj; }实现insertAfter/** * 把newElement插在targetElement后面 ,js的API只有insertBefore,没有insertAfter */ function insertAfter(newElement,targetElement) { var parent = targetElement.parentNode; if (parent.lastChild == targetElement) { parent.appendChild(newElement); } else { parent.insertBefore(newElement,targetElement.nextSibling); } }给element加上类名function addClass(element,value) { if (!element.className) { element.className = value; } else { newClassName = element.className; newClassName+= " "; newClassName+= value; element.className = newClassName; } }判断是不是数组function isArray(arg) { //return Object.prototype.toString.call(arr)=="[Object Array]";这种方法也可以 if (typeof arg == "object") { //所有数组都有一个包含单词"arry"的constructor,最后的i表示不区分大小写 var criteria = arg.constructor.toString().match(/array/i); return (criteria != null); } return false; }IE10之前不支持docunment.getElementByClassNamefunction getByClass(clsName,parent){ if(docunment.getElementByClassName) return docunment.getElementByClassName(clsName); //IE10之前 var oParent=parent?document.getElementById(parent):document, eles=[], elements=oParent.getElementsByTagName("*"); for(var i=0,l=elements.length;i获取css样式 function getStyle(obj,attr){ if(obj.currentStyle) {//IE 浏览器 return obj.currentStyle[attr]; }else{//Firefox浏览器 return getComputedStyle(obj,false)[attr]; } }手写动画//动画 startMove(oLi,{width:400,height:200,opacity:100}) function startMove(obj,json,fn){ clearInterval(obj.timer); obj.timer=setInterval(function () { for(var attr in json){ var cur=0; if(attr=="opacity"){ cur=Math.round(parseFloat(getStyle(obj,attr))*100); } else { cur=parseInt(getStyle(obj,attr)); } var speed=(json[attr]-cur)/8; speed=speed>0?Math.ceil(speed):Math.floor(speed); var flag=true; if(cur!=json[attr]){//使得所有属性做完运动才结束 flag=false; } if(attr=="opacity"){ obj.style.filter="alpha(opacity:"+(cur+speec)+")"; obj.style.opacity=(cur+speed)/100; } else{ obj.style[attr]=(cur+speed)+"px"; } } if(flag){ clearInterval(obj.timer); if(fn){ fn(); } } }) }取得窗口左边和上边的位置var leftPos=(typeof window.screenLeft =="number")?window.screenLeft:window.screenX;取得页面视口大小var pageWidth=window.innerWidth, pageHeight=window.innerHeight; if(typeof pageHeight!="number"){ if(document.compatMode=="CSS1Compat"){//标准模式 pageHeight=window.documentElement.clientHeight; pageWidth=window.documentElement.clientWidth; } else {//BackCompat pageHeight=window.body.clientHeight; pageWidth=window.body.clientWidth; } }检测插件方法/** * * 检测插件方法一,IE下无效 */ function hasPlugin(name){ name=name.toLowerCase(); for(var i=0;i获取元素 function getElement(id){ if(document.getElementById){ return document.getElementById(id); }else if(document.all){//IE5前 return document.all[id]; }else { throw new Error("no way to retrieve element!"); } }检查对象的某个特性是否存在function isHostMethod(object,property){ var t =typeof object[property]; return t=="function"|| (!!(t=="object")&&object[property])|| t=="unknown";//不懂 }对象转换成数组function convertToArray(nodes){ var array=null; try{ array=Array.propotype.slice.call(nodes,0);//IE8前无效 }catch(ex){ for(var i=0,len=nodes.length;i返回指定的属性 /** * * 返回指定的属性 IE ele.attribute[] * Element.getAttribute() */ function outputAttribute(ele){ var pairs=new Array(), attrname,attrvalue,u,len; for(i=0,len=ele.attribute.length;iele是否存在指定属性 /** * * ele是否存在指定属性 attr */ function hasattribute(ele,attr){ if(ele.hasAttribute){ return ele.hasAttribute(attr); }else {//IE return ele.attributes[attr].specified; } }ele是否符合选择器selector/** * ele是否符合选择器selector */ function matchesSelector(ele,selector){ if(ele.matchesSelector){ return ele.matchesSelector(selector); }else if(ele.msmatchesSelector){ return ele.msmatchesSelector(selector); }else if(ele.mozmatchesSelector){ return ele.mozmatchesSelector(selector); }else if(ele.webkitmatchesSelector){ return ele.webkitmatchesSelector(selector); }else{ throw new Error("not support"); } }获取内文本//innerText/textContent function getInnerText(ele){ return (typeof ele.innerText=="string")? ele.innerText:ele.textContent; }获取鼠标事件的父元素function getRelatedTarget(e){ if(e.relatedTarget) return e.relatedTarget; else if(e.fromElement) return e.fromElement;//mouseover else if(e.toElement) return e.toElement;//mouseout else return null; }探测按的是鼠标的哪个键function getButton(e){ if(document.implementation.hasFeature("MouseEvents","2.0")){ return e.button; }else { switch(e.button){ case 0 : case 1: case 3: case 5: case 7: return 0; case 2: case 6:return 2; case 4:return 1; } } }鼠标滚动事件//鼠标滚动,正数表示向上滚动 function getWheelDelta(e){ if(e.wheelData){ return (client.engine.opera&&client.engine.opera<9.5)? -e.wheelData:e.wheelData; }else { return -e.detail*40;//firefox } }提取选中的文本function getSelectedText(textbox){ if(typeof selectionStart=="number"){ return textbox.value.subString(textbox.selectionStart,textbox.selectionEnd); }else if(document.selection){//IE8之前没有selectionStart,selectionEnd属性 return document.selection.createRange().text; } }设置文本选中function selectText(textbox,startIndex,stopIndex){ if(textbox.setSelectionRange){ textbox.setSelectionRange(startIndex,stopIndex); }else if(textbox.createTextRange){//IE var range=textbox.createTextRange(); range.collapse(true); range.moveStart("character",0); range.moveEnd("character",stopIndex-startIndex); range.select(); } }bind方法对老版本的浏览器不起作用Function.prototype.bind = Function.prototype.bind || function(context){ var self = this; return function(){ return self.apply(context, arguments); }; }包装cookie//cookie var cookieUtil={ // 创建cookie setcookie:function (name, value, expires, path, domain, secure) { var cookieText = encodeURIComponent(name) + "=" + encodeURIComponent(value); if (expires instanceof Date) { cookieText += "; expires=" + expires.toGMTString(); } if (path) { cookieText += "; path=" + path; } if (domain) { cookieText += "; domain=" + domain; } if (secure) { cookieText += "; secure"; } document.cookie = cookieText; }, // 获取cookie getcookie:function (name) { var cookieName = encodeURIComponent(name) + "="; var cookieStart = document.cookie.indexOf(cookieName); var cookieValue = null; if (cookieStart > -1) { var cookieEnd = document.cookie.indexOf(";", cookieStart); if (cookieEnd == -1) { cookieEnd = document.cookie.length; } cookieValue = decodeURIComponent(document.cookie.substring(cookieStart + cookieName.length, cookieEnd)); } return cookieValue; }, // 删除cookie unsetcookie:function (name,path,domain,secure) { this.setcookie(name,"",new Date(0),path,domain,secure); } }包装子cookie//子cookie var subcookieUtil={ get:function(name,subname){ var subcookie=getAll(name); if(subcookie){ return subcookie[subname]; }else { return null; } }, getAll:function(name){ var cookieName = encodeURIComponent(name) + "="; var cookieStart = document.cookie.indexOf(cookieName); var cookieValue = null; var subcookie,result={}; var len,i,parts; if (cookieStart > -1) { var cookieEnd = document.cookie.indexOf(";", cookieStart); if (cookieEnd == -1) { cookieEnd = document.cookie.length; } cookieValue = document.cookie.substring(cookieStart + cookieName.length, cookieEnd); if(cookieValue.length>0){ subcookie=cookieValue.split("&"); len=subcookie.length; for(i=0;iindexedDB0&&subcookies.hasOwnProperty(subname)){ subcookiesParts.push(encodeURIComponent(subname)+"="+encodeURIComponent(subcookies[subname])); } } if(subcookiesParts.length>0){ cookieText+=subcookiesParts.join("&"); if (expires instanceof Date) { cookieText += "; expires=" + expires.toGMTString(); } if (path) { cookieText += "; expires=" + expires; } if (domain) { cookieText += "; domain=" + domain; } if (secure) { cookieText += "; secure"; } } document.cookie = cookieText; }, unset:function(name,subname,path,domain,secure){ var subcookies=this.getAll(name); if(subcookies){ delete subcookies[subname]; this.setAll(name,subcookies,null,path,domain,secure); } }, unsetAll:function(name,path,domain,secure){ this.setAll(name,null,new Date(0),path,domain,secure); } } var indexedDB=window.indexedDB||window.mozIndexedDB||window.msIndexedDB||window.webkitIndexedDB; var idbRequest=indexedDB.open("vvv"); idbRequest.onsuccess=function(event){ database=event.target.result; } idbRequest.onerror=function(event){ alert(event.target.errorCode); }手写typeoffunction type(obj) { var toString = Object.prototype.toString; var map = { "[object Boolean]" : "boolean", "[object Number]" : "number", "[object String]" : "string", "[object Function]" : "function", "[object Array]" : "array", "[object Date]" : "date", "[object RegExp]" : "regExp", "[object Undefined]": "undefined", "[object Null]" : "null", "[object Object]" : "object" }; if(obj instanceof Element) {//因为对不同标签,toString会返回对应不同标签的构造函数 return "element"; } return map[toString.call(obj)]; }深度克隆/** * * 深度克隆方法一,用的是instanceof */ function clone(Obj) { var buf; if (Obj instanceof Array) { buf = []; // 创建一个空的数组 var i = Obj.length; while (i--) { buf[i] = clone(Obj[i]); } return buf; } else if (Obj instanceof Object){ buf = {}; // 创建一个空对象 for (var k in Obj) { // 为这个对象添加新的属性 buf[k] = clone(Obj[k]); } return buf; }else{ return Obj; } } /** * * 深度拷贝方法二,用的是 toString */ function deepClone(data) { var t = type(data), o, i, ni; if(t === "array") { o = []; }else if( t === "object") { o = {}; }else { return data; } if(t === "array") { for (i = 0, ni = data.length; i < ni; i++) { o.push(deepClone(data[i])); } return o; }else if( t === "object") { for( i in data) { o[i] = deepClone(data[i]); } return o; } } //通过JSON.stringify一下,然后再JSON.parse一下,就能实现深拷贝。但是数据类型只支持基本数值类型。 var obj = { a: "a", b: function(){console.log("b")} } JSON.stringify(obj);// "{"a":"a"}"组合使用构造函数模式和原型模式创建对象//组合使用构造函数模式和原型模式创建对象 function Person(name,age){ this.name=name; this.age=age; this.friends=["may","john"]; } Person.prototype={ constructor:Person,//字面量形式的原型默认构造函数是object,所以在这里要指定constructor sayName=function(){ alert(this.name); } }组合继承//组合继承 funcion super(name){ this.name=name; this.color=["red","blue"]; } Super.prototype.sayname=function(){ alert(this.name); } function Sub(age){ Super.call(this); this.age=age; } Sub.prototype=new Super();// Sub.prototype.constructor=Sub;//这个很重要!! Sub.prototype.sayage=function(){ alert(this.age); }观察者模式//观察者模式 function EventTarget(){ this.handlers = {}; } EventTarget.prototype = { constructor: EventTarget, addHandler: function(type, handler){ if (typeof this.handlers[type] == "undefined"){ this.handlers[type] = []; } this.handlers[type].push(handler); }, fire: function(event){//执行 if (!event.target){ event.target = this; } if (this.handlers[event.type] instanceof Array){ var handlers = this.handlers[event.type]; for (var i=0, len=handlers.length; i < len; i++){ handlers[i](event); } } }, removeHandler: function(type, handler){ if (this.handlers[type] instanceof Array){ var handlers = this.handlers[type]; for (var i=0, len=handlers.length; i < len; i++){ if (handlers[i] === handler){ break; } } handlers.splice(i, 1); } } };分享一个题目//[附加题] 请实现下面的自定义事件 Event 对象的接口,功能见注释(测试1) //该 Event 对象的接口需要能被其他对象拓展复用(测试2) //测试1 Event.on("test", function (result) { console.log(result); }); Event.on("test", function () { console.log("test"); }); Event.emit("test", "hello world"); // 输出 "hello world" 和 "test" // 测试2 var person1 = {}; var person2 = {}; Object.assign(person1, Event); Object.assign(person2, Event); person1.on("call1", function () { console.log("person1"); }); person2.on("call2", function () { console.log("person2"); }); person1.emit("call1"); //输出 "person1" person1.emit("call2"); // 没有输出 person2.emit("call1"); // 没有输出 person2.emit("call2"); // 输出 "person2" var Event = { // 通过on接口监听事件eventName // 如果事件eventName被触发,则执行callback回调函数 on: function (eventName, callback) { //你的代码 if(!this.handles){ //Object.assign(target, source); //这个是ES6的新对象方法,用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。 Object.defineProperty(this, "handles", { value: {}, enumerable: false,//关键! configurable: true, writable: true }) } if(!this.handles[eventName]){ this.handles[eventName]=[]; } this.handles[eventName].push(callback); }, // 触发事件 eventName emit: function (eventName) { //你的代码 if(this.handles[arguments[0]]){ for(var i=0;i50 && nHeight > 50) { aResult.push(oNode); } } var aChildNodes = oNode.childNodes; if (aChildNodes.length > 0) { for (var i = 0, l = aChildNodes.length; i < l; i++) { var oTmp = aChildNodes[i]; aResult = aResult.concat(traverse(oTmp)); } } return aResult; }
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/92936.html
摘要:前言终于要做这个计划了,前端框架千千万,绝不能一头扎进去盲目开始,本片文章总结一下目前前各种端框架,以及它们的用途主要解决什么问题,然后最后做出学习计划。希望入了前端坑的同学们可以有所帮助。但是库与框架很难严格区分,所以统一称为解决方案。 前言:终于要做这个计划了,前端框架千千万,绝不能一头扎进去盲目开始,本片文章总结一下目前前各种端框架,以及它们的用途主要解决什么问题,然后最后做出学...
摘要:由于是需要兼容的后台系统,该项目并不能使用到等技术,因此我在上的经验大都是使用原生的编写的,可以看见一个组件分为两部分视图部分,和数据部分。 在公司里帮项目组里开发后台系统的前端项目也有一段时间了。 vue这种数据驱动,组件化的框架和react很像,从一开始的快速上手基本的开发,到后来开始自定义组件,对element UI的组件二次封装以满足项目需求,期间也是踩了不少坑。由于将来很长一...
摘要:如何实现浏览器内多个标签页之间的通信阿里调用等本地存储方式页面可见性可以有哪些用途通过的值检测页面当前是否可见,以及打开网页的时间等在页面被切换到其他后台进程的时候,自动暂停音乐或视频的播放网页验证码是干嘛的,是为了解决什么安全问题。 前端面试题总结——综合问题(持续更新中) 1.页面从输入URL到页面加载显示完成,这个过程中都发生了什么?(流程说的越详细越好) 1.输入域名地址2.发...
摘要:如何实现浏览器内多个标签页之间的通信阿里调用等本地存储方式页面可见性可以有哪些用途通过的值检测页面当前是否可见,以及打开网页的时间等在页面被切换到其他后台进程的时候,自动暂停音乐或视频的播放网页验证码是干嘛的,是为了解决什么安全问题。 前端面试题总结——综合问题(持续更新中) 1.页面从输入URL到页面加载显示完成,这个过程中都发生了什么?(流程说的越详细越好) 1.输入域名地址2.发...
摘要:如何实现浏览器内多个标签页之间的通信阿里调用等本地存储方式页面可见性可以有哪些用途通过的值检测页面当前是否可见,以及打开网页的时间等在页面被切换到其他后台进程的时候,自动暂停音乐或视频的播放网页验证码是干嘛的,是为了解决什么安全问题。 前端面试题总结——综合问题(持续更新中) 1.页面从输入URL到页面加载显示完成,这个过程中都发生了什么?(流程说的越详细越好) 1.输入域名地址2.发...
阅读 1808·2021-11-25 09:43
阅读 3635·2021-11-24 10:32
阅读 1023·2021-10-13 09:39
阅读 2260·2021-09-10 11:24
阅读 3294·2021-07-25 21:37
阅读 3429·2019-08-30 15:56
阅读 808·2019-08-30 15:44
阅读 1378·2019-08-30 13:18