《JavaScript重难点实例精讲》— DOM 与事件

《JavaScript重难点实例精讲》— DOM 与事件

xiaolu
2022-02-10 / 0 评论 / 15 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2022年02月14日,已超过134天没有更新,若内容或图片失效,请留言反馈。
DOM 是文档对象模型,全称为 Document Object Model。DOM 用一个逻辑树来表示一个文档,树的每个分支终点都是一个节点,每个节点包含着对象。DOM 提供了对文档结构化的表述,通过绑定不同的事件可以改变文档结构、样式和内容,从而能实现 “动态” 的页面。
——《JavaScript重难点实例精讲》


DOM 选择器

关于querySelctor的补充

实际匹配过程会遍历整个文档结构,创建一个匹配元素的初始列表,然后判断每个元素是否是基准元素的后代元素,第一个属于基准元素的后代元素将被返回,以下示例可以很好说明这一点:

<div>
  <h5>Original content</h5>
  <span>outside content</span>
  <p class="content">
    inside paragraph
    <span>inside span</span>
    inside paragraph
  </p>
<div>
var baseElement = document.querySelector("p");
console.log(baseElement.querySelector("div span").innerText);
// inside span

p 元素中并不存在 "div span" 这样的子元素,但是结果却输出了 inside span,这是因为匹配过程先是找出所有符合 "div span" 的元素,然后再判断它是否是基准元素的子元素

关于 HTMLCollection 和 NodeList

事实上,存在 Element 和 Node 两个类,(Document,Element 等都继承自 Node),这两个类下分别有 children() 和 childNodes() 两个函数,前者的返回值类型是 HTMLCollection, 后者是 NodeList

相同点

  • 都是类数组对象,有 length 属性,可以通过 call 或 apply 转变成真正的数组
  • 都有 item 函数,通过索引定位函数
  • 都是实时性的,DOM 树的变化会及时反映到这两个对象上,但是有一点比较特殊, querySelectorAll() 这个函数返回的 NodeList 对象是静态的,不是动态实时的

不同点

  • HTMLCollection 比 NodeList 多一个 namedItem() 函数 ,可通过 id 或 name 属性定位元素
  • HTMLCollection 对象只包含元素集合,即具有标签名的元素,而 NodeList 对象是节点的集合,既包括元素,也包括节点,如 text 文本节点

DOM 基本操作

// 创建一个元素节点
document.createElement('li');
// 创建一个文本节点
document.createTextNode('some text');
// 创建一个属性节点
document.createAttribute('class');
// 元素节点绑定属性节点
document.setArritbuteNode(something);
// 将文本节点作为元素节点的子元素
elementNode.appendChild(textNode);
// 将文本节点添加到元素节点前
mainNode.insertBefore(textNode, elementNode);

// 父节点删除第一个子节点
mainNode.removeChild(firstChild);
// 元素节点删除 href 属性节点
link.removeAttribute('href');
// 删除文本节点
link.innerHtml = '';

// 更新节点
mainNode.replaceChild(newDiv, div1);
// 更新样式 class
mainNode.className = 'container';
mainNode.setAttribute('class', 'container');
// 更新行内样式
mainNode.style.color = 'red';
mainNode.setAttribute('style', 'color:red;');

DOM 事件流

根据 W3C 标准,事件处理程序有三种级别:

DOM0 级事件处理程序

表现形式1:

var btn = document.getElementById('myBtn');
btn.onclick = function handler(){
  alert('you clicked!')
}

表现形式2:

<button onlick="handler()">Click Me</button>
<button onlick="alert('OK')">Click Me</button>
<script>
function handler() {
  alert('you clicked!');
}
</script>

DOM0 级事件只能绑定一个函数,这两种表现形式同时存在时,第一种会覆盖第二种,且 DOM0 级事件处理程序 只支持冒泡阶段,删除绑定时的操作如下:

btn.onclick = null;

DOM2 级事件处理程序

DOM2 级事件处理方式规定了添加事件处理程序和删除事件处理程序的方法,实现方式如下:

// browser < IE10,只支持冒泡阶段
element.attachEvent("on" + eventName, handler);
element.detachEvent("on" + eventName, handler);

// browser >= IE11 or other browsers,支持捕获和冒泡
// useCapture 表示是否支持冒泡,默认 false
addEventListener(eventName, handler, useCapture);
removeEventListener(eventName, handler, useCapture);

DOM2 级事件处理程序 支持绑定多个函数 ,达到条件时,所有绑定的函数都会触发 (包括 < IE10 的浏览器)

<div id='mybtn'>Click Me!</div>
<script>
  var elm = document.getElementById('mybtn');
  elm.addEventListener('click', function(){
    console.log('fisrt output');
  });
  elm.addEventListener('click', function(){
    console.log('second output');
  });
  // first output
  // second output
</script>

DOM3 级事件处理程序

DOM3 级事件处理程序允许自定义事件,它由 createEvent() 函数创建,返回的对象有一个 initCustomEvent() 函数,通过传递对应的参数可以自定义事件,判断是否支持DOM3:document.implementation.hasFeature('CustomEvents', '3.0'),如果返回 true 表示支持,否则不支持

事件处理 Tips

事件委托

事件委托是利用事件冒泡原理,管理某一类型的所有事件,利用父元素来代表子元素的某一类型的处理方式。
——《JavaScript重难点实例精讲》

没接触过事件委托的概念,但是自己在实际运用中确实用到了这种方法:

<ul>
  <li></li>
  <li></li>
  <li></li>
  ...
</ul>

对于这样的列表,或者是表格,如果对每个 li 绑定事件处理函数会十分繁琐,而且会导致一些负面影响:

  • 事件处理程序过多导致 页面交互时间过长
  • 事件处理程序过多导致 内存占用过多

以下示例没有在每个 li 上绑定函数,而是在 ul 上绑定了函数,达到一样的效果:

<body>
    <ul>
        <li>文本1</li>
        <li>文本2</li>
        <li>文本3</li>
        <!-- more -->
    </ul>
    <button id="add">Add Li</button>
</body>

<script>
    var add = document.querySelector('#add');
    var ul = document.querySelector('ul');
    ul.addEventListener('click', function (event) {
        console.log(event.target.innerText);
    });
    add.addEventListener('click', function () {
        var newLi = document.createElement('li');
        var newText = document.createTextNode('文本4');
        newLi.appendChild(newText);
        ul.appendChild(newLi);
    });
</script>
0

评论 (0)

取消