DOM方法总结及DOM库扩展
常用DOM方法 |
常用DOM方法:
方法 | 作用 |
---|---|
document.getElementById(“id”); | 通过元素的ID来获取元素对象 |
context.getElementsByTagName(“table”); | 通过元素的标签名来获取元素对象,把容器中所有子子孙孙的元素都获取到 |
document.getElementsByName(“abc”); | 通过元素的name属性来获取元素对象 |
context.getElementsByClassName(“abc”); | 通过元素的class属性来获取元素对象 |
document.documentElement | 返回文档的根节点 |
document.body | 获取body元素 |
context.querySelector(“#id”); | 移动端获取一个元素,节点集合不存在DOM映射 |
context.querySelectorAll(“#id”); | 移动端获取多个元素,节点集合不存在DOM映射 |
appendChild(newListItem); | 把元素添加到指定的容器中(末尾) |
document.createElement(“div”); | 创建一个元素标签对象 |
insertBefore(newItem,existingItem); | 把新元素添加到老元素之前 |
removeChild(); | 删除元素 |
cloneNode(false/true); | 克隆元素:false:只克隆当前元素;true:把元素内的子子孙孙都克隆 |
replaceChild(newnode,oldnode); | 替换元素 |
getAttribute(“target”); | 获取元素属性 |
setAttribute(“type”,”button”); | 添加指定的属性,并为其赋指定的值,如:设置input元素的type属性为button,不能修改class属性 |
removeAttribute(“abc”); | 删除属性 |
document.createDocumentFragment(); | 创建文档碎片 |
innerHTML | 获取对象的内容或向对象插入内容 |
DOM节点和关系属性:
节点 | 含义 |
---|---|
childNodes | 获取所有子节点 |
children | 获取所有元素子节点 |
parentNode | 获取父亲节点 |
previousSibling | 获取上一个哥哥节点(所有节点,包括文本节点) |
previousElementSibling | 获取上一个哥哥节点(元素节点) |
nextSibling | 获取弟弟节点 |
firstChild | 获取所有节点中的第一个 |
lastChild | 获取所有节点中的最后一个 |
节点 | nodeType | nodeName | nodeValue |
---|---|---|---|
元素节点(元素标签) | 1 | 大写的标签名 | null |
属性节点 | 2 | 小写属性名 | 属性内容 |
文本节点(文字) | 3 | #text | 文字内容 |
注释节点(注释) | 8 | #comment | 注释内容 |
document | 9 | #document | null |
DOM的盒子模型:
名称 | 含义 |
---|---|
clientWidth/clientHeight | width+左右padding;height+上下padding |
clientTop/clientLeft | 上边框的高度;左边框的宽度 |
offsetWidth/offsetHeight | clientWidth+左右边框;clientHeight+上下边框 |
offsetLeft/offsetTop | 当前元素的外边框距离父级参照物的左偏移量;当前元素的外边框距离父级参照物的上偏移量 |
scrollWidth/scrollHeight | 约等于真实内容的宽度(包含溢出的内容)+左padding;约等于真实内容的高度(包含溢出的内容)+上padding |
scrollLeft/scrollTop | 当前滚动条卷去的宽度;当前滚动条卷去的高度 |
DOM方法扩展 |
1.children——作用:获取某一个容器中所有的元素子节点(还可以筛选出指定标签名) |
HTML代码:
<div id="div1">
<div></div>
<div></div>
<div>
<p></p>
<p></p>
</div>
<p id="p1"></p>
<p></p>
<p></p>
</div>
获取div1下的所有元素子节点(儿子级别):
var oDiv = document.getElementById("div1");
console.log(oDiv.children.length); //6
但是children方法在非标准浏览器下不兼容,故需重写children方法
算法分析:首先获取所有的子节点(childNode),在所有的子节点中,把元素节点过滤出来,即nodeType===1。如果多传一个标签名,进行二次筛选,获取指定标签名的集合。代码如下:
function children(curEle, tagName) {
var ary = [];
if (/MSIE (6|7|8)/i.test(navigator.userAgent)) { //判断是不是IE浏览器
var nodeList = curEle.childNodes;
for (var i = 0; i < nodeList.length; i++) {
var curNode = nodeList[i];
curNode.nodeType === 1 ? ary[ary.length] = curNode : null;
}
nodeList = null;
} else { //标准浏览器中直接使用children
ary = Array.prototype.slice.call(curEle.children); //children返回的是类数组,为了和上面保持一致,将类数组转为数组
}
if (typeof tagName === "string") {
for (var j = 0; j < ary.length; j++) { //小心数组塌陷
var curEleNode = ary[j];
if (curEleNode.nodeName.toLowerCase() !== tagName.toLowerCase()) { //不是想要的那个标签
ary.splice(j, 1);
j--;
}
}
}
return ary;
}
var oDiv = document.getElementById("div1");
console.log(children(oDiv,"div")); //Array(3)
2.getElementsByClass——作用:通过元素的样式类名获取一组元素集合(兼容所有浏览器) |
jQuery中没有此方法,但jQuery的一部分选择器也是基于这个方法的原理来实现的
getElementsByClassName()原方法:写一个样式类名的话,只要包含这个样式类名就可以;写两个的话,只要同时包含这两个就可以,但和样式的顺序以及中间有多少个空格是没有关系的;如果不写,结果是一个空的集合
var flag = "getComputedStyle" in window; //判断是否兼容
//参数className是要获取的样式类名(可能是多个也可能是一个)
//context是获取的上下文,不传递值的话默认是document
function getElementsByClass(className, context) {
context = context || document;
if (flag) {
return listToArray(context.getElementsByClassName(className)); //this.listToArray类数组转为数组
}
//把传递进来的样式类名的首尾空格去掉,然后在按照中间的空格把里面的每一项拆分成数组
var ary = [], classNameAry = className.replace(/(^ +| +$)/g, "").split(/ +/g);
//获取指定上下文元素中的所有的元素标签,循环这些标签,获取每个标签的className的样式类名字符串
var nodeList = context.getElementsByTagName("*"); //获取所有的元素标签
for (var i = 0; i < nodeList.length; i++) {
var curNode = nodeList[i];
//判断curNode.className是否包含参数,如果两个都包含,curNode就是想要的,否则不是
var isOK = true; //假设curNode中包含了所有的样式
for (var j = 0; j < classNameAry.length; j++) { //循环classNameAry这个数组
var reg = new RegExp("(^| +)" + classNameAry[j] + "( +|$)");
if (!reg.test(curNode.className)) {
isOK = false;
break;
}
}
if (isOK) { //拿每一个标签分别和所有样式类名比较后,如果结果还是true,说明当前元素标签包含了所有的样式,也是想要的
ary[ary.length] = curNode;
}
}
return ary;
}
3.获取上一个哥哥元素节点(prev)、获取下一个弟弟元素节点(next)、获取所有的哥哥元素节点(prevAll)、获取所有的弟弟元素节点(nextAll)、获取相邻的两个元素节点(sibling)、获取所有的兄弟元素节点(siblings) |
获取上一个哥哥元素节点(prev):
prev算法分析:首先获取当前元素的上一个哥哥节点,判断是否为元素节点,不是的话基于当前的继续找上面的哥哥节点,一直找到哥哥元素节点为止,如果没有哥哥节点,返回null。代码如下:
var flag = "getComputedStyle" in window; //判断是否兼容
function prev(curEle) {
if (flag) {
return curEle.previousElementSibling;
}
var pre = curEle.previousSibling;
while (pre && pre.nodeType !== 1) {
pre = pre.previousSibling;
}
return pre;
}
var op = document.getElementById("p1");
console.log(prev(op));
获取下一个弟弟元素节点(next):
代码如下:
var flag = "getComputedStyle" in window; //判断是否兼容
function next(curEle) {
if (flag) {
return curEle.nextElementSibling;
}
var nex = curEle.nextSibling;
while (nex && nex.nodeType !== 1) {
nex = nex.nextSibling;
}
return nex;
}
var op = document.getElementById("p1");
console.log(next(op));
获取所有的哥哥元素节点(prevAll):
代码如下,prev方法见上:
function prevAll(curEle) {
var ary = [];
var pre = prev(curEle);
while (pre) {
ary.unshift(pre); //放到开头,防止倒序
pre = prev(pre);
}
return ary;
}
获取所有的弟弟元素节点(nextAll):
代码如下,next方法见上:
function nextAll(curEle) {
var ary = [];
var nex = next(curEle);
while (nex) {
ary.push(nex);
nex = next(nex);
}
return ary;
}
获取相邻的两个元素节点(sibling):
prev和next方法见上:
function sibling(curEle) {
var pre = this.prev(curEle);
var nex = this.next(curEle);
var ary = [];
pre ? ary.push(pre) : null;
nex ? ary.push(nex) : null;
return ary;
}
获取所有的兄弟元素节点(siblings):
prevAll和nextAll方法见上:
function siblings(curEle) {
return this.prevAll(curEle).concat(this.nextAll(curEle));
}
4.获取第一个元素子节点(firstChild)、获取最后一个元素子节点(lastChild) |
这两个方法jQuery中没有
获取第一个元素子节点(firstChild):
function firstChild(curEle) {
var chs = this.children(curEle);
return chs.length > 0 ? chs[0] : null;
}
获取最后一个元素子节点(lastChild):
function lastChild(curEle) {
var chs = this.children(curEle);
return chs.length > 0 ? chs[chs.length-1] : null;
}
5.获取当前元素索引(index) |
有几个哥哥索引就是几,代码如下:
function index(curEle) {
return this.prevAll(curEle).length;
}
6.prepend——作用:增加到某一个容器的开头(与appendChild对应) |
append:向指定容器的末尾追加元素(重新appendChild方法):
function append(newEle,container) {
container.appendChild(newEle);
}
prepend:增加元素到某一个容器的开头
算法分析:把新的元素添加到容器中第一个子元素节点的前面,如果一个元素子节点都没有,就放在末尾即可
function prepend(newEle, container) {
var fir = this.firstChild(container);
if (fir) {
container.insertBefore(newEle, fir);
return;
}
container.appendChild(newEle);
}
7.insertAfter——作用:增加到容器中某一个元素的后面(与insertBefore对应) |
重写insertBefore:追加到指定元素的前面
function insertBefore(newEle, oldEle) {
oldEle.parentNode.insertBefore(newEle, oldEle);
}
insertAfter相当于追加到oldEle弟弟元素的前面,如果弟弟不存在,也就是当前元素已经是最后一个了,把新的元素放在最末尾即可
function insertAfter(newEle, oldEle) {
var nex = this.next(oldEle);
if (nex) {
oldEle.parentNode.insertBefore(newEle, nex);
return;
}
oldEle.parentNode.appendChild(newEle);
}
8.hasClass——作用:判断是否存在某一个样式类名 |
function hasClass(curEle, clasName) {
var reg = new RegExp("(^| +)" + clasName + "( +|$)");
return reg.test(curEle.clasName);
}
9.removeClass——作用:删除样式类名 |
function removeClass(curEle, className) {
var ary = className.replace(/(^ +| +$)/g,"").split(/ +/g);
for (var i = 0; i < ary.length; i++) {
var curName = ary[i];
if (this.hasClass(curEle, curName)) {
var reg = new RegExp("(^| +)" + curName + "( +|$)", "g");
curEle.className = curEle.className.replace(reg, " ");
}
}
}
10.addClass——作用:给元素增加样式类名 |
function addClass(curEle, className) {
//为了防止className传递进来的值包含多个类名,把传递进来的值以一个或多个空格拆分成数组
var ary = className.replace(/(^ +| +$)/g,"").splice(/ +/g);
//循环数组,一项一项进行验证增加
for (var i = 0; i < ary.length; i++) {
var curName = ary[i];
if (!this.hasClass(curEle, className)) {
curEle.className += " " + curName;
}
}
}
11.getCss、setCss、setGroupCss获取/设置/批量设置css |
jQuery中统一叫css方法
getCss代码:
function getCss(curEle, attr) {
//处理带单位的问题
var reg = /^-?\d+(\.\d+)?(?:px|em|pt|deg|rem)?$/;
var val = null;
if (/MSIE (?:6|7|8)/.test(window.navigator.userAgent)) {
//这里处理filter的滤镜问题 alpha(opacity=40);
if (attr === 'opacity') {
//alpha(opacity=40)
val = curEle.currentStyle['filter'];
var reg1 = /^alpha\(opacity=(\d+(\.\d+)?)\)/;
return reg1.test(val) ? RegExp.$1 / 100 : 1;
}
val = curEle.currentStyle[attr];
} else {
val = window.getComputedStyle(curEle, null)[attr];
}
return reg.test(val) ? parseFloat(val) : val; //如果正则验证通过,寿命返回值是带单位的,那么我们就要人为去掉这个单位。否则不变
}
JS中给元素设置属性值,只能通过curEle.style[attr] = value这种方式给当前元素设置属性
setCss:给当前元素的某一个样式属性设置值(增加在行内样式上),代码如下:
function setCss(curEle, attr, value) {
if (attr === "float") { //浮动的兼容问题
curEle["style"]["cssFloat"] = value;
curEle["style"]["styleFloat"] = value;
return;
}
if (attr === "opacity") { //透明度的兼容问题
curEle["style"]["opacity"] = value;
curEle["style"]["filter"] = "alpha(opacity=" + value * 100 + ")";
return;
}
//对于某些样式属性,如果传递来的属性没有加单位,需要把单位默认的补上
var reg = /^(width|height|top|bottom|left|right|((margin|padding)(Top|Bottom|Left|Right)?))$/;
if (reg.test(attr)) {
if (!isNaN(value)) { //判断传递进来的value是否是一个有效数字
value += "px";
}
}
curEle["style"][attr] = value;
}
setGroupCss:批量设置css属性
代码如下:
function setGroupCss(curEle, options) {
options = options || 0;
//通过检测options的数据类型,如果不是一个对象,则不能进行批量的设置
if (options.toString() !== "[object][Object]") {
return;
}
//遍历对象中的每一项,调取setCss方法一个个的进行设置
for (var key in options) {
if(options.hasOwnProperty(key)){
this.setCss(curEle, key, options[key]);
}
}
}
setGroupCss(box, {
width: 20,
backgroundColor: "red",
float: "right",
padding: 10
});
css:此方法实现了获取、单独设置、批量设置元素的样式值
代码如下:
function css(curEle) {
var argTwo = arguments[1];
if (typeof argTwo === "string") { //第二个参数是一个字符串,这样的话很有可能就是在获取样式(还需要判断第三个参数)
var argThree = arguments[2];
if (!argThree) { //第三个参数不存在
return this.getCss.apply(this, arguments);
}
//第三个参数存在则为单独设置
this.setCss.apply(this, arguments);
}
argTwo = argTwo || 0;
if (argTwo.toString() === "[object Object]") {
//批量设置样式属性值
this.setGroupCss.apply(this, arguments);
}
}
公共方法库 |
var utils = (function () {
var flag = "getComputedStyle" in window;
//->listToArray:把类数组集合转换为数组
function listToArray(likeAry) {
if (flag) {
return Array.prototype.slice.call(likeAry, 0);
}
var ary = [];
for (var i = 0; i < likeAry.length; i++) {
ary[ary.length] = likeAry[i];
}
return ary;
}
//->formatJSON:把JSON格式字符串转换为JSON格式对象
function formatJSON(jsonStr) {
return "JSON" in window ? JSON.parse(jsonStr) : eval("(" + jsonStr + ")");
}
//->offset:获取页面中任意元素距离BODY的偏移
function offset(curEle) {
var disLeft = curEle.offsetLeft, disTop = curEle.offsetTop, par = curEle.offsetParent;
while (par) {
if (navigator.userAgent.indexOf("MSIE 8") === -1) {
disLeft += par.clientLeft;
disTop += par.clientTop;
}
disLeft += par.offsetLeft;
disTop += par.offsetTop;
par = par.offsetParent;
}
return {left: disLeft, top: disTop};
}
//->win:操作浏览器的盒子模型信息
function win(attr, value) {
if (typeof value === "undefined") {
return document.documentElement[attr] || document.body[attr];
}
document.documentElement[attr] = value;
document.body[attr] = value;
}
//->children:获取所有的元素子节点
function children(curEle, tagName) {
var ary = [];
if (!flag) {
var nodeList = curEle.childNodes;
for (var i = 0, len = nodeList.length; i < len; i++) {
var curNode = nodeList[i];
curNode.nodeType === 1 ? ary[ary.length] = curNode : null;
}
nodeList = null;
} else {
ary = this.listToArray(curEle.children);
}
if (typeof tagName === "string") {
for (var k = 0; k < ary.length; k++) {
var curEleNode = ary[k];
if (curEleNode.nodeName.toLowerCase() !== tagName.toLowerCase()) {
ary.splice(k, 1);
k--;
}
}
}
return ary;
}
//->prev:获取上一个哥哥元素节点
//->首先获取当前元素的上一个哥哥节点,判断是否为元素节点,不是的话基于当前的继续找上面的哥哥节点...一直到找到哥哥元素节点为止,如果没有哥哥元素节点,返回null即可
function prev(curEle) {
if (flag) {
return curEle.previousElementSibling;
}
var pre = curEle.previousSibling;
while (pre && pre.nodeType !== 1) {
pre = pre.previousSibling;
}
return pre;
}
//->next:获取下一个弟弟元素节点
function next(curEle) {
if (flag) {
return curEle.nextElementSibling;
}
var nex = curEle.nextSibling;
while (nex && nex.nodeType !== 1) {
nex = nex.nextSibling;
}
return nex;
}
//->prevAll:获取所有的哥哥元素节点
function prevAll(curEle) {
var ary = [];
var pre = this.prev(curEle);
while (pre) {
ary.unshift(pre);
pre = this.prev(pre);
}
return ary;
}
//->nextAll:获取所有的弟弟元素节点
function nextAll(curEle) {
var ary = [];
var nex = this.next(curEle);
while (nex) {
ary.push(nex);
nex = this.next(nex);
}
return ary;
}
//->sibling:获取相邻的两个元素节点
function sibling(curEle) {
var pre = this.prev(curEle);
var nex = this.next(curEle);
var ary = [];
pre ? ary.push(pre) : null;
nex ? ary.push(nex) : null;
return ary;
}
//->siblings:获取所有的兄弟元素节点
function siblings(curEle) {
return this.prevAll(curEle).concat(this.nextAll(curEle));
}
//->index:获取当前元素的索引
function index(curEle) {
return this.prevAll(curEle).length;
}
//->firstChild:获取第一个元素子节点
function firstChild(curEle) {
var chs = this.children(curEle);
return chs.length > 0 ? chs[0] : null;
}
//->lastChild:获取最后一个元素子节点
function lastChild(curEle) {
var chs = this.children(curEle);
return chs.length > 0 ? chs[chs.length - 1] : null;
}
//->append:向指定容器的末尾追加元素
function append(newEle, container) {
container.appendChild(newEle);
}
//->prepend:向指定容器的开头追加元素
//->把新的元素添加到容器中第一个子元素节点的前面,如果一个元素子节点都没有,就放在末尾即可
function prepend(newEle, container) {
var fir = this.firstChild(container);
if (fir) {
container.insertBefore(newEle, fir);
return;
}
container.appendChild(newEle);
}
//->insertBefore:把新元素(newEle)追加到指定元素(oldEle)的前面
function insertBefore(newEle, oldEle) {
oldEle.parentNode.insertBefore(newEle, oldEle);
}
//->insertAfter:把新元素(newEle)追加到指定元素(oldEle)的后面
//->相当于追加到oldEle弟弟元素的前面,如果弟弟不存在,也就是当前元素已经是最后一个了,我们把新的元素放在最末尾即可
function insertAfter(newEle, oldEle) {
var nex = this.next(oldEle);
if (nex) {
oldEle.parentNode.insertBefore(newEle, nex);
return;
}
oldEle.parentNode.appendChild(newEle);
}
//->hasClass:验证当前元素中是否包含className这个样式类名
function hasClass(curEle, className) {
var reg = new RegExp("(^| +)" + className + "( +|$)");
return reg.test(curEle.className);
}
//->addClass:给元素增加样式类名
function addClass(curEle, className) {
var ary = className.replace(/(^ +| +$)/g, "").split(/ +/g);
for (var i = 0, len = ary.length; i < len; i++) {
var curName = ary[i];
if (!this.hasClass(curEle, curName)) {
curEle.className += " " + curName;
}
}
}
//->removeClass:给元素移除样式类名
function removeClass(curEle, className) {
var ary = className.replace(/(^ +| +$)/g, "").split(/ +/g);
for (var i = 0, len = ary.length; i < len; i++) {
var curName = ary[i];
if (this.hasClass(curEle, curName)) {
var reg = new RegExp("(^| +)" + curName + "( +|$)", "g");
curEle.className = curEle.className.replace(reg, " ");
}
}
}
//->getElementsByClass:通过元素的样式类名获取一组元素集合
function getElementsByClass(strClass, context) {
context = context || document;
if (flag) {
return this.listToArray(context.getElementsByClassName(strClass));
}
//->IE6~8
var ary = [], strClassAry = strClass.replace(/(^ +| +$)/g, "").split(/ +/g);
var nodeList = context.getElementsByTagName("*");
for (var i = 0, len = nodeList.length; i < len; i++) {
var curNode = nodeList[i];
var isOk = true;
for (var k = 0; k < strClassAry.length; k++) {
var reg = new RegExp("(^| +)" + strClassAry[k] + "( +|$)");
if (!reg.test(curNode.className)) {
isOk = false;
break;
}
}
if (isOk) {
ary[ary.length] = curNode;
}
}
return ary;
}
//->getCss:获取元素的样式值
function getCss(attr) {
var val = null, reg = null;
if (flag) {
val = window.getComputedStyle(this, null)[attr];
} else {
if (attr === "opacity") {
val = this.currentStyle["filter"];
reg = /^alpha\(opacity=(\d+(?:\.\d+)?)\)$/;
val = reg.test(val) ? reg.exec(val)[1] / 100 : 1;
} else {
val = this.currentStyle[attr];
}
}
reg = /^(-?\d+(\.\d+)?)(px|pt|em|rem)?$/;
return reg.test(val) ? parseFloat(val) : val;
}
//->setCss:给当前元素的某一个样式属性设置值(增加在行内样式上的)
function setCss(attr, value) {
if (attr === "float") {
this["style"]["cssFloat"] = value;
this["style"]["styleFloat"] = value;
return;
}
if (attr === "opacity") {
this["style"]["opacity"] = value;
this["style"]["filter"] = "alpha(opacity=" + value * 100 + ")";
return;
}
var reg = /^(width|height|top|bottom|left|right|((margin|padding)(Top|Bottom|Left|Right)?))$/;
if (reg.test(attr)) {
if (!isNaN(value)) {
value += "px";
}
}
this["style"][attr] = value;
}
//->setGroupCss:给当前元素批量的设置样式属性值
function setGroupCss(options) {
for (var key in options) {
if (options.hasOwnProperty(key)) {
setCss.call(this, key, options[key]);
}
}
}
//->css:此方法实现了获取、单独设置、批量设置元素的样式值
function css(curEle) {
var argTwo = arguments[1], ary = Array.prototype.slice.call(arguments, 1);
if (typeof argTwo === "string") {
if (!arguments[2]) {
return getCss.apply(curEle, ary);
}
setCss.apply(curEle, ary);
}
argTwo = argTwo || 0;
if (argTwo.toString() === "[object Object]") {
setGroupCss.apply(curEle, ary);
}
}
//->把外界需要使用的方法暴露给utils
return {
win: win,
offset: offset,
listToArray: listToArray,
formatJSON: formatJSON,
children: children,
prev: prev,
next: next,
prevAll: prevAll,
nextAll: nextAll,
sibling: sibling,
siblings: siblings,
index: index,
firstChild: firstChild,
lastChild: lastChild,
append: append,
prepend: prepend,
insertBefore: insertBefore,
insertAfter: insertAfter,
hasClass: hasClass,
addClass: addClass,
removeClass: removeClass,
getElementsByClass: getElementsByClass,
css: css
}
})();
还没有评论,来说两句吧...