Web APIs——DOM

什么是DOM?

文档对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口

W3C已经定义了一系列的DOM接口,通过这些DOM接口可以改变网页的内容、结构和样式。

① 对于JavaScript,为了能够使JavaScript操作HTML,JavaScript就有了一套自己的DOM编程接口。

② 对于HTML,DOM使得HTML形成一棵DOM树,包括文档、元素、节点。我们获取过来的DOM元素是一个对象(object),所以称为文档对象模型

  • 文档:一个页面就是一个文档,DOM中使用document表示
  • 元素:页面中的所有标签都是元素,DOM中使用element表示
  • 节点:网页中的所有内容都是节点(标签、属性、文本、注释等),DOM中使用node表示

DOM把以上内容都看作是对象。

关于DOM操作,主要是针对于元素的操作。主要有创建、增、删、改、查、复制、属性操作、事件操作

1. 创建

  • document.write()
  • element.innerHTML
  • document.createElement()

三种动态创建元素的区别:

① document.write是直接将内容写入页面的内容流,但是页面文档流加载完毕,再调用这句话会导致页面全部重绘。

② innerHTML是将内容写入某个DOM节点,不会导致页面全部重绘。

③ innerHTML创建多个元素效率更高(不要拼接字符串,而是采取数组形式拼接好后再赋值给innerHTML),结构稍微复杂

④ createElement()创建多个元素效率稍微低一点点,但是结构更清晰。

总结:不同浏览器下,innerHTML(以数组形式拼接的方式)效率要比createElement高。

2. 增

① node.appendChild(child); 该方法将一个节点添加到指定父节点的子节点列表末尾。类似于CSS里面的after伪元素。

② node.insertBefore(child, 指定元素); 该方法将一个节点添加到父节点的指定子节点前面。类似于CSS里面的before伪元素。

3. 删

node.removeChild(child); 该方法从DOM中删除一个子节点,返回删除的节点。

4. 改

JavaScript的DOM操作可以改变网页内容、结构和样式,我们可以利用DOM操作元素来改变元素里面的内容、属性表单的值等。

① 修改元素属性:src、href、id、alt、title等

<script>
    // 修改元素属性
    // 1. 获取元素
    var ldh = document.getElementById('ldh');
    var zxy = document.getElementById('zxy');
    var img = document.querySelector('img');
    // 2. 注册事件  处理程序
    zxy.onclick = function() {
        img.src = 'images/zxy.jpg';
        img.title = '张学友';
    }
    ldh.onclick = function() {
        img.src = 'images/ldh.jpg';
        img.title = '刘德华';
    }
</script>

② 修改普通元素内容:

  • element.innerText:从起始位置到终止位置的内容,但它去除html标签,同时空格和换行也会去掉。
  • element.innerHTML:起始位置到终止位置的全部内容,包括html标签,同时保留空格和换行。

innerText与innerHTML的区别:innerText不识别html标签,非标准;innerHTML识别html标签,W3C标准,保留空格和换行。这两个属性是可读写的,可以获取元素里面的内容。

③ 修改表单元素:type、value、checked、selected、disabled等

④ 修改元素样式:

  • element.style  行内样式操作。该方式获得修改元素样式,如果样式比较少或者功能简单的情况下使用。
  • element.className  类名样式操作。 当样式比较多或功能复杂的时候,可以通过修改className来更改元素的样式。

例如:element.className = 'new';  如果想要保留原先的类名,可以这样改:element.className = 'old new';(中间用空格隔开)

注意:

  • JS里面的样式采取驼峰命名法,比如 fontSize、backgroundColor
  • JS修改style样式操作,产生的是行内样式,css权重比较高

排他思想:如果有同一组元素,我们想要某一个元素实现某种样式,需要用到循环的排他思想算法:

  • 所有元素全部清除样式(干掉其他人)
  • 给当前元素设置样式(留下我自己)
  • 注意顺序不能颠倒,首先干掉其他人,再设置自己

5. 查

获取页面中查询DOM的元素可以使用以下几种方式:

① DOM提供的API方法(这些用法太古老,不太推荐):

  • 根据ID获取:document.getElementById(id);
  • 根据标签名获取:

    document.getElementsByTagName('tag name');

    element.getElementsByTagName('tag name');  可以得到这个元素里面的某些标签

② HTML5提供的新方法提倡):

  • 根据类名获得某些元素集合:document.getElementsByClassName('class name');
  • 指定选择器的第一个元素对象,注意,里面的选择器需要加符号:'.box'  '#an' 等:document.querySelector('.box');
  • 指定选择器的所有元素对象集合:document.querySelectorAll('.box');

③ 利用节点操作获取元素提倡):利用父子兄层级关系获取元素逻辑性强,但是兼容性差。在DOM树中,节点使用node来表示。

HTML的DOM树中的所有节点均可通过JavaScript进行访问,所有HTML元素(节点)均可被修改,也可以创建或删除。

一般地,节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个基本属性。

  • 元素节点  nodeType 为1
  • 属性节点  nodeType 为2
  • 文本节点  nodeType 为3(文本节点包含文字、空格、换行等)

我们在实际开发中,节点操作主要操作的是元素节点。

利用DOM树可以把节点划分为不同的层级关系,常见的是父子兄层级关系。

  • 父级节点:node.parentNode     

    parentNode属性可返回某节点的父节点,注意是最近的一个父节点。如果指定的节点没有父节点则返回null。

  • 子节点:

  1) parentNode.childNodes(标准)

    parentNode.childNodes返回包含指定节点的子节点的集合,该集合为即使更新的集合。

    注意:返回值里面包含了所有的子节点,包括元素节点,文本节点等。

    如果只想要获得里面的元素节点,则需要专门处理。所以一般不提倡使用childNodes。

var ul = document.querySelector('ul');
for (var i = 0; i < ul.childNodes.length; i++) {
        if (ul.childNodes[i].nodeType == 1) {
            // ul.childNodes[i]是元素节点
            console.log(ul.childNodes[i]);
        }
}

  2) parentNode.children(非标准)

    parentNode.children是一个只读属性,返回所有的子元素节点。它只返回子元素节点,其余节点不返回(重点)

    虽然children是一个非标准,但是得到了各个浏览器的支持,因此我们可以放心使用。

  3) parentNode.firstChild

    firstChild返回第一个子节点,找不到则返回null。同样,也是包含所有的节点。

  4) parentNode.lastChild

    lastChild返回最后一个子节点,找不到则返回null。同样,也是包含所有的节点。

  5) parentNode.firstElementChild

    firstElementChild返回第一个子元素节点,找不到则返回null。该方法有兼容性问题,IE9以上才支持

  6) parentNode.lastElementChild

    lastElementChild返回最后一个子元素节点,找不到则返回null。该方法有兼容性问题,IE9以上才支持

实际开发中,firstChild和lastChild包含其他节点,操作不方便,而firstElementChild和lastElementChild又有兼容性的问题,那么我们如何获取第一个子元素节点和最后一个子元素节点呢?

解决方案:

如果想要得到第一个子元素节点,可以使用parentNode.children[0]

如果想要得到最后一个子元素节点,可以使用parentNode.children[length-1](length是子元素的个数)

  • 兄弟节点:

  1) node.nextSibling

    nextSibling返回当前元素的下一个兄弟节点,找不到则返回null。同样,也是包含所有的节点。

  2) node.previousSibling

    previousSibling返回当前元素上一个兄弟节点,找不到则返回null。同样,也包含所有的节点。

  3) node.nextElementSibling

    nextElementSibling返回当前元素下一个兄弟元素节点,找不到则返回null。该方法有兼容性问题,IE9以上才支持。

  4) node.previousElementSibling

    previousElementSibling返回当前元素上一个兄弟节点,找不到则返回null。该方法有兼容性问题,IE9以上才支持。

如何解决兼容性问题?自己封装一个兼容性的函数:

function getNextElementSibling(element) {
    var el = element;
    while (el = el.nextSibling) {
        if (el.nodeType === 1) {
            return el;
        }
    }
    return null;
}

④ 特殊元素的获取:

  • 获取body元素:document.body;
  • 获取html元素:document.documentElement;

这几种方式都可以获取元素节点,但是节点操作会更简单。网页中的所有内容都是节点(标签、属性、文本、注释等)

6. 复制

复制节点(克隆节点/拷贝节点):node.cloneNode();  该方法返回调用该方法的节点的一个副本。

注意:

① 如果括号参数为空或者为false,则是浅拷贝,即只克隆复制节点本身,不克隆里面的子节点。

② 如果括号参数为true,则是深度拷贝,会赋值节点本身以及里面所有的子节点。

7. 属性操作

① 获取属性值:

  • element.属性,获取内置属性值(元素本身自带的属性)
  • element.getAttribute('属性');  主要获得自定义的属性(标准),程序员自定义的属性

② 设置属性值:

  • element.属性 = '值';  设置内置属性值
  • element.setAttribute('属性', '值');  主要设置自定义的属性(标准)

③移除属性值:element.removeAttribute('属性');

H5自定义属性:

自定义属性的目的是为了保存并使用数据。有些数据可以保存到页面中而不用保存到数据库中。

自定义属性是通过getAttribute('属性')获取。

但是有些自定义属性很容易引起歧义,不容易判断是元素的内置属性还是自定义属性。

H5增加了自定义属性:

① 设置H5自定义属性:H5规定自定义属性以data-开头作为属性名并且赋值。

比如:<div data-index="1"></div>

或者使用JS设置:element.setAttribute('data-index', '2');

② 获取H5自定义属性:

  • 兼容性获取:element.getAttribute('data-index');
  • H5新增 element.dataset.index 或者 element.dataset[ 'index' ]   IE11才开始支持

8. 事件操作

JavaScript使我们有能力创建动态页面,而事件是可以被JavaScript侦测到的行为。

简单理解:触发---响应机制

网页中的每个元素都可以产生某些可以触发JavaScript的事件,例如,我们可以在用户点击某按钮时产生一个事件,然后去执行某些操作。

事件三要素:事件源、事件类型、事件处理程序。

执行事件的步骤:①获取事件源  ②注册事件(也称绑定事件,采取 事件源.事件类型 = 事件处理程序)  ③添加事件处理程序(采取函数赋值形式)

常见的鼠标事件:

猜你喜欢

转载自www.cnblogs.com/zcy9838/p/12920623.html