烦恼
不知道有没有其他前端战友和我有一样的烦恼,Dom的基本操作源生和jQuery对Dom的操作老是搞混。花了好多时间去看源生Dom的节点操作或者一些api,然后隔了一段时间没捋,又TM忘记了。反正我是这样,前端框架层出不穷,前端库也百花齐放,看了再多的源码,再多的框架,别人问了你一个最最基本的Document.getElementByTag或者...ByClassName返还的是Dom还是什么结构的时候,当场懵逼了。写这篇文章的目的并不是为了分享给各位大佬看,而是方便自己以后隔三差五过来瞄一眼,或者当有其他人问我这方面的时候,url一丢给他,自己看去。尽显高手风范。
记住一点:技术要学,逼也要装。
下面出现的代码操作全部来自于git:一个小demo
原生Dom相关
针对源生没被包装过的Dom做的一些操作。
(一)获取dom操作
- getElementById
- getElementsByCLassName
- getElementsByTagName
- getElementsByName
1.getElementById
顾名思义,就是通过id字段去获取dom节点,而且获取到的就是源生Dom节点。
2.getElementsByCLassName
通过class属性去获取dom节点,返还的是一个类似于数组而非数组的一个结构。是一个HTMLCollection对象而非NodeList对象
html:
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
复制代码
js:
document.getElementsByClassName('box') instanceof NodeList
document.getElementsByClassName('box') instanceof HTMLCollection
Object.prototype.toString.call(document.getElementsByClassName('box'))
复制代码
输出结果分别是:
false
true
"[object HTMLCollection]"
复制代码
3.getElementsByTagName
通过标签tag名去获取dom节点,返还的是一个类似于数组而非数组的一个结构。是一个HTMLCollection对象而非NodeList对象
html:
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
复制代码
js:
document.getElementsByTagName('div') instanceof NodeList
document.getElementsByTagName('div') instanceof HTMLCollection
Object.prototype.toString.call(document.getElementsByTagName('div'))
复制代码
输出结果分别是:
false
true
"[object HTMLCollection]"
复制代码
4.getElementsByName
通过标签中的name属性去作为筛选条件
html:
<div name='box'>1</div>
<div name='box'>2</div>
<div name='box'>3</div>
<div name='box'>4</div>
复制代码
js:
document.getElementsByName('box')
Object.prototype.toString.call(document.getElementsByName('box'))
复制代码
输出结果:
NodeList(4)[div, div, div, div]
"[object NodeList]"
复制代码
通过name属性去获取的dom节点是一个NodeList数据结构的值
总结
4种原生常用获取dom节点,通过id获取的是可以直接使用的dom,通过className和TagName获取的是HTMLCollection的对象,里面包含的都是一个个dom,而通过Name属性获取的是基于NodeList对象的数据结构
(二)dom父子节点相关操作
- appendChild(node) - 插入新的子节点(元素)
- removeChild(node) - 删除子节点(元素)
- innerHTML - 节点(元素)的文本值
- parentNode - 节点(元素)的父节点
- childNodes - 节点(元素)的子节点
- children - 节点(元素)子节点
- attributes - 节点(元素)的属性节点
- nextSibling - 下一个兄弟节点
- previousSibling - 上一个兄弟节点
- firstChild - 第一个子节点
- lastChild - 最后一个子节点
- insertBefore - 插入在某个节点之前
方法很多,但是这里着重介绍childNodes和children
1.childNodes
调用childNodes方法返回的子节点包含了特殊的dom:text
例如 html:
<div class="box-1" id="box-1">
<div class="box-child1"></div>
<div class="box-child2">
<div class="box-child3"></div>
</div>
</div>
复制代码
document.getElementById('box-1').childNodes
document.getElementById('box-1').children
复制代码
输出结果:
NodeList(5)[text, div.box-child1, text, div.box-child2, text]
HTMLCollection(2)[div.box-child1, div.box-child2]
复制代码
结论: childNodes返回的是NodeList数据结构,里面出现了text节点,输出第一位元素的值,发现输出的值是#text,查看了Text的官方文档,提供了一个解释,因为换行,空格,tab等都会产生text的节点,故而只要把html中的元素进行新的排版
<div class="box-1" id="box-1"><div class="box-child1"></div><div class="box-child2"><div class="box-child3"></div></div></div>
复制代码
那么输出的结果就和children一样的了,但是children并不是w3c的标准,但是所有的浏览器都已经支持的。所以放心大胆的用children吧,免得text节点的存在影响你代码的逻辑。还有一点,childrenNode返还的是Nodelist数据结构,children返回的是HTMLCollection结构。
JQuery相关
jquery获取dom节点非常简单,通过$('')的方式传入 .类名、#id名、标签名等等就能筛选获取到经过jquery包装过的dom元素,但是这些dom元素不能直接使用dom元素的原生方法,而是jquery封装的一套方法。原因可以看源码,新写了一个Jquery对象,里面并没有原生的那些api了。
jQuery.parent(expr) //找父亲节点,可以传入expr进行过滤,比如$("span").parent(".class")
jQuery.parents(expr) //类似于jQuery.parents(expr),但是是查找所有祖先元素,不限于父元素
jQuery.children(expr) //返回所有子节点,这个方法只会返回直接的孩子节点,不会返回所有的子孙节点
jQuery.contents() //返回下面的所有内容,包括节点和文本。这个方法和children()的区别就在于,包括空白文本,也会被作为一个jQuery对象返回,children()则只会返回节点
jQuery.prev() //返回上一个兄弟节点,不是所有的兄弟节点
jQuery.prevAll() //返回所有之前的兄弟节点
jQuery.next() //返回下一个兄弟节点,不是所有的兄弟节点
jQuery.nextAll() //返回所有之后的兄弟节点
jQuery.siblings() //返回兄弟姐妹节点,不分前后
jQuery.find(expr) //跟jQuery.filter(expr)完全不一样。jQuery.filter()是从初始的jQuery对象集合中筛选出一部分,而jQuery.find()的返回结果,不会有初始集合中的内容,比如("p span").
jquery的所有dom操作api是有一个官方文档的,没必要去背,因为背了以后不用还是会忘,写多了就记下来了,遇到不会想不起来就上网搜,咱是开发,不是考试,哈哈哈哈 jquery-dom-api