8 个你不知道的 DOM 功能[每日前端夜话0x79]

栏目: 后端 · 发布时间: 4年前

内容简介:翻译:疯狂的技术宅来源:

每日前端夜话 0x79

每日前端夜话,陪你聊前端。

每天晚上18:00准时推送。

正文共:4740 字

预计阅读时间: 16 分钟

翻译:疯狂的技术宅

来源: logrocket

8 个你不知道的 DOM 功能[每日前端夜话0x79]

最近关注了太多的工具,现在最好从所有 React 和 npm-install-everything 的文章中休息一下,来看看一些纯粹的 DOM 和 Web API 功能,它们可以在不依赖任何第三方库的前提下在现代浏览器中运行。

这篇文章将讲解八个鲜为人知的 DOM 功能,这些功能具有强大的浏览器支持。为了帮助你理解每个功能的工作原理,我将通过大量的测试代码为你自己提供演示,这些代码都放在了CodePen上。

由于微信公众号不能引用并显示CodePen上的效果,请大家点击文末的查看原文或者复制链接并粘贴到浏览器【http://blog.yidengxuetang.com/post/201905/30/】,到我的博客上查看效果。另外查看原文之前顺便点一下“在看” ^_^

学习这些方法和属性没有陡峭的学习曲线,并且可以与项目中所使用的任何 工具 集在一起使用。

addEventListener() 的新参数 options

你肯定用 addEventListener() 处理过将事件附加到 Web 文档中的元素。通常 addEventListener() 调用看起来像这样:

1element.addEventListener('click', doSomething, false);

第一个参数是正在监听的事件。第二个参数是一个回调函数,它将在事件发生时执行。第三个参数是一个名为 useCapture 的布尔值,用于指示是否要使用事件冒泡或捕获【 https://www.sitepoint.com/event-bubbling-javascript/ 】。

这些大家都知道(特别是前两个)。但也许你不知道 addEventListener() 也接受一个替换最终布尔值的参数。这个新参数是一个 options 对象,如下所示:

1element.addEventListener('click', doSomething, {
2  capture: false,
3  once: true,
4  passive: false
5});

请注意,该语法允许定义三个不同的属性。以下是每个含义的快速概述:

  • capture — 与之前提到的 useCapture 参数相同的布尔值【 https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Parameters

  • once — 布尔值,如果设置为 true ,则表示该事件应仅在目标元素上运行一次,然后被删除

  • passive — 一个最终的布尔值,如果设置为 true ,表示该函数永远不会调用 preventDefault() ,即使它被包含在函数体中

其中最有趣的是 once 选项。这肯定会在很多情况下派上用场,并且无需用 removeEventListener() 或使用其他一些复杂的技术来强制单个事件触发器。如果你用过 jQuery,可能熟悉该库中的类似功能:.one() 方法。

你可以试着运行以下 CodePen 项目中关于 options 对象的一些代码:

CodePen演示:https://codepen.io/impressivewebs/pen/GeJZYz/

请注意,演示页面上的按钮只会附加一次文本。如果将 once 值改为 false ,则多次单击该按钮,每次单击按钮时都会附加文本。

浏览器对 options 对象的支持非常好:所有浏览器都支持它,除了 IE11 及更早版本【 https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Browser_compatibility 】,因此如果你不考虑微软 Edge 之前的浏览器,那么使用起来还是非常安全的。

scrollTo() 方法用于在窗口或元素中平滑滚动

平滑滚动总是经常被用到的。当点击本地页面链接并立即跳转到指定位置时(如果你眨眼,甚至可能会错过跳转过程),这会显得很突兀。平滑滚动改进了页面的用户体验。

虽然过去用 jQuery 插件就足以完成了,但现在用 window.scrollTo() 方法只需要一行 JavaScript。

scrollTo() 方法作用于 Window 对象,告诉浏览器滚动到页面上的指定位置。这是一个最简单语法的例子:

1window.scrollTo(0, 1000);

这将向右滚动窗口 0px (表示x坐标或水平滚动)并向下滚动 1000px (垂直滚动,这通常是你想要的)。但这样做的话滚动并不是一个平滑的动画效果,页面将会突然滚动。

有时确实是你想要的。但是为了能够平滑滚动,你必须加入鲜为人知的 ScrollToOptions 对象,如下所示:

1window.scrollTo({
2  top: 0,
3  left: 1000,
4  behavior: 'smooth'
5});

这段代码与前面的例子相同,但在 options 对象中添加了 behavior 属性的 smooth 值。

请看下面这个 CodePen 演示,允许你自定义滚动量和行为:

CodePen演示:https://codepen.io/impressivewebs/pen/pGYXgj

尝试在框中输入一个数字(最好是一个比较大的数字,比如4000)并更改 behavior 选择框以使用 smoothauto (这是 behavior 属性仅有的两个选项)。

关于此功能的一些说明:

  • 对于 scrollTo() 的基本支持是全面的,但并非所有浏览器【 https://caniuse.com/#feat=element-scroll-methods 】都支持 options 对象

  • 此方法在应用于元素时也可以使用

  • 这些选项也同样适用于 scroll()scrollBy() 方法

setTimeout() 和带有可选参数的 setInterval()

在更多情况下,使用 window.setTimeout()window.setInterval() 实现基于时序的动画的方案已经被性能更好的 window.requestAnimationFrame() 所取代。但是有些情况下使用 setTimeout()setInterval() 是正确的选择,因此了解这些方法的一个鲜为人知的特性是很好的。

通常你总会看到这些方法被使用,语法如下:

let timer = window.setInterval(doSomething, 3000);
function doSomething () {
  // Something happens here…
}

这里的 setInterval() 传递两个参数:回调函数和时间间隔。如果使用 setTimeout() 将只运行一次,而在当前这种情况下,它会无限期地运行,直到我在传入 timer 变量时调用 window.clearTimeout()

这很简单。但是如果我希望回调函数能够接受参数呢?可以这样做:

let timer = window.setInterval(doSomething, 3000, 10, 20);
function doSomething (a, b) {
  // Something happens here…
}

注意我在 setInterval() 调用中添加了两个参数。然后我的 doSomething() 函数接受了这些参数,并可以根据需要操作它们。

这是一个 CodePen 演示,演示了如何使用 setTimeout()

CodePen:https://codepen.io/impressivewebs/pen/PgoNEj

单击该按钮时,将会使用传入的两个值进行计算。可以通过修改代码中的数字更改值。

至于浏览器支持,似乎在兼容性上有些小问题,不过看上去现在几乎所有还在使用中的浏览器都支持可选参数功能,包括 IE10。

单选按钮和复选框的 defaultChecked 属性

你可能知道,对于单选按钮和复选框,可以直接通过 checked 属性去获取或设置它,如下所示(假设 radioButton 是对特定表单输入的引用):

1console.log(radioButton.checked); // true
2radioButton.checked = false;
3console.log(radioButton.checked); // false

但是还有一个名为 defaultChecked 的属性,它可以应用于单选按钮组或复选框组,用来找出组中哪一个最初被设置为了 checked

这是一些HTML示例:

1<form id="form">
2  <input type="radio" value="one" name="setOne"> One
3  <input type="radio" value="two" name="setOne" checked> Two<br />
4  <input type="radio" value="three" name="setOne"> Three
5</form>

有了这个属性,即使在更改了被选中的单选按钮之后,也可以通过遍历找出最初哪一个是默认值,如下所示:

1for (i of myForm.setOne) {
2  if (i.defaultChecked === true) {
3    console.log(‘i.value’);
4  }
5}

下面是CodePen演示,它将显示当前选中的单选按钮或默认选中的单选按钮,具体取决于你所使用的按钮:

CodePen:https://codepen.io/impressivewebs/pen/qwWoOr

该示例中的 defaultChecked 选项将始终为 “Two” 单选按钮。如上所述,这也可以用于复选框组。你可以试着修改 HTML 中的默认选中选项,然后再次点击按钮看看效果。

下面是一个复选框组的演示:

CodePen:https://codepen.io/impressivewebs/pen/wZMJYQ

在这种情况下,你会注意到默认情况下应该会检查两个复选框,因此当使用 defaultChecked 查询时,这两个复选框都会返回 true

使用 normalize() 和 wholeText 操作文本节点

HTML 文档中的文本节点可能会很复杂,尤其是当动态插入或创建节点时。例如假设有以下 HTML:

1<p id="el">This is the initial text.</p>
2

然后我可以在该段落元素中添加一个文本节点:

1let el = document.getElementById('el');
2el.appendChild(document.createTextNode(' Some more text.'));
3console.log(el.childNodes.length); // 2

请注意,在附加的文本节点之后的注释中,我记录了段落内子节点的长度,并且它表示有两个节点。这些节点是一个文本字符串,但由于文本是动态附加的,因此它们应该被视为单独的节点。

在某些情况下,如果将文本视为单个文本节点会更有帮助,这使文本更容易操作。这就是 normalize()wholeText() 的用武之地。

normalize() 方法可用于合并单独的文本节点:

1el.normalize();
2console.log(el.childNodes.length); // 1

在元素上调用 normalize() 将会合并该元素内的任何相邻的文本节点。如果恰好在相邻的文本节点之间散布着一些 HTML,那么 HTML 将保持原样,而所有相邻的文本节点将被合并。

但是,如果由于某种原因我想使文本节点分开,但我仍然希望能够将文本作为一个单元抓取,那么 wholeText 就是有用的。因此我可以在相邻的文本节点上执行此操作,而不是调用 normalize()

1console.log(el.childNodes[0].wholeText);
2// This is the initial text. Some more text.
3console.log(el.childNodes.length); // 2

只要我没有调用 normalize() ,文本节点的长度将保持为 2 ,我可以用 wholeText 记录整个文本。但需要注意以下几点:

  • 我必须在其中一个文本节点上调用 wholeText ,而不是元素(因此代码中的 el.childNodes [0]el.childNodes[1] 也可以正常工作)

  • 文本节点必须相邻,中间不能有其他 HTML 分隔它们

你可以看到这两个功能以及 splitText() 方法已经用在了这个 CodePen 演示中【 https://codepen.io/impressivewebs/pen/ZZzrBV?editors=0011 】。打开 CodePen 控制台或浏览器的开发人员工具控制台可以查看生成的日志。

insertAdjacentElement() 和 insertAdjacentText()

很多人可能很熟悉 insertAdjacentHTML() 方法,它允许你轻松地将一串文本或 HTML 添加到页面中与其他元素相关的特定位置。

但也许你不知道的是,还有另外两个以类似方式工作的方法: insertAdjacentElement()insertAdjacentText()

insertAdjacentHTML() 的一个缺点是插入的内容必须是字符串的形式。因此如果要包含 HTML,则必须将其声明为:

1el.insertAdjacentHTML('beforebegin', '<p><b>Some example</b> text goes here.</p>');

但是 insertAdjacentElement() 的第二个参数可以是元素引用:

1let el = document.getElementById('example'),
2addEl = document.getElementById('other');
3el.insertAdjacentElement('beforebegin', addEl);

这个方法的有趣之处在于,它不仅会将引用的元素添加到指定的位置,而且还会将元素从文档中的原始位置移除。这是一种在 DOM 中移动元素的简单方法。

这是使用 insertAdjacentElement() 的 CodePen 演示。点击按钮可以有效地“移动”目标元素:

CodePen:https://codepen.io/impressivewebs/pen/MRjOpj

insertAdjacentText() 方法的工作方式类似,但提供的文本字符串将仅作为文本插入,即使它包含HTML。请注意以下演示:

CodePen:https://codepen.io/impressivewebs/pen/MRymba

你可以将自己的文本添加到输入字段,然后使用该按钮将其添加到文档中。注意:任何特殊字符(如HTML标记)都将会作为 HTML 实体插入,请区分此方法与 insertAdjacentHTML() 行为的区别。

所有三种方法( insertAdjacentHTML()insertAdjacentElement()insertAdjacentText() )的第一个参数所使用的值的规则是相同的:

  • beforebegin :在调用方法的元素之前插入

  • afterbegin :在第一个子节点之前插入元素内部

  • beforeend :在最后一个子节点之后插入元素内部

  • afterend :插入到元素后面

event.detail 属性

如前所述,我们可以用熟悉的 addEventListener() 方法将事件附加到网页上的元素。例如:

1btn.addEventListener('click', function () {
2  // do something here...
3}, false);

使用 addEventListener() 时,你可能想要阻止函数调用中的默认浏览器行为。例如,你可能希望拦截 <a> 元素的点击并使用 JavaScript 来处理,你会这样做:

1btn.addEventListener('click', function (e) {
2  // do something here...
3  e.preventDefault();
4}, false);

这里使用了 preventDefault() ,这等价于老式的 return false 语句。这需要你将 event 对象传递给函数,因为在该对象上调用了 preventDefault() 方法。

但是你可以用 event 对象做更多事情。事实上当使用某些事件时(例如 clickdbclickmouseupmousedown ),这些事件会暴露一些叫做 UIEvent 接口的东西。正如 MDN 所指出的,该接口上的许多功能已被弃用或没有标准化。但最有趣并且最有用的是 detail 属性,它是官方规范的一部分。

以下是它在同一个事件监听器示例中的代码:

1btn.addEventListener('click', function (e) {
2  // do something here...
3  console.log(e.detail);
4}, false);

我已经设置了一个 CodePen 演示,演示了使用许多不同事件的结果:

CodePen:https://codepen.io/impressivewebs/pen/QoZoQe

演示中的每个按钮都将按照按钮文本描述的方式进行响应,并显示一条显示当前点击次数的消息。需要注意的是:

  • WebKit 浏览器允许无限制的点击次数,除了 dblclick ,它总是两次点击。 Firefox 只允许最多三次点击,然后计数再次开始

  • 我已经包通过包含 blurfocus 来证明这些不符合条件并且总是返回0(即没有点击)

  • 在 IE11 等旧版浏览器中的行为严重不一致

请注意,在演示中包含了一个很好的用例——模仿三击事件:

1btnT.addEventListener('click', function (e) {
2  if (e.detail === 3) {
3    trpl.value = 'Triple Click Successful!';
4  }
5}, false);

如果所有浏览器都计算过三次点击次数,那么你还可以检测到更高的点击次数,但我认为在大多数情况下,三次点击事件就足够了。

scrollHeight 和 scrollWidth 属性

scrollHeightscrollWidth 属性可能听起来很熟悉,因为你可能会将它们与其他与宽度和高度相关的 DOM 功能混淆。例如, offsetWidthoffsetHeight 属性将返回元素的高度和宽度,而不会考虑溢出。

请注意以下演示:

CodePen:https://codepen.io/impressivewebs/pen/WWxEpX

演示中的列具有相同的内容。左边列的 overflow 被设置为 auto ,而右边列的 overflow 被设置为 hiddenoffsetHeight 属性返回相同的值,因为它不考虑可滚动区域或隐藏区域,它只测量元素的实际高度,包括垂直填充和边框。

另一方面,命名恰当的 scrollHeight 属性将会计算元素的完整高度,包括可滚动(或隐藏)区域:

CodePen:https://codepen.io/impressivewebs/pen/EJyvoB

上面的演示与前一个相同,只不过它用了 scrollHeight 来获取每列的高度。再次注意,两列的值相同。但这次它的值要打得多,因为溢出区域也算作高度的一部分。

上面的示例主要关注元素高度,这是最常见的用例,但你也可以用 offsetWidthscrollWidth ,它们以相同的方式应用于水平滚动。

总结

这就是你不知道的 DOM 功能列表,这些可能是我在近几年遇到的一些最有趣的功能,所以我希望在不远的将来你能把它们用在自己的项目中。

如果你之前用过其中的某些功能,或是如果你能想到其中某个功能的有趣的用例,请在评论中告诉我。

原文:https://blog.logrocket.com/8-dom-features-you-didnt-know-existed-ec2a0a28fd89

下面夹杂一些私货:也许你和高薪之间只差这一张图

2019年京程一灯课程体系上新,这是我们第一次将全部课程列表对外开放。

愿你有个好前程,愿你月薪30K。我们是认真的 ! 8 个你不知道的 DOM 功能[每日前端夜话0x79]

8 个你不知道的 DOM 功能[每日前端夜话0x79]

在公众号内回复“体系”查看高清大图

长按二维码,加大鹏老师微信好友

拉你加入前端技术交流群

唠一唠怎样才能拿高薪

8 个你不知道的 DOM 功能[每日前端夜话0x79]

小手一抖,资料全有。长按二维码关注 前端先锋 ,阅读更多技术文章和业界动态。

8 个你不知道的 DOM 功能[每日前端夜话0x79]


以上所述就是小编给大家介绍的《8 个你不知道的 DOM 功能[每日前端夜话0x79]》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Big Java Late Objects

Big Java Late Objects

Horstmann, Cay S. / 2012-2 / 896.00元

The introductory programming course is difficult. Many students fail to succeed or have trouble in the course because they don't understand the material and do not practice programming sufficiently. ......一起来看看 《Big Java Late Objects》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具