对于DOM来说,知识点其实并不多,要理解DOM并不难,难的是会用。可能有的人看见DOM获取元素要这么长一串单词就觉得生无可恋了。不过说实在的,如果你能理解他的意思跟用法。而且稍微再有点英语基础的话,DOM其实还是很简单的。而对于觉得自己英语不好的人来说,不用想了,多打代码是你唯一的出路,程序员练得就是手感。

  上一篇文章中,我主要讲了下一些事件,还有一些节点的操作。不过对于节点的层次只是大概的提了一下,这里就对节点的层次进行一个祥述。

  在我们的DOM模型中,是由节点组成的,节点可以是标签,属性和文本。对于我们来说,一眼就能看出一个节点是什么节点。可是,在js中,要区分节点的话就要用到它的方法了

节点

nodeType

nodeName

nodeValue

标签

1

对应的标签名

null

属性

2

对应的属性名

对应的属性值

文本

3

#text

对应的文本内容

  nodeType方法是用来获取节点类型的。对应上表,标签的节点类型为1。属性的节点类型为2。而文本的节点类型则为3。通过nodeType方法我们可以知道一个节点是什么类型的。止于后面两种方法,则分别是用来获取节点的名字和节点的值的。他们所对应的值我在表格中都有描述,所以这边就不多提了。那具体要怎么来获取节点的类型呢?

<!DOCTYPE html>

<html>

<head lang="en">

    <meta charset="UTF-8">

    <title></title>

</head>

<body>

<div class="box">

    <ul id="list">

        <li>111111</li>

        <li>222222</li>

        <li id="li3">333333</li>

        <li>444444</li>

    </ul>

</div>

<script>

    var li3=document.getElementById("li3");

    console.log(li3.nodeType);

    console.log(li3.nodeName);

    console.log(li3.nodeValue);

</script>

</body>

</html>

  以上述代码为例,他输出的值分别是1,LI,null。

  在DOM中,还有一些方法可以获得自己的父辈节点和子代节点。可能有人好奇为什么要这么做,不是可以直接添加一个id名或者直接获取标签名不就好了嘛,为什么还要这么麻烦有这么多的方法让我们来记。写过静态页面的人肯定就不会这么说了,因为,在一个页面中标签实在是太多了,如果每用一个标签就要取一个名字的话,很容易造成重名,要不就是名字命名的很长。这些都会带来很多的不变,所以,就有了DOM中的方法来获取这些跟当前节点有的父辈,子代,或者兄弟节点。

  首先来讲讲获取父辈节点,上述代码中,我们如果要获取id为li3这个节点的父辈节点的话,我们就可以使用

var li3=document.getElementById("li3");

console.log(li3.parentNode);

  这样,我们就可以获得id为li3的这个节点的父辈节点了,这个方法在任何浏览器中都适用,而且没有兼容性问题。

  然后就是获取子代节点了,同样的以上述代码为例。比如我们要获取ul这个标签的子代节点,我们就有两种方式了。一种是

var list=document.getElementById("list");

var lis=li.childNode;

for(var i=0;i<lis.length;i++){

  console.log(lis[i]);

}

  这种方法在不同的浏览器就会有不同的效果了,在谷歌,火狐都中,不但可以获得标签节点,还可以获得文本节点,这里所说的文本节点,就是每个li标签之间的换行而产生的文本节点。而在IE8及之前的浏览器中则会忽略空白文本,也就是只会获取到标签节点。所以还有另一种获取的方式:

var list=document.getElementById("list");

var lis=li.children;

for(var i=0;i<lis.length;i++){

console.log(lis[i]);

}

  这种方法并不是DOM中的方法,不过所有的浏览器都支持这种方法,并且他会获得所有的标签子节点。因为他的兼容性好,并且简单。所以在获取子节点的时候更提倡的使用到这个方法。

  如果说获取子节点这种方法还算运气好还有一个替代的方法的话,接下来要说的几个方法兼容性就不那么尽如人意了。之前说了,节点之间除了父子关系外,还有兄弟关系。这里说的兄弟关系,也就是同级的节点之间的关系。所以,兄弟节点也分前一个节点和后一个节点。就拿之前那段代码来说id为li3的节点的前一个兄弟节点为<li>222222</li>,它的后一个兄弟节点为<li>444444</li>。那要如何获取他们呢?先说说获取前一个兄弟节点。我们可以用以下方法。

var li3 = document.getElementById("li3");

console.log(li3.previousSibling);

  因为节点有三部分组成 ,标签 ,属性,文本,而previousSibling所获取的不仅仅是标签节点,还能够获取文本节点,这种方法所有浏览器都是支持的,只是IE8及之前的浏览器会忽略空白文本节点。

  因为获取到的空白节点没有用,所以就有另一种直接获取前一个标签兄弟节点。

var li3 = document.getElementById("li3");

console.log(li3.previousElementSibling);

  根据语义,就可以知道是前一个元素节点。他在谷歌跟火狐中都是能直接获取到前一个元素节点,而ie8及之前的版本却不支持这种方法。所以,为了在各个版本中都能兼容,我们就要封装一个函数来使得各个浏览器都能兼容。

    function getPreviousSibling(obj){

        if(obj.previousElementSibling){

            return obj.previousElementSibling;

        }else {

            var node = obj.previousSibling;

            while(node&&node.nodeType!=1){

                node = node.previousSibling;

            }

            return node;  

        }

    }

  这里,我们定义了一个getPreviousSibling的函数用来获取前一个标签兄弟节点,这个函数有一个参数用来传入要获取哪个标签的前一个标签节点。在函数中,我们就用到了能力检测,也就是这里的if else判断。如果obj.previousElementSibling这个方法存在,那么返回obj.previousElementSibling。如果这个方法不存在,那么执行else里的代码。在else中,我们定义了一个变量node等于obj.previousSibling。这个方法是所有浏览器都兼容的。然后进入while循环,循环的成立的条件时node,也就是obj.previousSibling存在,并且它的nodeType不等于1,这句代码的意思就是如果这个要判断的节点的前一个兄弟节点存在并且不是标签节点的时候,那么进入到循环中来,让node等于obj.previousSibling也就是再之前的兄弟节点。一直到没有前一个兄弟节点了,或者前一个兄弟节点的节点类型不为1的时候,跳出循环,此时,node的值就是要操作的节点的前一个标签节点。把这个值返回。所以这段代码就完成了在任何浏览器中都能获取到要操作节点的前一个标签节点了。

  我们调用一下他,并在控制台打印它的值。

console.log(getPreviousSibling(li3));

  在google浏览器中会显示<li>222222</li>,而在ie8中则是显示 [object HTMLLIElement] ,这只是不同浏览器显示的问题,但这个结果说明我们封装的函数是有用的,能在低版本浏览器中起作用的。如果看明白了获取前一个标签兄弟节点的原理的话,之后的就不会很简单了。获取后一个标签兄弟节点跟这个是一模一样的。唯一不同的就是他获取后一个兄弟节点是

var li3 = document.getElementById("li3");

console.log(li3.nextSibling);

  而获取后一个标签兄弟节点是:

var li3 = document.getElementById("li3");

console.log(li3.nextElementSibling);

  他们有着相同的兼容性问题,所以我们也可以按照上面的方法封装一个函数来使得他兼容各个浏览器。

    function getNextSibling(obj){

        if(obj.nextElementSibling){

            return  obj.nextElementSibling;

        }else {

            var node = obj.nextSibling;

            while(node&&node.nodeType!=1){

                node = node.nextSibling;

            }

            return node;

        }

    }  

console.log(getNextSibling(li3));

  我们在控制台中打印一下它。在google浏览器中会显示<li>444444</li>,而在ie8中则是显示 [object HTMLLIElement] 。

  与这四个方法相似的还有四个方法。分别是获取第一个子元素和最后一个子元素。获取第一个子元素也有两种方法。

var ul=document.getElementById("list");

console.log(ul.firstChild);

var ul=document.getElementById("list");

console.log(ul.firstElementChild);

  前一中方法是获取第一个子元素,包括文本节点,后一种方法则是获取第一个标签子元素。跟之前一样,他们也是有一样的简永兴问题。所以要封装到一段函数中。

 function getFirstChild(obj){

        if(obj.firstElementChild){

            return obj.firstElementChild;

        }else {

            var node = obj.firstChild;

            while(node&&node.nodeType!=1){

                node = node.nextSibling;

            }

            return node;

        }

    }

  与之相对应,还有一个就是获取最后一个子元素。他也有两种方法分别能获取最后一个子元素和最后一个标签子元素。分别是

var ul=document.getElementById("list");

console.log(ul.lastChild);

var ul=document.getElementById("list");

console.log(ul.lastElementChild);

给他们封装一个方法来兼容各个版本的浏览器。

  function getLastChild(obj){   

        if(obj.lastElementChild){

            return obj.lastElementChild;

        }else {

            var node = obj.lastChild;

            while(node&&node.nodeType!=1){

                node = node.previousSibling;

            }

            return node;

        }

    }

  好了,总算把这些绕来绕去的方法说完了,看着好像很烦,不过总结一下,找到规律之后发现还是很好记的。从获取兄弟节点开始,我一共提了八种方法,他们实际实现的功能其实只有四种,分别是获取下一个兄弟节点,获取上一个兄弟节点和获取第一个子元素,获取最后一个子元素每个功能有两种方法,这两种方法一种是会获取到文本节点的,但是所有浏览器都兼容,只是对于ie8及以下版本来说他是忽略文本节点的,所以获取到的就是元素节点。而另一种方法则是能直接获取到元素节点的,只是这个方法ie8及以下的版本都不兼容。所以就有了封装兼容性函数。这么一理,整个思路就清晰多了,再回头看的时候就不会感觉那么绕了。

  好了,接下来就提一下另一个知识点,就是元素的克隆和追加。

<!DOCTYPE html>

<html>

<head lang="en">

    <meta charset="UTF-8">

    <title></title>

</head>

<body>

<ul id="list">

    <li>111111</li>

    <li>222222</li>

    <li id="li3">333333</li>

    <li>444444</li>

</ul>

<script>

    var ul = document.getElementById("list");

    var li = document.getElementById("li3");

    console.log(li.cloneNode(false));

    console.log(li.cloneNode(true));

    console.log(ul.cloneNode(false));

    console.log(ul.cloneNode(true));

</script>

</body>

</html>

  在上述代码中,我们通过id的方式获取到了ul标签和id名为li3的li标签。我们克隆一个li标签并且在空中台中输出它,在这里,克隆节点我们用的是li.cloneNode();括号内的参数是用来选择克隆深度的,这里填的是一个boolean值,如果这个值为true的时候,那么就是深度克隆,他会克隆这个标签中所有的内容包括他的文本内容和子代标签。而值为false的时候,他克隆的则仅仅是一个标签,而不会有内容。

  上述代码在google中输出的结果为

  我们可以看到前三行为前面三行代码输出的值,第四行及之后的值则是第四行输出的内容。

前面我说了克隆和追加,既然我们克隆了这个节点,要怎么追加呢?比如我们如何把克隆的li加到原有的ul中呢?这时候,我们就要用到appendChild方法了。我们把克隆的li赋值给一个变量,然后把他克隆到ul中,具体代码如下

 var newLI= li.cloneNode(true);

  ul.appendChild(newLI);

  注意,appendChild放法是把克隆的节点放到了ul的最后面。所以,在页面中我们可以看到

  这样,我们就完成了元素的克隆和追加。

DOM基础(三)的更多相关文章

  1. HTML DOM基础知识

    HTML DOM基础知识 一.什么是DOM? 1.HTML DOM 定义了访问和操作HTML文档的标准方法. 2.HTML DOM 把 HTML 文档呈现为带有元素.属性和文本的树结构(节点树). 3 ...

  2. Javascript DOM基础(一)概念

    Dom基础概念: <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" ...

  3. js入门——Dom基础

    DOM=DocumentObject Model,文档对象模型. Dom有三个不同的部分. 1.核心DOM 也是最基础的文档结构的标准模型 2.XMLDOM 针对XML文档的标准模型 3.HTML D ...

  4. 第一百一十三节,JavaScript文档对象,DOM基础

    JavaScript文档对象,DOM基础 学习要点: 1.DOM介绍 2.查找元素 3.DOM节点 4.节点操作 DOM(Document Object Model)即文档对象模型,针对HTML和XM ...

  5. DOM基础(四)

    每次写DOM的时候,就觉得好像没什么好写,因为涉及到知识点的方面的确不多,对于DOM来说,更多的还是练习为主.在练习的时候,最好能结合着js基础语法的知识点来学习.这样,在学习DOM的时候就不会那么枯 ...

  6. BOM基础 计时器 定时器 DOM 基础

    -------------------------------------------滴水穿石,我心永恒. day48 CSSJS 1 ECMA script 2 BOM browser object ...

  7. 第五讲 DOM基础

    DOM基础: 什么是DOM:其实就是dovument,div获取.修改样式等等,但是不只是js的组成部分,而且还是一套规范,规定了这些浏览器怎么处理这些操作: 浏览器支持情况:IE(IE7-8,10% ...

  8. 深入浅出DOM基础——《DOM探索之基础详解篇》学习笔记

    来源于:https://github.com/jawil/blog/issues/9 之前通过深入学习DOM的相关知识,看了慕课网DOM探索之基础详解篇这个视频(在最近看第三遍的时候,准备记录一点东西 ...

  9. JavaScript DOM基础总结

    上个月在进行百度三面时候,面试官提问JavaScript DOM方法,我回答的有点少,前面太关注JavaScript 兼容性,框架方面,JavaScript 原生DOM基础没有记牢,心中有点遗憾.下来 ...

  10. JavaScript DOM 基础操作

    JavaScript DOM 基础操作 一.获取元素的六方式 document.getElementById('id名称') //根据id名称获取 document.getElementsByclas ...

随机推荐

  1. 让php Session 存入 redis 配置方法

    首先要做的就是安装redis 安装方法:http://redis.io/download Installation Download, extract and compile Redis with: ...

  2. Shell 基础

    1.结构        #!指定执行脚本的shell  #!/bin/sh        # 注释行        命令和控制结构    2.修改权限        chmod +x ...    3 ...

  3. STL内存管理

    1. 概述 STL Allocator是STL的内存管理器,也是最低调的部分之一,你可能使用了3年stl,但却不知其为何物. STL标准如下介绍Allocator the STL includes s ...

  4. JQuery hover toggle事件使用

    JQuery hover toggle事件使用: <%@ page language="java" import="java.util.*" pageEn ...

  5. Wireshark对常见视频应用的抓包分析的结果

    一.PC端直播: YY客户端直播用的udp(P2P)9158客户端直播用的rtp/rtcp 二.Web端直播: YY网页端直播用的tcp9158网页端直播用的tcp六间房网页端直播用的tcp17173 ...

  6. Spring MVC 返回NULL时客户端用$.getJSON的问题

    如果Spring MVC返回是NULL,那么客户端的$.getJSON就不会触发: 必须返回点什么东西: 如果返回的是一个字符串,客户端的$.getJSON也不会触发:把字符串 包装成List< ...

  7. Canvas arcTo绘制圆弧

    arcTo(x1,y1,x2,y2,r); 当前点x0,y0;圆弧与(x0,y0-x1,y1)相切,与(x1,y1-x2,y2)相切: <!DOCTYPE html> <html l ...

  8. 在Node.js中使用RabbitMQ系列二 任务队列

    在上一篇文章在Node.js中使用RabbitMQ系列一 Hello world我有使用一个任务队列,不过当时的场景是将消息发送给一个消费者,本篇文章我将讨论有多个消费者的场景. 其实,任务队列最核心 ...

  9. svn git协同管理

    项目开发过程中总有一些奇奇怪怪的需求出现. 我们的项目管理是使用SVN的,用SVN是历史原因,无法整个项目向Git切换.由于我需要管理SVN,做一些代码合并工作.每次合并都会遇到SVN代码需要对比查看 ...

  10. HDU2063(二分图最大匹配)

    过山车 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...