浏览器对象相关

节点Nodes 与 Element节点 的区别

官方解释

在 HTML DOM (文档对象模型)中,每个部分都是节点

  • 文档本身是文档节点
  • 所有 HTML 元素是元素节点
  • 所有 HTML 属性是属性节点
  • HTML 元素内的文本是文本节点 (包括回车符也是属于文本节点)
  • 注释是注释节点

Element 对象可以拥有类型为元素节点、文本节点、注释节点的子节点。

NodeList 对象表示节点列表,比如 HTML 元素的子节点集合。

元素也可以拥有属性。属性是属性节点。

总结:元素是元素节点,是节点中的一种,但元素节点中可以包含很多的节点。

自己总结

Dom 文档是层级节点的合集,每个节点都可以有自己的父级/子级节点,节点是有类型的,分为文档节点、注释节点、元素节点、属性节点、文本节点。

所以 Element(元素)是节点的一种。可以吧Node节点看做基类,element 继承基类,具有Node的属性方法,同事拓展了许多自身特有的属性方法。

高频属性方法

常用的 Document 的方法

方法 描述
createComment(data) 用指定的字符串创建新的Comment节点
createElement(tagName[, options]) 用指定的标记名创建新的Element节点
createTextNode(data) 用指定的文本创建新的TextNode节点
getElementId(id) 返回文档中具有指定id属性的Element节点
getElementByTagName(tagName) 返回文档中具有指定标记名的所有Element节点

示例

// 通过ID获取元素
var elem = document.getElementById('id');

// 通过标签名获取元素
var allParas = document.getElementsByTagName("p");

// 创建元素
let newDiv = document.createElement("div");

// 注释节点
var comment = docu.createComment('这是注释内容');
newDiv.appendChild(comment);

// 文本节点
let newContent = document.createTextNode("Hi there and greetings!");
// 添加文本节点 到这个新的 div 元素
newDiv.appendChild(newContent);
复制代码

Node常用的属性和方法

属性 描述
childNodes 以Node[]的形式存放当前节点的子节点,如果没有节点,则返回空数组
firstChild 以Node的形式返回当前节点的第一个节点,如果没有节点则返回NULL
lastChild 以Node的形式返回当前节点的最后一个节点,如果没有节点则返回NULL
parentNode 以Node的形式返回当前节点的父节点,如果没有节点则返回NULL
nodeName 节点的名字,Element节点则代表Element标记的名称
nodeType 代表节点的类型
方法 描述
appendChild(aChild) 通过把一个节点增加到当前节点的childNode[]组,给文档树增加节点
cloneNode(deep) 复制当前节点,或者复制当前节点以及它的所有子孙节点
hasChildNodes() 如果当前节点拥有子结点,则返回true
insertBefore(newNode, referenceNode) 给文档树插入一个节点,位置在当前节点的指定位置之前,如果该节点已经存在,则删除之,然后再将节点插入到它的位置。
removeChild(child) 从文档树中删除并返回指定的子结点
replaceChild(newChild, oldChild) 从文档树中删除并返回指定的子结点,用另一个节点替代它。

示例

// 创建一个新的段落元素 <p>,然后添加到 <body> 的最尾部
var p = document.createElement("p");
document.body.appendChild(p);

var dupNode = node.cloneNode(deep);
// node
// 将要被克隆的节点

// dupNode
// 克隆生成的副本节点

// deep 可选
// 是否采用深度克隆,如果为true,则该节点的所有后代节点也都会被克隆,如果为false,则只克隆该节点本身.

var p = document.getElementById("para1"),
var p_prime = p.cloneNode(true);

// 如果id为foo的这个元素有子节点,则从dom树中删除它的第一个子节点
var foo = document.getElementById("foo");

if ( foo.hasChildNodes() ) {
  foo.removeChild( foo.childNodes[0] );
}

var insertedNode = parentNode.insertBefore(newNode, referenceNode);
// insertedNode 被插入节点(newNode)
// parentNode 新插入节点的父节点
// newNode 用于插入的节点
// referenceNode newNode 将要插在这个节点之前
// 如果 referenceNode 为 null 则 newNode 将被插入到子节点的末尾。

let oldChild = node.removeChild(child);

parentNode.replaceChild(newChild, oldChild);
// newChild
// 用来替换 oldChild 的新节点。如果该节点已经存在于 DOM 树中,则它首先会被从原始位置删除。

// oldChild
// 被替换掉的原始节点。
复制代码

Element常用的属性和方法

属性 描述
tagName 以字符串形式返回指定属性的值
innerHTML 返回该元素包含的HTML代码,可读写
className 返回当前元素的class属性,可读写
style 返回元素节点的行内样式,可读写
方法 描述
addEventListener(type, listener, options) 添加事件的回调函数
removeEventListener(type, listener[, options]) 移除事件监听函数
dispatchEvent() 触发事件
preventDefault() 阻止默认的点击事件执行
setAttribute() 把指定的属性设置为指定的字符串值,如果该属性不存在则添加一个新属性

浏览器事件捕获,冒泡

浏览器事件模型中的过程主要分为三个阶段:捕获阶段、目标阶段、冒泡阶段。

事件模型

parent.addEventListener("click", function (e) {
    // e.stopPropagation(); 不再派发事件。终止事件在传播过程的捕获、目标处理或起泡阶段进一步传播。调用该方法后,该节点上处理该事件的处理程序将被调用,事件不再被分派到其他节点。

    // e.target.nodeName 指当前点击的元素, e.currentTarget.nodeName绑定监听事件的元素
    console.log("parent 捕获", e.target.nodeName, e.currentTarget.nodeName);
}, true);
复制代码

addEventListener(type, listener, options) 第三个参数

这里要注意addEventListener的第三个参数, 如果为true,就是代表在捕获阶段执行。如果为false,就是在冒泡阶段进行。

阻止事件传播

  • e.stopPropagation()

大家经常听到的可能是阻止冒泡,实际上这个方法不只能阻止冒泡,还能阻止捕获阶段的传播。

  • stopImmediatePropagation()

如果有多个相同类型事件的事件监听函数绑定到同一个元素,当该类型的事件触发时,它们会按照被添加的顺序执行。如果其中某个监听函数执行了 event.stopImmediatePropagation() 方法,则当前元素剩下的监听函数将不会被执行。

阻止默认行为

  • e.preventDefault()

可以阻止事件的默认行为发生,默认行为是指:点击a标签就转跳到其他页面、拖拽一个图片到浏览器会自动打开、点击表单的提交按钮会提交表单等等,因为有的时候我们并不希望发生这些事情,所以需要阻止默认行为

事件委托的方式

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
    </head>
    <body>
        <ul id="ul">
            <li>1</li>
            <li>2</li>
            <li>3</li>
            <li>4</li>
            <li>5</li>
            <li>6</li>
            <li>7</li>
            <li>8</li>
        </ul>
    </body>
    <script type="text/javascript">
        const ul = document.querySelector("ul");
        ul.addEventListener('click', function (e) {
            const target = e.target;
          if (target.tagName.toLowerCase() === "li") {
            const liList = this.querySelectorAll("li");
            index = Array.prototype.indexOf.call(liList, target);
            alert(`内容为${target.innerHTML}, 索引为${index}`);
          }
        })
    </script>
</html>


复制代码

兼容性

attachEvent——兼容:IE7、IE8; 不支持第三个参数来控制在哪个阶段发生,默认是绑定在冒泡阶段 addEventListener——兼容:firefox、chrome、IE、safari、opera;

浏览器兼容的绑定事件函数

class BomEvent {
    constructor(element) {
        this.element = element;
    }

    addEvent(type, handler) {
        if (this.element.addEventListener) {
            //事件类型、需要执行的函数、是否捕捉
            this.element.addEventListener(type, handler, false);
        } else if (this.element.attachEvent) {
            this.element.attachEvent('on' + type, function () {
                handler.call(element);
            });
        } else {
            this.element['on' + type] = handler;
        }
    }

    removeEvent(type, handler) {
        if (this.element.removeEnentListener) {
            this.element.removeEnentListener(type, handler, false);
        } else if (element.datachEvent) {
            this.element.detachEvent('on' + type, handler);
        } else {
            this.element['on' + type] = null;
        }
    }
}

// 阻止事件 (主要是事件冒泡,因为IE不支持事件捕获)
function stopPropagation(ev) {
    if (ev.stopPropagation) {
        ev.stopPropagation(); // 标准w3c
    } else {
        ev.cancelBubble = true; // IE
    }
}
// 取消事件的默认行为
function preventDefault(event) {
    if (event.preventDefault) {
        event.preventDefault(); // 标准w3c
    } else {
        event.returnValue = false; // IE
    }
}

复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享