使用自定义 html 属性标签时出错

Posted

技术标签:

【中文标题】使用自定义 html 属性标签时出错【英文标题】:error while using custom html property tags 【发布时间】:2022-01-15 14:46:09 【问题描述】:

我正在尝试使我的项目中的每个 html 元素都可点击。当它被点击时,它应该带我到另一个网页(other.html) 我的 JS:


let objs = document.querySelectorAll( 'body *' );
console.log(objs)
Array.from(objs).map(x => 
if (x.hasAttribute('loc') && x.hasAttribute('trig'))
let loc = x.getAttribute('loc')
let trig = x.getAttribute('trig')
let functionAtLast = function() location.href = loc
x.addEventListener(trig, functionAtLast)


)

我的 HTML:

<b loc = 'other.html' act = 'click'>hi</b>

当我点击粗体文本时,什么也没有发生。

我在这里做错了什么?

【问题讨论】:

“我试图让我的项目中的每个 HTML 元素都可以点击” - 为什么?这听起来是个坏主意,因为并非每个 HTML 元素都是可交互的(例如 &lt;script&gt;&lt;noscript&gt;&lt;style&gt; 等) 自定义属性应该写成data-。见Using data attributes。什么都没有发生或您收到错误消息?如果是后者,错误是什么? map 是一个返回新数组的 FP 风格的函数,它不等同于 forEach 属性是trig还是act 您应该将选择器更改为body *[log][trig] 【参考方案1】:

map 不应用于变异 数组元素 - 也不打算 用于迭代数组。为此,您应该使用for( of )(也不要使用.forEach 方法)。

您应该使用 HTML5 的 data-* 属性来存储自定义数据,而不是定义您自己的标准外观属性。 我假设trig 是“触发器”的缩写,它是运行时定义的事件名称。 我已将其更改为 data-event-name。 您可以通过HTMLElement.dataset['eventName'] 获取值。 dataset automatically converts - in HTML attribute names to camelCase,所以您不需要需要执行 `getAttribute("data-event-name")。 我假设loc 是“位置”的缩写,基本上是href URI。我已将其更改为 data-href

像这样:

function setupClickableEverything() 
    const allBodyElementsWithAttribs = document.querySelectorAll( 'body *[data-event-name][data-href]' );
    for( const el of allBodyElementsWithAttribs ) 
        const eventName = el.dataset['eventName'];
        el.addEventListener( eventName, setWindowLocationToDataSetHref );
    


window.addEventListener( 'DOMContentLoaded', setupClickableEverything );

function setWindowLocationToDataSetHref( e ) 
    
    const el   = e.currentTarget;
    const href = el.dataset['href'];
    window.location = href;

示例 HTML:

<b data-href="https://***.com/questions/51390971/im-lost-what-happened-to-asp-net-mvc-5/51391202#51391202" data-event-name="click">Navigate on click</b>
<br />
<b data-href="https://***.com/questions/15305278/how-to-check-if-a-string-contains-a-specific-text/15305313#15305313" data-event-name="mousedown">Navigate on mousedown</b>
<br />
<b data-href="https://***.com/questions/70011022/is-there-a-difference-between-and-is-not-in-c/70011062#70011062" data-event-name="contextmenu">Navigate on right-click</b>

这是一个使用 *** sn-p 稍作修改的演示。 由于 SO 对 Snippets 施加的 CSP,下面的演示无法导航、打开弹出窗口或将内容加载到 &lt;iframe&gt;,但它仍然展示了它的工作原理原则

function setupClickableEverything() 

    const allBodyElementsWithAttribs = document.querySelectorAll( 'body *[data-event-name][data-href]' );

    for( const el of allBodyElementsWithAttribs ) 
        
        const eventName = el.dataset['eventName'];
    //  const href      = el.dataset['href'];
        el.addEventListener( eventName, setWindowLocationToDataSetHref );
    


window.addEventListener( 'DOMContentLoaded', setupClickableEverything );

function setWindowLocationToDataSetHref( e ) 
    
    const el   = e.currentTarget;
    const href = el.dataset['href'];
    //window.location = href;
    // To avoid breaking this demo, links are opened in the <iframe>.
    // *** snippets cannot use `window.open`.
    
//  document.getElementById('demoIFrame').src = href;
    document.getElementById('demoOutput').textContent = href;
<b data-href="https://***.com/questions/51390971/im-lost-what-happened-to-asp-net-mvc-5/51391202#51391202" data-event-name="click">Navigate on click</b>

<br />

<b data-href="https://***.com/questions/15305278/how-to-check-if-a-string-contains-a-specific-text/15305313#15305313" data-event-name="mousedown">Navigate on mousedown</b>

<br />

<b data-href="https://***.com/questions/70011022/is-there-a-difference-between-and-is-not-in-c/70011062#70011062" data-event-name="contextmenu">Navigate on right-click</b>

<hr />

<!-- To avoid breaking this demo, links are NOT actually opened, just shown in the <output> element below. I tried to make it work using an <iframe> but the CSP on SO prevents that. Note that SO snippets are blocked from using `window.open` too.  -->
<!--<iframe id="demoIFrame"   border="1"></iframe>-->
<output id="demoOutput"></output>

【讨论】:

次要吹毛求疵:“事件名称”不是更常用的称为事件type吗? @SebastianSimon 您在技术上是正确的 (the best kind of correct) 但是在 MDN 的准权威文档中,他们交替使用术语“名称”和“类型”,并且考虑到 OP 对 JS 和 DOM 我来说似乎是新的想要使用更容易理解的术语。 我正在尝试这个,但它不起作用。没有错误,但是当我点击文本时,什么也没有发生。 @JSst67 你用过你的调试器吗?您是否确保脚本仅在 DOMContentLoadedDOMContentLoaded 之后运行? @JSst67 我已经更新了我的答案以包含一个工作示例(尽管由于 SO sn-ps 的安全限制,实际上没有导航到任何地方)。

以上是关于使用自定义 html 属性标签时出错的主要内容,如果未能解决你的问题,请参考以下文章

自定义包含标签出错,找不到文件

自定义HTML标签属性

HTML5的自定义属性的使用总结

怎么在html中写自定义freemaker标签

如何使用自定义 html 消息在出错时退出 php

js 自定义html标签属性