jQuery append动态生成元素如何添加无值属性?不同写法效果是否一致?
两种async属性写法的等价性与有效性
async="async" 和裸写async完全等价,两种写法都能正常生效,没有任何功能差异。
这是HTML布尔属性的标准行为:对于async/defer/disabled/checked这类布尔属性,浏览器只判断属性是否存在,不关心属性的具体值——只要属性出现在标签上,不管值写的是async、true、false甚至是空字符串,都会被判定为开启状态。
jQuery生成async="async"的形式是正常现象:它内部调用标准DOM的setAttribute方法设置属性时,对布尔属性会默认用属性名作为属性值填充,完全符合W3C规范,不会改变脚本的异步加载行为。你可以在控制台读取任意一种写法生成的script节点的async属性,返回值都是true,GTM脚本会正常异步加载,不会阻塞页面解析。
变通写法与原写法的差异
你写的先插入元素、再通过prop()设置async的方案,最终功能和原写法完全一致,仅存在极其细微的时序差别,绝大多数场景下不会有任何可感知的影响。
两种写法的核心区别只有async属性的设置时机:
- 原写法是在script元素插入DOM树之前,就已经把async属性配置完成,元素插入的瞬间就带有async标识。
- 变通写法是先把不带async属性的script标签插入DOM,再追加设置async属性。
这里有个需要注意的边界:如果是没有src的内联脚本,插入DOM后再设置async是无效的,但你这里加载的是带外部地址的GTM脚本,插入后再设置async依然会被浏览器识别,按异步规则加载执行,不会出现同步阻塞的问题。
如果你既想要裸写async的标签形式,又想规避二次设置属性的时序问题,不需要额外加id做二次查询,创建元素的时候直接用prop()配置属性即可,参考代码:
const gtmScript = $("<script />"); gtmScript.prop("src", "https://www.googletagmanager.com/gtag/js?id=<?php echo $block->getGoogleTagManagerId(); ?>"); gtmScript.prop("async", true); $("body").append(gtmScript);
这种写法生成的标签就是你预期的不带属性值的async形式,属性在元素插入前就配置完成,和原生写在HTML里的标签行为完全一致。
内容的提问来源于stack exchange,提问作者Black

