首页技术文章正文

-8 个你不知道的 DOM 功能【黑马web前端】

更新时间:2019年07月26日 11时16分40秒 来源:黑马程序员论坛



1.addEventListener() 的新参数 options
你肯定用 addEventListener() 处理过将事件附加到 Web 文档中的元素。通常addEventListener() 调用看起来像这样:
[JavaScript] 纯文本查看 复制代码
element.addEventListener('click', doSomething, false);

第一个参数是正在监听的事件。第二个参数是一个回调函数,它将在事件发生时执行。第三个参数是一个名为 useCapture 的布尔值,用于指示是否要使用事件冒泡或捕获【https://www.sitepoint.com/event-bubbling-javascript/】。
这些大家都知道(特别是前两个)。但也许你不知道 addEventListener() 也接受一个替换最终布尔值的参数。这个新参数是一个 options 对象,如下所示:
[JavaScript] 纯文本查看 复制代码
element.addEventListener('click', doSomething, {
  capture: false,
  once: true,
  passive: false
});

请注意,该语法允许定义三个不同的属性。以下是每个含义的快速概述:
  • capture  — 与之前提到的 useCapture  参数相同的布尔值【https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Parameters
  • once  — 布尔值,如果设置为 true,则表示该事件应仅在目标元素上运行一次,然后被删除passive  — 一个最终的布尔值,如果设置为 true,表示该函数永远不会调用preventDefault(),即使它被包含在函数体中

其中最有趣的是 once 选项。这肯定会在很多情况下派上用场,并且无需用removeEventListener() 或使用其他一些复杂的技术来强制单个事件触发器。如果你用过 jQuery,可能熟悉该库中的类似功能:.one() 方法。
浏览器对 options 对象的支持非常好:所有浏览器都支持它,除了 IE11 及更早版本【https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Browser_compatibility】,因此如果你不考虑微软 Edge 之前的浏览器,那么使用起来还是非常安全的。
2.scrollTo() 方法用于在窗口或元素中平滑滚动
平滑滚动总是经常被用到的。当点击本地页面链接并立即跳转到指定位置时(如果你眨眼,甚至可能会错过跳转过程),这会显得很突兀。平滑滚动改进了页面的用户体验。
虽然过去用 jQuery 插件就足以完成了,但现在用 window.scrollTo() 方法只需要一行 JavaScript。
scrollTo() 方法作用于 Window 对象,告诉浏览器滚动到页面上的指定位置。这是一个最简单语法的例子:
[JavaScript] 纯文本查看 复制代码
window.scrollTo(0, 1000);
这将向右滚动窗口 0px (表示x坐标或水平滚动)并向下滚动 1000px (垂直滚动,这通常是你想要的)。但这样做的话滚动并不是一个平滑的动画效果,页面将会突然滚动。
有时确实是你想要的。但是为了能够平滑滚动,你必须加入鲜为人知的ScrollToOptions 对象,如下所示:
[JavaScript] 纯文本查看 复制代码
window.scrollTo({
  top: 0,
  left: 1000,
  behavior: 'smooth'
});
这段代码与前面的例子相同,但在 options 对象中添加了 behavior 属性的smooth值。
关于此功能的一些说明:
  • 对于 scrollTo() 的基本支持是全面的,但并非所有浏览器【https://caniuse.com/#feat=element-scroll-methods】都支持 options 对象
  • 此方法在应用于元素时也可以使用
  • 这些选项也同样适用于 scroll() 和 scrollBy() 方法


3.setTimeout()和带有可选参数的setInterval()
在更多情况下,使用 window.setTimeout()window.setInterval()实现基于时序的动画的方案已经被性能更好的window.requestAnimationFrame() 所取代。但是有些情况下使用setTimeout()setInterval() 是正确的选择,因此了解这些方法的一个鲜为人知的特性是很好的。
通常你总会看到这些方法被使用,语法如下:
[JavaScript] 纯文本查看 复制代码
let timer = window.setInterval(doSomething, 3000);
function doSomething () {
  // Something happens here…
}

这里的 setInterval() 传递两个参数:回调函数和时间间隔。如果使用setTimeout() 将只运行一次,而在当前这种情况下,它会无限期地运行,直到我在传入 timer 变量时调用 window.clearTimeout()。
这很简单。但是如果我希望回调函数能够接受参数呢?可以这样做:
[JavaScript] 纯文本查看 复制代码
let timer = window.setInterval(doSomething, 3000, 10, 20);
function doSomething (a, b) {
  // Something happens here…
}

注意我在 setInterval() 调用中添加了两个参数。然后我的 doSomething()函数接受了这些参数,并可以根据需要操作它们。
至于浏览器支持,似乎在兼容性上有些小问题,不过看上去现在几乎所有还在使用中的浏览器都支持可选参数功能,包括 IE10。
4.单选按钮和复选框的 defaultChecked 属性
你可能知道,对于单选按钮和复选框,可以直接通过 checked 属性去获取或设置它,如下所示(假设 radioButton 是对特定表单输入的引用):
[JavaScript] 纯文本查看 复制代码
console.log(radioButton.checked); // true
radioButton.checked = false;
console.log(radioButton.checked); // false

但是还有一个名为
[JavaScript] 纯文本查看 复制代码
el.insertAdjacentHTML('beforebegin', '<p><b>Some example</b> text goes here.</p>');
defaultChecked 的属性,它可以应用于单选按
钮组或复
选框组,用来找出组中哪一个最初被设置为了 checked。
这是一些HTML示例:
[HTML] 纯文本查看 复制代码
<form id="form">
  <input type="radio" value="one" name="setOne"> One
  <input type="radio" value="two" name="setOne" checked> Two<br />
  <input type="radio" value="three" name="setOne"> Three
</form>
有了这个属性,即使在更改了被选中的单选按钮之后,也可以通过遍历找出最初哪一个是默认值,如下所示:
[JavaScript] 纯文本查看 复制代码
for (i of myForm.setOne) {
  if (i.defaultChecked === true) {
    console.log(‘i.value’);
  }
}
5.使用 normalize() 和 wholeText 操作文本节点
HTML 文档中的文本节点可能会很复杂,尤其是当动态插入或创建节点时。例如假设有以下 HTML:
[HTML] 纯文本查看 复制代码
<p id="el">This is the initial text.</p>
然后我可以在该段落元素中添加一个文本节点:
[JavaScript] 纯文本查看 复制代码
let el = document.getElementById('el');
el.appendChild(document.createTextNode(' Some more text.'));
console.log(el.childNodes.length); // 2
请注意,在附加的文本节点之后的注释中,我记录了段落内子节点的长度,并且它表示有两个节点。这些节点是一个文本字符串,但由于文本是动态附加的,因此它们应该被视为单独的节点。
在某些情况下,如果将文本视为单个文本节点会更有帮助,这使文本更容易操作。这就是 normalize()和wholeText()的用武之地。
normalize() 方法可用于合并单独的文本节点:
[JavaScript] 纯文本查看 复制代码
el.normalize();
console.log(el.childNodes.length); // 1
在元素上调用 normalize() 将会合并该元素内的任何相邻的文本节点。如果恰好在相邻的文本节点之间散布着一些 HTML,那么 HTML 将保持原样,而所有相邻的文本节点将被合并。
但是,如果由于某种原因我想使文本节点分开,但我仍然希望能够将文本作为一个单元抓取,那么 wholeText 就是有用的。因此我可以在相邻的文本节点上执行此操作,而不是调用 normalize()。
[JavaScript] 纯文本查看 复制代码
console.log(el.childNodes[0].wholeText);
// This is the initial text. Some more text.
console.log(el.childNodes.length); // 2
只要我没有调用 normalize(),文本节点的长度将保持为 2,我可以用wholeText 记录整个文本。但需要注意以下几点:
  • 我必须在其中一个文本节点上调用 wholeText,而不是元素(因此代码中的el.childNodes [0]、el.childNodes[1]也可以正常工作)
  • 文本节点必须相邻,中间不能有其他 HTML 分隔它们

6.insertAdjacentElement() 和 insertAdjacentText()
很多人可能很熟悉 insertAdjacentHTML() 方法,它允许你轻松地将一串文本或 HTML 添加到页面中与其他元素相关的特定位置。
但也许你不知道的是,还有另外两个以类似方式工作的方法:insertAdjacentElement() 和 insertAdjacentText()。
insertAdjacentHTML() 的一个缺点是插入的内容必须是字符串的形式。因此如果要包含 HTML,则必须将其声明为:
[JavaScript] 纯文本查看 复制代码
el.insertAdjacentHTML('beforebegin', '<p><b>Some example</b> text goes here.</p>');
但是 insertAdjacentElement() 的第二个参数可以是元素引用:
[JavaScript] 纯文本查看 复制代码
let el = document.getElementById('example'),
addEl = document.getElementById('other');
el.insertAdjacentElement('beforebegin', addEl);
这个方法的有趣之处在于,它不仅会将引用的元素添加到指定的位置,而且还会将元素从文档中的原始位置移除。这是一种在 DOM 中移动元素的简单方法。
所有三种方法(insertAdjacentHTML(),insertAdjacentElement()和insertAdjacentText() )的第一个参数所使用的值的规则是相同的:
  • beforebegin:在调用方法的元素之前插入
  • afterbegin:在第一个子节点之前插入元素内部
  • beforeend:在最后一个子节点之后插入元素内部
  • afterend:插入到元素后面

7.event.detail 属性
如前所述,我们可以用熟悉的 addEventListener()方法将事件附加到网页上的元素。例如:
[JavaScript] 纯文本查看 复制代码
btn.addEventListener('click', function () {
  // do something here...
}, false);

使用addEventListener()时,你可能想要阻止函数调用中的默认浏览器行为。例如,你可能希望拦截 <a> 元素的点击并使用 JavaScript 来处理,你会这样做:
[JavaScript] 纯文本查看 复制代码
btn.addEventListener('click', function (e) {
  // do something here...
  e.preventDefault();
}, false);

这里使用了 preventDefault(),这等价于老式的 return false 语句。这需要你将 event 对象传递给函数,因为在该对象上调用了 preventDefault()方法。
但是你可以用 event 对象做更多事情。事实上当使用某些事件时(例如click,dbclick,mouseup,mousedown),这些事件会暴露一些叫做 UIEvent 接口的东西。正如 MDN 所指出的,该接口上的许多功能已被弃用或没有标准化。但最有趣并且最有用的是 detail 属性,它是官方规范的一部分。
以下是它在同一个事件监听器示例中的代码:
[JavaScript] 纯文本查看 复制代码
btn.addEventListener('click', function (e) {
  // do something here...
  console.log(e.detail);
}, false);
8.scrollHeight 和 scrollWidth 属性
scrollHeight 和 scrollWidth 属性可能听起来很熟悉,因为你可能会将它们与其他与宽度和高度相关的 DOM 功能混淆。例如,offsetWidth 和offsetHeight 属性将返回元素的高度和宽度,而不会考虑溢出。

推荐了解热门学科

java培训 Python人工智能 Web前端培训 PHP培训
区块链培训 影视制作培训 C++培训 产品经理培训
UI设计培训 新媒体培训 产品经理培训 Linux运维
大数据培训 智能机器人软件开发




传智播客是一家致力于培养高素质软件开发人才的科技公司“黑马程序员”是传智播客旗下高端IT教育品牌。自“黑马程序员”成立以来,教学研发团队一直致力于打造精品课程资源,不断在产、学、研3个层面创新自己的执教理念与教学方针,并集中“黑马程序员”的优势力量,针对性地出版了计算机系列教材50多册,制作教学视频数+套,发表各类技术文章数百篇。

传智播客从未停止思考

传智播客副总裁毕向东在2019IT培训行业变革大会提到,“传智播客意识到企业的用人需求已经从初级程序员升级到中高级程序员,具备多领域、多行业项目经验的人才成为企业用人的首选。”

中级程序员和初级程序员的差别在哪里?
项目经验。毕向东表示,“中级程序员和初级程序员最大的差别在于中级程序员比初级程序员多了三四年的工作经验,从而多出了更多的项目经验。“为此,传智播客研究院引进曾在知名IT企业如阿里、IBM就职的高级技术专家,集中研发面向中高级程序员的课程,用以满足企业用人需求,尽快补全IT行业所需的人才缺口。

何为中高级程序员课程?

传智播客进行了定义。中高级程序员课程,是在当前主流的初级程序员课程的基础上,增加多领域多行业的含金量项目,从技术的广度和深度上进行拓展“我们希望用5年的时间,打造上百个高含金量的项目,覆盖主流的32个行业。”传智播客课程研发总监于洋表示。




黑马程序员热门视频教程【点击播放】

Python入门教程完整版(懂中文就能学会) 零起点打开Java世界的大门
C++| 匠心之作 从0到1入门学编程 PHP|零基础入门开发者编程核心技术
Web前端入门教程_Web前端html+css+JavaScript 软件测试入门到精通


在线咨询 我要报名
和我们在线交谈!