3

见多识广,介绍Web开发中current开头的一些API属性

 2 years ago
source link: https://www.zhangxinxu.com/wordpress/2021/11/currentscript-currenttarget-currentsrc/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=10171 鑫空间-鑫生活
本文欢迎分享与聚合,全文转载就不必了,尊重版权,圈子就这么大,若急用可以联系授权。

封面占位图

一、事件对象currentTarget属性

使用示意:

button.addEventListsner('click', function (event) {
    // event.currentTarget
});

可以看到,currentTarget 是 event 事件对象的一个属性,在日常开发中,我们使用的更多的是 event.target,那么 event.currentTargetevent.target 的区别是什么呢?

我们看下面这个例子,HTML 代码如下:

<a href="###" id="element"><img src="zxx.jpg"></a>

此时给外面的 <a> 元素绑定点击事情:

element.addEventListener('click', function (event) {
    event.target.style.border = '10px solid deeppink';
    event.currentTarget.style.border = '10px solid deepskyblue';
});

就会看到,当点击图片的时候,<img> 元素出现了粉红边框,而 <a> 元素外面出现了天蓝边框。

实时效果如下:

mm9s.jpg

这是因为:

  • event.target 表示点击的元素;
  • event.currentTarget 表示绑定事件的元素。

在事件函数中,event.currentTarget 是可以和 this 划等号的,例如:

button.addEventListsner('click', function (event) {
    // 下面的返回值是 true
    console.log(event.currentTarget === this);
});

这就会带来疑问,既然已经有了 this,那还需要 currentTarget 属性做什么呢?

原因其实很简单,因为 this 上下文是会变化的,例如下面代码中的 this 就不是绑定事件的元素,此时 currentTarget 属性就能体现其作用了:

button.addEventListsner('click', (event) => {
    // 下面的返回值是 false
    console.log(event.currentTarget === this);
});

二、currentScript与当前运行脚本元素

currentScriptdocument 对象上的一个属性,可以返回当前 JS 代码执行所属的 <script> 元素。

<script id="thatsMe">console.log(document.currentScript);</script>

此时,控制台就会有类似下图的输出结果:

当前脚本执行所在的元素

大家如果条件允许(例如桌面浏览器访问),打开控制台,就可以看到截图所示的内容输出。

<script src="./zxx.js"></script>

其中,zxx.js 中有这么一行 JS 代码如下:

>console.log(document.currentScript);

就会输出下面截图所示的效果:

外露 JS 与currentScript

document.currentScript 不能在事件中,或者 JS 已经加载完毕之后再执行,例如:

document.addEventListener('click', function () {
    console.log(document.currentScript);
});

此时,在控制台输出的 log 值就是 null

又例如如果设置了 type="module",输出结果也是 null

<script id="thatsMe" type="module">
    // 结果是 null
    console.log(document.currentScript);
</script>

可见 document.currentScript 这个属性开始挺脆的,属于事儿多活还不怎么样的属性。

document.currentScript 是个低频使用属性,当一段 JS 或一个 JS 模块被多处引用的时候,document.currentScript 可以帮忙判断引用来源,和所处的上下文环境。

例如 A 页面和 B 页面同时引用了 zxx.js 文件,此时,就可以使用 document.currentScript 判断使用当前 JS 的是哪个页面。

IE12+浏览器支持,如下截图:

2021-11-01_194623.png

IE6-IE9,以及IE11浏览器有对应的 polyfill 解决方法,项目地址参见:https://github.com/JamesMGreene/document.currentScript

三、Web Animation API之currentTime

Web Animation API 在几年前我有专门介绍过,戳这里了解详细

currentTime 表示当前动画执行的时间,例如一个动画总计 3s,则 currentTime 可以返回当前执行的时间是在哪里,单位是 ms,也就是毫秒。

使用示意:

var fadeAni = element.animate([
    { opacity: 0 },
    { opacity: 1 }
], 3000);
setTimeout(() => {
    console.log(fadeAni.currentTime);
}, 1500);

此时显示的时间比 1483 略高一点,如下图所示:

动画当前时间

出乎意料的不是1500,我尝试了几次,时间都是差不多的,都是 1483ms 大一点。

在Firefox浏览器下结果是:

Firefox执行时间

嗯么……Chrome 浏览器的值还可以理解,动画的刷新率是 60,每次刷新间隔时间是 16.666ms,定时器执行的时候还在前面一帧,1500 – 16.6666,时间正好对得上。

至于 Firefox 浏览器,搞不定,算了,以后有时间再深究吧。

Web Animations API 的兼容性主要是 Safari 浏览器拖了后腿,不过有成熟的 polyfill 代码,因此,实际开发还是使用的。

Web Animations兼容性截图

四、TreeWalker API中的currentNode

关于 TreeWalker API 我不想多说,因为,日常开发使用 TreeWalker API 的机会并不大,如果你是开发大型的框架或者库,需要对整个 DOM 文档的树形结构进行遍历处理,则 TreeWalker API 就比较合适。

如果只是普通的遍历,则 document.querySelectorAll() 就能满足我们的日常开发需求。

与 TreeWalker API 相类似的还有 NodeIterator API 的,就功能而言, NodeIterator API 更简单,更纯粹一点。

而 TreeWalker 则细节和功能上要更强大一些,包括,可以忽略整个节点过滤(NodeFilter.FILTER_REJECT),可以指定过滤的方向,支持的属性和方法也更多,例如这里要介绍的 currentNode

下面通过一个简单的例子说说两者的区别。

已知 HTML 如下:

<ul id="container">
    <li>列表</li>
    <li>
        LI 内嵌列表:
        <ol>
            <li>项目1</li>
            <li>项目2</li>
        </ol>
    </li>
</ul>

1. FILTER_REJECT 作用区别

NodeIterator 中虽然也可以使用 NodeFilter.FILTER_REJECT,但是只是语法上支持,实际效果和 NodeFilter.FILTER_RSKIP 类似,但是在 TreeWalker 中, 节点一旦匹配 NodeFilter.FILTER_REJECT,其所有的子元素都会被忽略。

var nodeIterator = document.createNodeIterator(container, NodeFilter.SHOW_ELEMENT, { 
    acceptNode: function(node) { 
        return node.nodeName == 'LI' ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT; 
    } 
});

var pars = [];
var currentNode;

while (currentNode = nodeIterator.nextNode()) {
    pars.push(currentNode);
}

console.log(pars);
var treeWalker = document.createTreeWalker(container, NodeFilter.SHOW_ELEMENT, { 
    acceptNode: function(node) { 
        return node.nodeName == 'LI' ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT; 
    }
}, false);

var nodeList = [];
var currentNode2;

while (currentNode2 = treeWalker.nextNode()) {
    nodeList.push(currentNode2);
}

console.log(nodeList);

上面两段 JS 代码几乎一致,区别就在于一个是 createNodeIterator,一个是 createTreeWalker,但是最终出书的结果却明显有区别:

对比输出结果

2. 属性和方法数量的区别

直接看下面的表,显示了 NodeIterator 和 TreeWalker 对象在支持的属性和方法上的区别:

TreeWalker属性 NodeIterator属性 filter filter currentNode – TreeWalker方法 NodeIterator方法 previousNode() previousNode() nextNode() nextNode() parentNode() – firstChild() – lastChild() – previousSibling() – nextSibling() –

可见 TreeWalker 的遍历要强大很多。

3. currentNode 的含义和作用

TreeWalker.currentNode 可以返回 TreeWalker 对象当前指定的节点。

例如下面的示意代码:

var treeWalker = document.createTreeWalker(container, NodeFilter.SHOW_ELEMENT, { 
    acceptNode: function(node) { 
        return node.nodeName == 'LI' ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT; 
    }
}, false);

var nodeList = [];
var currentNode = treeWalker.currentNode;

while (currentNode) {
    nodeList.push(currentNode);
    currentNode = treeWalker.nextNode();
}

console.log(nodeList);

运行结果如下截图所示:

currentNode

treeWalker.currentNode 的第一个节点一定是根节点。

在开发中的作用,往往是改变遍历的根节点位置。

treeWalker.currentNode = otherNode;

此时,遍历的起点会改变为 otherNode。

TreeWalker API 是一个 IE9+ 浏览器支持的成熟的 API,可以放心使用。

五、IMG 图片当前地址 currentSrc

相比上面几个属性,currentSrc 属性要更常用,也更实用些,因为可替代低。

currentSrc 主要用在响应式图片开发中。

所谓“响应式图片”可以参考我之前的这篇文章:“响应式图片srcset全新释义sizes属性w描述符”。

例如下面这样一个 HTML 代码:

<img src="1.jpg"
  srcset="1.jpg 128w, 2.jpg 256w, 3.jpg 512w"
  sizes="(max-width: 360px) 340px, 128px">

在不同的设备宽度和不同的设备密度下,加载的图片是会有区别的,下面问题来了,如何知道当前 <img> 元素加载的图片呢?

这就需要 currentSrc 属性,返回当前真实价值的图片 URL 地址。

如果图片的资源加载判断是使用的 <source> 元素实现的,则 currentSrc 属性也是有效的。

<picture>
    <source srcset="logo-768.png 768w, logo-768-1.5x.png 1.5x">
    <source srcset="logo-480.png, logo-480-2x.png 2x">
    <img id="img" src="logo-320.png" alt="logo">
</picture>

此时,img.currentSrc 就是真实加载的图像 URL 地址。

audio、video同样适用

<video controls>
    <source src="foo.webm" type="video/webm">
    <source src="foo.ogg" type="video/ogg">
    <source src="foo.mov" type="video/quicktime">
</video>

此时可以使用 video.currentSrc 获知浏览器加载的究竟是哪个资源地址。

currentSrc 属性的兼容性和 srcset 等属性类似,是一个可以在移动端放心使用的html属性,如下图:

currentSrc 兼容性

六、其他及结语

对于 SVG 元素,还有 currentScalecurrentTranslate 这两个属性,表示 SVG 元素当前缩放和位移,不过因为日常开发使用场景不多,这里不做展开介绍。

其他就没什么了,本文介绍的这5个 current 开头的属性,虽然大家可能没怎么用过,但其实都是挺有用的些属性,建议了解下,可以不暂时不需要知道具体的细节,但是需要知道有这么个东西,这样当你遇到类似场景的时候,就能够快速找到问题的解决方法。

本文内容已经很长了,就不再继续展开做介绍了。

行文仓促,如果文中有表述不准确的地方,欢迎指正。

如果您觉得本文的内容对你的学习有所帮助,欢迎转发,欢迎分享,比心。

2764.svg

(本篇完)1f44d.svg 是不是学到了很多?可以分享到微信
1f44a.svg 有话要说?点击这里


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK