DOM基础

什么是 DOM

  • DOM( Document Object Model,文档对象模型)是W3C制订的一套技术规范,用来描述 Javascript脚本如何与HTML进行交互的Web标准
  • 加载 HTML 页面时, Web浏览器生成一个树型结构,用来表示页面内部结构。DOM 将这种树型结构理解为由节点组成的DOM树
  • DOM规定了一系列标准接口,允许开发人员通过标准方式访问文档结构、操作网页内容、控制样式和行为等
  • 在DOM中,接口可以理解为就是函数(函数 方法 API 接口 本质上都是一个函数)

DOM版本

  • 在W3C推出DOM标准之前,市场上已经流行了不同版本的DOM规范,主要包括IE和 Netscape两个浏览器厂商各自制订的私有规范,这些规范定义了一套文档结构操作的基本方法。虽然这些规范存在差异,但是思路和用法基本相同,如文档结构对象、事件处理方式、脚本化样式等。习惯上,我们把这些规范称为DOM0级,虽然这些规范没有统一并实现标准化,但是得到所有浏览器的支持并被广泛应用

  • 1998年W3C对DOM进行标准化,并先后推出了3个不同的版本,每个版本都是在上一个版本的基础上进行完善和扩展。但是在某些情况下,不同版本之间可能会存在不兼容的规定

    1. DOM1级:1998年10月,W3C推出DOM1.0版本规范,作为推荐标准进行正式发布,主要包括两个子规范

      • DOM Core(核心部分):把XML文档设计为树形节点结构,并为这种结构的运行机制制订了套规范化标准,同时定义了创建、编辑、操纵这些文档结构的基本属性和方法
      • DOM HTML:针对HTML文档、标签集合,以及与个别HTML标签相关的元素定义了对象属性和方法
    2. DOM2级:2000年11月,W3C正式发布了更新后的DOM核心部分,并在这次发布中添加了一些新规范,于是人们就把这次发布的DOM称为2级规范,2003年1月,W3C又正式发布了对 DOM HTML子规范的修订,添加了针对HTML4.01和 XHTML1.0版本文档中很多对象、属性和方法.W3C把新修订的DOM规范统一称为DOM2.0推荐版本,该版本主要包括6个推荐子规范

      • DOM2core:继承于 DOM Core子规范,规定了DOM文档结构模型,添加了更多的特性,如针对命名空间的方法等
      • DOM2HTML:继承于 DOM HTML,规定了针对HTML的DOM文档结构模型,并添加了一些属性
      • DOM2 Events:规定了与鼠标相关的事件(包括目标、捕获、冒泡和取消)的控制机制,但不含与键盘相关事件的处理部分
      • DOM2Style(或DOM2Css):提供了访问和操纵所有与Css相关的样式及规则的能力
      • DOM2 Traversal和DOM2 Range:DoM2 Traversal规范允许开发人员通过迭代方式访问DOM
      • DOM2vews:提供了访问和更新文档表现(视图)的能力。
    3. DoM3级:2004年4月,W3C发布了DOM3版本,DOMB3版本主要包括以下3个推荐子规范

      • DOM3Core:继承于DOM2Core,并添加了更多的新方法和属性,同时修改了已有的一些方法
      • DOM3 Load and Save:提供将XML文档的内容加载到DOM文档中,以及将DOM文档序列化为XML文档的能力
      • DOM3 Validation:提供了确保动态生成的文档的有效性的能力,即如何符合文档类型声明

document对象

  • Document 对象是是window对象的一个属性,因此可以将document对象作为一个全局对象来访问。当浏览器载入 html文档, 它就会成为 Document 对象。

  • 打开控制台输入 document,然后我们就看到了一个document对象,既然是对象,输入 typeof document, 控制打印了 "object"

console.log(document);
console.log(typeof document);
//查看document对象的方法和属性
for(var i in document){
    console.log(i)
}

节点

什么是节点

  • 在网页中所有对象和内容都被称为节点。
  • 如文档、元素、文本、属性、注释等。
  • 节点(Node)是DOM最基本的单元,并派生出不同类型的节点,它们共同构成了文档的树形结构模型。

节点种类(常用)

  • document 文档节点
  • documentFragment 文档片段节点
  • Element 元素节点
  • attr 属性节点
  • text 文本节点
  • comment 注释节点

节点关系

DOM把文档视为一棵树形结构,也称为节点树。节点之间的关系包括:上下父子关系,相邻兄弟关系

相邻兄弟关系

  • 在节点树中,最顶端节点为根节点。
  • 除了根节点之外,每个节点都有一个父节点
  • 节点可以包含任何数量的子节点
  • 叶子是没有子节点的节点
  • 同级节点是拥有相同父节点的节点

节点类型名称和值

  • childNodes:获取某个元素中的所有的子节点,使用中括号语法或者item()方法可以获取对应的节点
  • nodeType:获取节点的类型
  • nodeName:节点名称
  • nodeValue:节点的值
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>节点</title>
</head>
<body>
<div id="box">
    <p>我是p标签</p>
    <span>hello</span>
    <i>i标签</i>
    <div>我是div</div>
    <!--<h3>h333</h3>-->
    <em>em标签</em>
</div>
<script>
    var oBox = document.getElementById("box");
    var nodes = oBox.childNodes;
    console.log(nodes);//节点的集合 NodeList类型
    console.log(nodes[3]);//直接可以获取到节点
    console.log(nodes.item(5));//直接可以获取到节点

    //document的节点类型 名称 和值
    console.log(document.nodeType);//9
    console.log(document.nodeName);//#document
    console.log(document.nodeValue);//null


    //元素节点的类型 名称和 值
    console.log(nodes[1].nodeType);//1
    console.log(nodes[1].nodeName);//节点名称就是标签名 大写
    console.log(nodes[1].nodeValue);//null

    //文本节点的类型 名称和 值
    console.log(nodes[0].nodeType);//3
    console.log(nodes[0].nodeName);//#text
    console.log(nodes[0].nodeValue);//当前的文本内容

    //注释节点的类型 名称和 值
    console.log(nodes[9].nodeType);//8
    console.log(nodes[9].nodeName);//#comment
    console.log(nodes[9].nodeValue);//当前被注释的内容

    var myAttr = document.createAttribute("my");
    myAttr.value = "yes";
    console.log(myAttr);
    console.log(myAttr.nodeType);//2
    console.log(myAttr.nodeName);//my  属性节点是标准的键值对形式   属性名就是节点名称
    console.log(myAttr.nodeValue);//yes  属性值就是节点的值

</script>
</body>
</html>

访问节点

获取元素基础方法

  • 通过标签名获取(完美兼容)

    • 可以使用内置对象document上的getElementsByTagName方法来获取页面上的某一种标签

    • 获取的一定是一个选择集(伪数组),不是数组,但是可以用下标的方式操作选择集里面的标签元素。

    • 这个集合拥有length属性

    • 通过标签名获取的对象 要么在使用的时候添加下标,要么在获取的时候添加下标,因为使用的时候,只能拿一个元素去使用

    var oLis = document.getElemerntsByTagName("li");
    console.log(oLis);
    oLis[0].style.backgroundColor = "green";
    oLis[1].style.backgroundColor = "green";
    oLis[2].style.backgroundColor = "green";
    oLis[3].style.backgroundColor = "green";
    
    //或者
    
    var oLis1 = document.getElementsByTagName("li")[0];
    oLis1.style.backgroundColor = "pink";
  • 通过id获取标签(完美兼容)

    • 可以使用内置对象document上的getElementsByID方法来获取页面上的某一种标签

    • id是唯一的 所以通过id获取的标签也是唯一的

    • id如果没有获取,那么仍然可以拿着id名来使用,因他是唯一的。但是不建议这样书写

    var oBox = document.getElementById("box");
    console.log(oBox);//得到整个元素
    oBox.style.backgroundColor = "red";
  • 通过类名来获取元素(不兼容IE678)

    • 可以使用内置对象document上的getElementsByClassName方法来获取页面上的某一种标签

    • 使用和getElementsByTagName使用方法一致

    // IE8不认识此方法:对象不支持“getElementsByClassName”属性或方法
    var oLi1 = document.getElementsByClassName("li1");
    oLi1[0].style.backgroundColor = "green";
  • 通过Name属性获取元素(几乎不使用)

    • 可以使用内置对象document上的getElementsByName方法来获取页面上的某一种标签
    • 使用和getElementsByTagName使用方法一致
    • 兼容性:针对ie:通过Name获取 只能获取到表单元素 不支持其他元素通过name属性获取
    var oLi = document.getElementsByName("oli");
    oLi[0].style.height = "300px";

selectors API

  • selectors API就是由W3C发布的一个事实标准,为浏览器实现元素的css选择器
  • 两个核心方法 querySelectorquerySelectorAll(IE8+)
  • querySelectorquerySelectorAll方法参数必须是符合css选择器语法规则的字符串。其中querySelector返回的是一个元素,querySelectorAll返回的是一个集合,一个NodeList对象(可以使用数组的forEach方法)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>新的选择器</title>
</head>
<body>
<ul class="outer">
    <li>11</li>
    <li>22</li>
    <li>33</li>
</ul>
<script>
    var oLis = document.querySelectorAll(".outer>li");
    console.log(oLis);//[li,li,li]
    console.log(oLis[0]);

    var oLi = document.querySelector(".outer>li");
    console.log(oLi);

    var oLi2 = document.querySelector(".outer>li:nth-child(2)");
    console.log(oLi2);
</script>
</body>
</html>

selectors API和传统方法的比较

  • getElementsByXXXXX获取的是一个动态的集合
  • queryselectorAll获取的是静态的集合
  • 动态:选出来的元素会随着文档的改变而改变,静态:只要取出来,就和页面有没有任何关系
var oUl = document.getElementsByTagName("ul")[0];
var oLis = oUl.getElementsByTagName("li");
console.log(oLis.length);

//直接陷入死循环  因为getElementsByTagName获取的元素是动态的,所以我们遍历的长度是获取元素的长度
// 每次插入一个 长度就会加1  所有永远运行不完
for (var i = 0; i < oLis.length; i++) {
    oUl.appendChild(document.createElement("li"))
}
console.log(oLis.length);


// querySelectorAll获取的元素就是静态的
var oLis = document.querySelectorAll("ul li");
console.log(oLis.length);

for (var i = 0; i < oLis.length; i++) {
    document.querySelector("ul").appendChild(document.createElement("li"))
}
console.log(oLis.length);

节点关系中访问节点方法

  • parentNode 获取元素的父元素节点 (全兼容)

  • children:获取元素的所有子元素节点(IE678 可以获取到注释节点 所有在IE678这样获取的时候注意不要写注释)

  • 获取元素的上一个兄弟节点

    • previousSibling 获取元素的上一个兄弟节点(在ie678中获取的是上一个兄弟元素节点 在非ie678中获取的是上一个节点(可能是文本节点))

    • previousElementSibling 在ie678中不支持 在非ie678中获取的是上一个元素节点(兼容性有顺序要求 previousSibling不能写前,因为previousSibling所有浏览器识别 但是意义不一样)

  • 获取下一个兄弟节点

    • nextSibling 获取下一个兄弟节点

    • nextElementSibling 获取下一个兄弟节点

  • 获取第一个子元素节点

    • firstChild:获取元素的第一个子元素节点

    • firstElementChild:获取元素的第一个子元素节点

  • 获取最后一个子元素节点

    • lastChild:获取元素的最后一个子元素节点

    • lastElementChild:获取元素的最后一个子元素节点

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>访问元素节点</title>
</head>
<body>
<ul id="box">
    <li>11</li>
    <li>22</li>
    <li>33</li>
    <li>44</li>
<!--    <li>注释</li>-->
    <li>55</li>
</ul>
<div class="con">
    <div>1</div>
    <span>span</span>
    <p>p</p>
    <h2>h2</h2>
</div>
<script>

    //通过get选择器的方式选择
    var oBox = document.getElementById("box");
    var oLis = oBox.getElementsByTagName("li");
    console.log(oLis);

    /*var oCon = document.getElementsByClassName("con")[0];
    console.log(oCon.children);//  类数组集合 [div, span, p, h2]
    console.log(oBox.children);// 类数组集合  [li, li, li, li, li]*/

    //获取元素的父节点
    console.log(oLis[3]);
    console.log(oLis[3].parentNode);
    console.log(oLis[3].parentNode.parentNode);
    console.log(oLis[3].parentNode.parentNode.parentNode);
    console.log(oLis[3].parentNode.parentNode.parentNode.parentNode);
    console.log(oLis[3].parentNode.parentNode.parentNode.parentNode.parentNode);//null
    // console.log(oLis[3].parentNode.parentNode.parentNode.parentNode.parentNode.parentNode);//报错


    //获取上一个兄弟节点
    console.log(oLis[3].previousSibling);
    console.log(oLis[3].previousElementSibling);
    // 兼容性写法
    if (oLis[3].previousElementSibling){
        console.log(oLis[3].previousElementSibling);
    }else{
        console.log(oLis[3].previousSibling);
    }

    // 获取下一个兄弟
    console.log(oLis[3].nextElementSibling);

    //获取第一个子节点
    console.log(oBox.firstElementChild);

    //获取最后一个子节点
    console.log(oBox.lastElementChild);
</script>
</body>
</html>

其他获取节点方法

  • 获取body元素

    document.body==document.getElementsByTagName('body')[0]

  • 获取head元素

    document.head==document.getElementsByTagName('head')[0]

  • 获取html元素

    document.documentElement==document.getElementsByTagName('html')[0]

posted @ 2023-01-12 22:34  z_bky  阅读(51)  评论(0)    收藏  举报