探索在原生网页中使用自定义数据属性

先说说我为什么有这种“奇怪”的想法。
它基于这样一个场景:我最近闲来无事完善了一个小demo:音乐播放器。在里面有一个功能 —— 点击列表某一项弹出音乐播放弹框。我原先一直是“为每一项单独加一个click事件监听”。这很糟糕!

<div id="videob"></div>

//js代码
videob.onclick=function(){
	let video=document.createElement('video')
	video.setAttribute('src','xxx')
	video.setAttribute('controls','controls')
	video.style.cssText="width:90%;height:300px"
	document.querySelector('body').appendChild(video)
}

后来我优化时改用了 事件代理 ,不得不承认它非常优秀,但是我不得不改变结构,使得js中出现了一堆“MP4数据”(一个数组),在触发事件时判断当前是哪一个,然后从数组中拿到赋值给 audiosrc


事实上,在开发 Web 应用时,经常会用 JavaScript 获取文档之外的信息 ,某些情况下,我们需要用一些技巧来处理这些额外信息以保证 Web 应用能够正常运行。一般而言,技巧无外乎是将额外的信息塞入事件处理程序或滥用 rel 属性或 class 属性以方便注入行为。

幸运的是,HTML5引入了自定义数据属性:所有的自定义数据属性都以 data-前缀开头,HTML5 文档的验证器会在验证时忽略它。开发人员可以在任意元素中加入自定义数据属性,属性值可以是照片的元数据、经纬度坐标或者弹出窗口的尺寸。
最棒的是,几乎在所有浏览器中,你都能够使用自定义数据属性,因为我们可以轻易地使用 JavaScript 来获取它们。


在开始操作之前,我们必须先“重复”一个概念:0级DOM事件 。通俗来说就是各种on前缀的事件名称(比如:onclick、onmouseon、onkeydown),他们可以存在于 <script> 或者HTML标签中,且没有事件捕获和冒泡机制!

为什么设置onclick不好
有这样一个场景:弹出窗口的名声似乎一直不好 —— 这是很自然的事情。弹出窗口常被用来向用户显示广告,或者伪装成不被怀疑的间谍软件或病毒,而最糟糕的是骗取个人信息并随后加以出售。因此,大多数浏览器都有阻止弹出窗口的插件也就不足为怪了。
不过,Web 应用的开发人员尤其是初学者常常需要依赖于弹出窗口,以便向用户显示在线帮助信息、附加选项或者其他重要的用户界面功能。
我们通常能在一个页面中看到如下代码:

<a href="#" onclick="window.open('xxx',null,'width=300,height=300');">go to xxx</a>

就是这段没怎么起眼的代码存在着非常致命的问题:

  1. 链接的目标地址没有设置!如果 JavaScript 被禁用了,那么链接将无法引导用户进入相应页面。这很一个非常严重,以至于我们需要立即解决。我建议开发者永远不要省略 href属性、任何情况下都不要为 href 属性赋“#”。
  2. 注意保持行为与内容分离,正如用链接样式表保持样式信息分离一样。开始的时候,使用 onclick 会带来便利,但是想象一下页面上有 50 个链接的情况,那时你会看到 onclick 方法失控的场面。你将只能一遍又一遍地编写重复的 JavaScript 代码。如果是通过服务器端代码来生成浏览器端代码,那么你就是在增加 JavaScript 事件。

为了解决上面的问题,我们为每个a链接设置了href,而且增加了不同的class!以增加“相同类型元素”的可识别性。

<a href="xxx" class="pop">go to xxx</a>

//js代码
var link=document.querySelector('a.pop')
link.onclick=function(e){
	e.preventDefault();
	window.open(this.getAttribute('href'));
}

我们还没有为open设置长宽!

现在,我们又回到了和文章开头一样的问题!


使用自定义数据属性
当创建应用了 JavaScript 的 Web 应用时,刚刚提到的情况比较常见。如你所见,在代码中存储窗口的期望高度和宽度是可取的,但是 onclick 方法有诸多弊端。我们可以改换在元素上嵌入属性的方式加以实现。现在要做的是将链接改造成下面这种形式:

<a href="xxx" data-width="600" data-height="400" class="pop">go to xxx</a>
var link=document.querySelector('a.pop')
link.onclick=function(e){
	e.preventDefault();
	window.open(this.getAttribute('href'),null,"width="+this.getAttribute('data-width')+",height="+this.getAttribute('data-height'));
}

好吧,这个例子似乎没有什么说服力。
但是为了让你能够真正认识到“问题的严重性”,我将带你来看看文章开头的示例:

<div id="mxc">
	<div class="videob" data-uri="./img/1.mp4"></div>
	<div class="videob" data-uri="./img/2.mp4"></div>
</div>
mxc.addEventListener('click',function(e){
	let target=e.target || e.srcElement;
	let video=document.createElement('video')
	video.setAttribute('src',target.getAttribute('data-uri'))
	video.setAttribute('controls','controls')
	video.style.cssText="width:90%;height:300px;margin:0 auto"
	document.querySelector('body').appendChild(video)
},false)

这样才“真正”体现了“代理的价值”!


事实上,我们确实在很多地方可以用到它:比如自定义组件(vue / 微信小程序)中我们可以为它设置参数为它本身携带的值。


展望
开发者可以用自定义数据属性将各式各样的信息嵌入标记中。
我们可以使用自定义数据属性将日期和时间缓存在页面中,并以用户时区为基准来显示日期和时间。只需将时间以 UTC 的形式置于 HTML 页面中,在客户端将其转换成用户本地时间即可。(主要配合浏览器的缓存:在页面信息未改变时不会更新)

猜你喜欢

转载自blog.csdn.net/qq_43624878/article/details/107977721