Node(节点)1.Node概述 【DOM】文档对象模型 基本思想: (1)把结构文档解析成一系列节点,再由这些节点组成一个树状结构; (2)均有规范的对外结构,以便于编程(操作)文档(比如增删内容)。 ps:严格地说,DOM不属于JavaScript。 pss:但是操作DOM是JavaScript最常见的任务。 psss:而JavaScript也是最常用于DOM操作的语言。 pssss:所以,DOM往往放在JavaScript里面介绍。【Node】DOM的最小单位 对于HTML文档,Node主要有以下6中类型: 节点 名称 含义 Document 文档node 整个文档(window.document) DocumentType 文档类型node 文档的类型(比如:<DOCTYPE html>) Element 元素node HTML元素 Attribute 属性node HTML属性 Text 文本node HTML文档中出现的文本 DocumentFragment 文档碎片node 文档碎片 思考:节点集合是不是一个数组???2.【Node属性】(1)通用属性:nodeName,nodeType nodeName属性返回节点的名称, nodeType属性返回节点的常数值 类型 nodeName nodeType ELEMENT_NODE 大写的HTML元素名 1 ATTRIBUTE_NODE 等同于Attr.name 2 TEXT_NODE #text 3 其它现用现查(2)返回当前node的相关节点属性:ownerDocument、nextSibling,previousSibling,parentNode,parentElement 【ownerDocument】 ownerDocument属性返回当前节点所在的顶层文档对象,即document对象。 ps:document对象本身的ownerDocument属性,返回null。 思考:若是属性,文本节点呢?(均返回顶层Document对象) 【nextSibling】 nextSibling属性返回紧跟在当前节点后面的第一个同级节点。 如果当前节点后面没有同级节点,则返回null ps:从上述代码中能够得到的是,该属性还包括文本节点和评论节点。因此如果当前节点后面有空格,该属性会返回一个文本节点,内容为空格。 【previousSibling】 previousSibling属性返回当前节点前面的第一个同级节点。 如果当前节点前面没有同级节点,则返回null。 ps:对于当前节点前面有空格,则previoussibling属性会返回一个内容为空格的文本节点。 pss:回车也算是文本节点 【parentNode】 parentNode属性返回当前节点的父节点。 如果当前节点没有父节点,则返回null(document节点)。 ps:一般情况下,一个节点的父节点只可能是三种类型:element节点、document节点和documentfragment节点。 【parentElement】 parentElement属性返回当前节点的父元素节点。 如果当前节点没有父节点,或者父节点类型不是Element节点,则返回null(3)返回当前node的内容的属性:textContent,nodeValue 【textContent】 textContent属性返回当前节点和它的所有后代节点的文本内容。 【nodeValue】 nodeValue属性返回或设置当前节点的值,格式为字符串。 但是nodeValue只对Text节点(、Comment节点、XML文档的CDATA节点)有效,其他类型的节点一律返回null。(4)返回当前节点的子节点的属性:childNodes,firstChild,lastChild 【childNodes】 childNodes属性返回一个节点集合(NodeList),节点集合中包括当前节点的所有子节点。 【注】 ①如果当前节点不包括任何子节点,则返回一个空的NodeList集合。 ②由于NodeList对象是一个动态集合,一旦子节点发生变化,立刻会反映在返回结果之中。 【firstChild】 firstChild属性返回当前节点的第一个子节点,如果当前节点没有子节点,则返回null。 需要指出的是,除了HTML元素子节点,该属性还包括文本节点和评论节点。 【lastChild】 lastChild属性返回当前节点的最后一个子节点,如果当前节点没有子节点,则返回null。3.Node的方法(1) appendChild(),hasChildNodes() 【appendChild()】 appendChild()方法接受一个节点对象作为参数,将其作为最后一个子节点,插入当前节点 【hasChildNodes()】 hasChildNodes()方法返回一个布尔值,表示当前节点是否有子节点。(2) cloneNode(),insertBefore(),removeChild(),replaceChild() 【childNodes()】 cloneNode()方法用于克隆一个节点。它接受一个布尔值作为参数,表示是否同时克隆子节点。默认是false,即不克隆子节点。 【注】需要注意的是,克隆一个节点,会拷贝该节点的所有属性,但是会丧失addEventListener方法和on-属性(即node.onclick = fn)添加在这个节点上的事件回调函数。 【insertBefore()】 insertBefore方法用于将某个节点插入当前节点的指定位置。 它接受两个参数,第一个参数是所要插入的节点,第二个参数是当前节点的一个子节点,新的节点将插在这个节点的前面。 该方法返回被插入的新节点,根据情况不是必须创建变量来保存。 var text1 = document.createTextNode(‘1‘); var li = document.createElement(‘li‘); li.appendChild(text1); var ul = document.querySelector(‘ul‘); ul.insertBefore(li,ul.firstChild); 上述代码的作用是,将带有文字节点的li插入到ul的第一个子节点之前。 【removeChild()】 removeChild方法接受一个子节点作为参数,用于从当前节点移除该节点。 它返回被移除的节点,根据情况不是必须创建变量来保存。 【replaceChild()】 replaceChild方法用于将一个新的节点,替换当前节点的某一个子节点。 它接受两个参数,第一个参数是用来替换的新节点,第二个参数将要被替换走的子节点。它返回被替换走的那个节点。 var replacedNode = parentNode.replaceChild(newChild, oldChild); 例子: var divA = document.getElementById(‘A‘); var newSpan = document.createElement(‘span‘); newSpan.textContent = ‘Hello World!‘; divA.parentNode.replaceChild(newSpan,divA); 上述代码是将界面中的divA替换成了代码创建的span标签。(3) contains(),isEqualNode() 【contains()】 contains方法接受一个节点作为参数,返回一个布尔值。 contains方法表示判断【参数节点】是否为【当前节点】的子节点。 ps:document.body.contains(node) 检查某个节点,是否包含在当前文档之中。 pss:nodeA.contains(nodeA) // true 节点自身包含自身的结果是真的。虽然理论上很难解释 【isEqualNode()】 isEqualNode方法返回一个布尔值,用于检查两个节点是否相等。 ps:所谓相等的节点,指的是两个节点的类型相同、属性相同、子节点相同。4、HTML元素 html元素是网页的根元素,document.documentElement就指向这个元素。js中关于html元素也提供了一些相关的属性和方法来帮助我们更好的操作: (1)视图窗口大小:clientWidth属性,clientHeight属性 (2)html元素大小:offsetWidth属性,offsetHeight属性 ps:clientWidth和clientHeight这两个属性返回的是视口(viewport)的大小,单位为像素。 pss:clientWidth和clientHeight在计算视图大小的时候不计算滚动条部分。 psss:window.innerWidth和window.innerHeight包括了滚动条的高度和宽度。5.HTML内元素(1) 元素位置相关属性 【offsetParent】 offsetParent表示获取距离【当前元素】的最靠近的、并且CSS的position属性不等于static的父元素。 若找不到返回body 【offsetTop、offsetLeft】 offsetTop:当前HTML元素左上角相对于offsetParent的垂直位移。 offsetLeft:当前HTML元素左上角相对于offsetParent的水平位移。(2) 获取元素对象的方法 大致分为四种: querySelector方法 querySelectorAll方法 getElementsByTagName方法 getElementsByClassName方法 【注意:querySelector系列方法与getElementsBy系列方法对比有什么不同?】 (i)两者的W3C标准不同 querySelector系列属于W3C中的Selectors API规范 getElementsBy系列则属于 W3C的DOM 规范。 (ii)两者浏览器的兼容不同 querySelector系列基本能被所有浏览器支持。 getElementsBy系列则通常只有在考虑兼容性的时候才被提起(尽管两者功能近似) (iii)接受参数不同 querySelector系列接收的参数是一个css选择器名。 getElementsBy系列接收的参数只能是单一的className、tagName 和 name。 var c1 = document.querySelectorAll(‘.k1 .u‘); var c2 = document.getElementsByClassName(‘p‘); var c3 = document.getElementsByClassName(‘b2‘)[0].getElementsByClassName(‘d‘); 需要注意的是,querySelector系列所接收的参数是必须严格符合css选择器规范的。所以下面这种写法将会出错。 var e1 = document.getElementsByClassName(‘1a2b3c‘); var e2 = document.querySelectorAll(‘.1a2b3c‘); console.log(e1 && e1[0].className); console.log(e2 && e2[0].className); (iv)返回值不同 querySelectorAll()返回的是一个静态节点列表(Static NodeList) getElementsBy系列的返回的是一个动态节点列表(Live NodeList)。 //查看下面两个经典案例 //案例1 var ul = document.querySelectorAll(‘ul‘)[0], var list = ul.querySelectorAll("li"); for(var i = 0; i < list.length ; i++){ ul.appendChild(document.createElement("li")); } //案例2 var ul = document.getElementsByTagName(‘ul‘)[0], var list = ul.getElementsByTagName("li"); for(var i = 0; i < list.length ; i++){ ul.appendChild(document.createElement("li")); } 结论是: 案例2中的list是一个动态的NodeList,每一次调用list都会重新对文档进行查询,导致无限循环的问题。 案例1中的list是一个静态的Node List,是一个li集合的快照,对文档的任何操作都不会对其产生影响
时间: 2024-10-30 16:36:31