一、前言
因为一个很小的项目或者说几个页面却要搭上Jquery,当然很不值,gzip下,好歹也有小几十K。为了能够方便的操作Dom,我们需要写很多兼容性的原生JS。就在我看leaflet的源码的时候,我觉得它的DomUtil写的还是不错的。
二、具体的代码分析
首先,我们定义一个类,var DomUtil = { functionName: function(){ } }; 以下均已字面量的形式表示。
(1)get: 获取一个元素
get: function (id) { return typeof id === 'string' ? document.getElementById(id) : id; }
很简单吧,只是粗略的返回是元素或者传进来的参数。
(2)getStyle:获取元素的样式
getStyle: function (el, style) { //IE: currentStyle //Firefox: defaultView var value = el.style[style] || (el.currentStyle && el.currentStyle[style]); if ((!value || value === 'auto') && document.defaultView) { var CSS = document.defaultView.getComputedStyle(el, null); value = css ? css[style] : null; } return value === 'auto' ? null : value; }
(3)create:创建一个元素(可以将其放入父元素)
//创建一个元素(可以将其放入父元素) create: function (tagName, className, container) { var el = document.createElement(tagName); el.className = className; //是否存在父容器 if (container) { container.appendChild(el); } return el; }
(4)remove:移除元素
//移除元素 //先获取父元素,然后父元素移除子元素 remove: function (el) { var parent = el.parentNode; if (parent) { parent.removeChild(el); } }
(5)empty:清空元素内部子元素
//清空元素内部子元素 empty: function (el) { while (el.firstChild) { el.removeChild(el.firstChild); } }
(6)toFront:将元素取出放在队尾或者说是叠加层的最上面,就像加饼一样,一层一层往上放,但是如果引用的是同一个元素,则在父容器中有且仅存在一个元素。
//置于顶上 toFront: function (el) { el.parentNode.appendChild(el); }
(6)toBack:置于队首或者叠加层底部。
//置于底部 toBack: function (el) { var parent = el.parentNode; //insertBefore:insertBefore(newchild,refchild) parent.insertBefore(el, parent.firstChild); }
(7)hasClass:是否有CSS样式
//返回class集合 getClass: function (el) { return el.className.baseVal === undefined ? el.className : el.className.baseVal; }
className.baseVal是获取SVG的一个方法,className是获取带空格类名的集合。
1 //是否有CSS类2 hasClass: function (el, name) {3 //先判断是否支持了classList,classList包含了has、add、remove等方法4 if (el.classList !== undefined) {5 return el.classList.contains(name);6 }7 var className = L.DomUtil.getClass(el);8 return className.length > 0 && new RegExp('(^|//s)' + name + '(//s|$)').test(className);9 }
上面代码第8行,用正则test测试字符串是否含有此模式。
(8)addClass:增加类样式
1 //设置class2 setClass: function (el, name) {3 if (el.className.baseVal === undefined) {4 el.className = name;5 } else {6 // in case of SVG element7 el.className.baseVal = name;8 }9 }
1 //增加类串 2 addClass: function (el, name) { 3 if (el.classList !== undefined) { 4 var classes = L.Util.splitWords(name); 5 for (var i = 0, len = classes.length; i < len; i++) { 6 //调用classList的add 7 el.classList.add(classes[i]); 8 } 9 } else if (!L.DomUtil.hasClass(el, name)) {10 var className = L.DomUtil.getClass(el);11 //setClass,覆盖之前的类串12 L.DomUtil.setClass(el, (className ? className + ' ' : '') + name);13 }14 }
(9)removeClass:移除class
1 //移除class2 removeClass: function (el, name) {3 if (el.classList !== undefined) {4 el.classList.remove(name);5 } else {6 //以字符串的形式替换7 L.DomUtil.setClass(el, L.Util.trim((' ' + L.DomUtil.getClass(el) + ' ').replace(' ' + name + ' ', ' ')));8 }9 }
(10)设置透明度
1 //设置透明度 2 setOpacity: function (el, value) { 3 //如果存在opactity的属性 4 if ('opacity' in el.style) { 5 el.style.opacity = value; 6 7 } else if ('filter' in el.style) {//存在filter 8 9 var filter = false,10 filterName = 'DXImageTransform.Microsoft.Alpha';11 12 // filters collection throws an error if we try to retrieve a filter that doesn't exist13 try {14 filter = el.filters.item(filterName);15 } catch (e) {16 // don't set opacity to 1 if we haven't already set an opacity,17 // it isn't needed and breaks transparent pngs.18 if (value === 1) { return; }19 }20 21 value = Math.round(value * 100);22 23 if (filter) {24 filter.Enabled = (value !== 100);25 filter.Opacity = value;26 } else {27 el.style.filter += ' PRogid:' + filterName + '(opacity=' + value + ')';28 }29 }30 }
三、附上源码
1 /* 2 * L.DomUtil contains various utility functions for working with DOM. 3 */ 4 5 L.DomUtil = { 6 get: function (id) { 7 return typeof id === 'string' ? document.getElementById(id) : id; 8 }, 9 //js如何获取一个元素的样式 10 getStyle: function (el, style) { 11 //IE: currentStyle 12 //firefox: defaultView 13 var value = el.style[style] || (el.currentStyle && el.currentStyle[style]); 14 15 if ((!value || value === 'auto') && document.defaultView) { 16 var css = document.defaultView.getComputedStyle(el, null); 17 value = css ? css[style] : null; 18 } 19 20 return value === 'auto' ? null : value; 21 }, 22 //创建一个元素(可以将其放入父元素) 23 create: function (tagName, className, container) { 24 var el = document.createElement(tagName); 25 el.className = className; 26 //是否存在父容器 27 if (container) { 28 container.appendChild(el); 29 } 30 31 return el; 32 }, 33 //移除元素 34 //先获取父元素,然后父元素移除子元素 35 remove: function (el) { 36 var parent = el.parentNode; 37 if (parent) { 38 parent.removeChild(el); 39 } 40 }, 41 //清空元素内部子元素 42 empty: function (el) { 43 while (el.firstChild) { 44 el.removeChild(el.firstChild); 45 } 46 }, 47 //置于顶上 48 toFront: function (el) { 49 el.parentNode.appendChild(el); 50 }, 51 //置于底部 52 toBack: function (el) { 53 var parent = el.parentNode; 54 //insertBefore:insertBefore(newchild,refchild) 55 parent.insertBefore(el, parent.firstChild); 56 }, 57 //是否有CSS类 58 hasClass: function (el, name) { 59 //先判断是否支持了classList,classList包含了has、add、remove等方法 60 if (el.classList !== undefined) { 61 return el.classList.contains(name); 62 } 63 var className = L.DomUtil.getClass(el); 64 return className.length > 0 && new RegExp('(^|//s)' + name + '(//s|$)').test(className); 65 }, 66 //增加类串 67 addClass: function (el, name) { 68 if (el.classList !== undefined) { 69 var classes = L.Util.splitWords(name); 70 for (var i = 0, len = classes.length; i < len; i++) { 71 //调用classList的add 72 el.classList.add(classes[i]); 73 } 74 } else if (!L.DomUtil.hasClass(el, name)) { 75 var className = L.DomUtil.getClass(el); 76 //setClass,覆盖之前的类串 77 L.DomUtil.setClass(el, (className ? className + ' ' : '') + name); 78 } 79 }, 80 //移除class 81 removeClass: function (el, name) { 82 if (el.classList !== undefined) { 83 el
新闻热点
疑难解答