【问题标题】:error while using custom html property tags使用自定义 html 属性标签时出错
【发布时间】: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]

标签: javascript html


【解决方案1】:

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

  • 您应该使用 HTML5 的 data-* 属性来存储自定义数据,而不是定义您自己的标准外观属性。
    • 我假设trig 是“触发器”的缩写,它是运行时定义的事件名称。
    • 我假设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://stackoverflow.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://stackoverflow.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://stackoverflow.com/questions/70011022/is-there-a-difference-between-and-is-not-in-c/70011062#70011062" data-event-name="contextmenu">Navigate on right-click</b>

这是一个使用 StackOverflow 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>.
    // StackOverflow snippets cannot use `window.open`.
    
//  document.getElementById('demoIFrame').src = href;
    document.getElementById('demoOutput').textContent = href;
}
<b data-href="https://stackoverflow.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://stackoverflow.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://stackoverflow.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" width="500" height="500" border="1"></iframe>-->
<output id="demoOutput"></output>

【讨论】:

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