HTML内联事件属性中如何获取元素本身并移除该属性?
嘿,我来帮你拆解这个问题,其实这里有两个核心点:一是内联事件里怎么正确获取触发元素本身,二是非阻塞加载样式后清理onload属性的最优方案——刚好我踩过类似的坑,给你详细说说:
一、内联事件中获取触发元素的正确姿势
首先要区分两种场景:
1. 普通元素(比如<link>、<img>、<button>这类)
对于这些元素的内联onclick/onload,直接用this就能精准拿到触发事件的元素本身!比如你用的<link>标签,完全可以这么写:
<link rel="stylesheet" media="none" onload="this.media='all'; this.removeAttribute('onload')" href="//fonts.googleapis.com/css?family=Open+Sans:300,400,600,700%7CPT+Sans+Narrow%7CSource+Sans+Pro:200,300,400,600,700,900&subset=all&display=swap" type="text/css">
这个代码亲测有效:this就是当前的<link>元素,执行完逻辑后会移除自身的onload属性,DevTools里就不会残留这个属性了。
2. <body>元素的特殊坑
你之前在<body>的onload里用this没生效,是因为**<body onload="...">里的this指向的是window,而不是<body>元素本身**——这是历史遗留的特性,早期window.onload是唯一的页面加载完成事件,<body>的onload只是它的别名而已。
如果要在<body>的内联onload里操作自身,有两种简单的方式:
- 直接用
document.body(最直观):<body onload="document.body.classList.add('loaded'); document.body.removeAttribute('onload')"> - 或者通过
event.target获取(需要把event传入):<body onload="(function(el){el.classList.add('loaded'); el.removeAttribute('onload')})(event.target)">
二、非阻塞加载样式的最优实现方案
你的需求是除了critical.css外,其他样式非阻塞加载,同时清理onload属性,这里有几个比内联事件更优雅的方案:
1. 优化版内联方案(适合快速改造现有代码)
把media="none"换成media="print"兼容性更好(有些旧浏览器不支持none),然后用this完成逻辑:
<link rel="stylesheet" media="print" onload="this.media='all'; this.removeAttribute('onload')" href="//fonts.googleapis.com/css?family=Open+Sans:...">
这个方案简单直接,改完就能用,而且能完美移除onload属性。
2. 分离式脚本方案(符合关注点分离,推荐)
如果不想让HTML里混着脚本逻辑,可以把处理逻辑写到单独的<script>里,批量处理所有非阻塞加载的样式:
<!-- 非阻塞加载的样式,先设media为print --> <link rel="stylesheet" media="print" href="//fonts.googleapis.com/css?family=Open+Sans:..."> <link rel="stylesheet" media="print" href="/path/to/other-style.css"> <script> // 批量处理所有标记为media="print"的样式标签 document.querySelectorAll('link[media="print"]').forEach(link => { link.onload = function() { this.media = 'all'; // 清理属性和事件监听,彻底干净 this.removeAttribute('media'); this.onload = null; }; }); </script>
这个方案的好处是HTML结构更干净,逻辑集中管理,就算有10个样式文件也不用一个个加内联事件,维护起来更方便。
3. Preload+动态创建link(性能最优,适合现代浏览器)
对于支持HTML5的现代浏览器,可以用rel="preload"预加载资源,然后在加载完成后动态创建<link>标签添加到页面,完全不会阻塞渲染:
<!-- 预加载样式资源,不会阻塞渲染 --> <link rel="preload" href="//fonts.googleapis.com/css?family=Open+Sans:..."> <link rel="preload" href="/path/to/other-style.css"> <script> document.querySelectorAll('link[rel="preload"]').forEach(preloadLink => { preloadLink.onload = function() { // 创建真正的样式标签 const styleLink = document.createElement('link'); styleLink.rel = 'stylesheet'; styleLink.href = this.href; document.head.appendChild(styleLink); // 移除预加载标签,彻底清理 this.remove(); }; }); </script>
这个方案的优势是预加载能更早触发资源请求,同时完全不阻塞页面渲染,性能更好,而且全程没有内联事件残留的问题。
最后总结一下
- 普通元素的内联事件里,
this就是触发元素;<body>的onload要特殊处理,用document.body最省心。 - 非阻塞加载样式的最优选择,推荐用分离式脚本批量处理或者preload+动态创建link,既满足功能需求,又让代码更易维护,还能彻底解决
onload属性残留的问题。
内容的提问来源于stack exchange,提问作者s3c

