不在DOM中的元素上的document.querySelector()吗? [英] document.querySelector() on elements not in DOM?

查看:365
本文介绍了不在DOM中的元素上的document.querySelector()吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用jQuery的网站上工作,但我试图不再使用它.在jQuery中,您可以在网站上尚未存在或尚未创建的元素上添加一个均匀的侦听器,这没有问题.当您登录时,我只有在DOM上的元素,并且整个网站只有一个JS文件.

I'm working on a website, with jQuery but I'm trying to not use it anymore. In jQuery you can add an even listener on a element that wasn't on the website or wasn't created yet and no problem. I have elements that are only on the DOM when you're logged in, and I only have one JS file for the whole website.

问题是例如,当您登录时看不到登录"按钮,它甚至不在DOM中,但它在代码中仍然具有事件侦听器,在控制台上没有错误,脚本运行良好.

Problem is, for example, when you're logged in you can't see the "log in" button, it's not even in the DOM, but it still have the event listener in the code, no error on the console, script runs well.

$("#logInButton").on("click", somefunction);

但是,使用document.querySelector("#logInButton").onclick = somefunction并且已经登录,由于document.querySelector("#logInButton")为空,它会引发错误.

But, using document.querySelector("#logInButton").onclick = somefunction and being logged in already, it throws an error because document.querySelector("#logInButton") is null.

我可以这样做:

let logInButton = document.querySelector("#logInButton");

logInButton ? logInButton.onclick = somefunction : "";

效果很好,但是我知道这不是一个好习惯.是否有任何变通方法或改进措施,而不使用jQuery?

And it works well, but I know it's not a good practice. Any workaround or improvement to that, not using jQuery?

如果发生了什么,JSFiddle. (请参阅控制台)

推荐答案

效果很好,但是我知道这不是一个好习惯.

And it works well, but I know it's not a good practice.

如果在页面上具有#logInButton是可选的,则这是一种很好的做法 —而不是使用onclick而不是addEventListener(但这可能是样式问题).自然地,您会在文档的 end 链接的脚本中,将代码放在</body>标记之前(或通过DOMContentLoaded回调触发).

If having #logInButton on the page is optional, that's perfectly good practice — other than using onclick rather than addEventListener (but that's probably a matter of style). Naturally, you'd have this code in a script linked at the end of the document, just prior to the </body> tag (or trigger it via a DOMContentLoaded callback).

但是,如果您想要与jQuery等效,则需要考虑jQuery的基于集合"的思维方式,并使用querySelectorAll:

But if you want the equivalent of the jQuery, you need to think in jQuery's "set-based" mindset and use querySelectorAll:

// Not very efficient
document.querySelectorAll("#logInButton").forEach(function() {
    // Set up the handler here using `this`
});

除了jQuery使用#id格式优化查询以进行getElementById调用(动态地 更快),然后使用if(与您的一样)来构建带有任何一个的集合元素或零.

Except that jQuery optimizes queries using #id format to a getElementById call (which is dramatically faster) and then uses an if (like yours) to build the set with either one element or zero.

也许您在尝试不使用jQuery时,可能会给自己一些辅助函数来代替它,因为DOM API非常冗长.如果您喜欢jQuery的基于集合的性质,则甚至可以使它们基于集合:

Perhaps in your quest to not use jQuery, you might give yourself a couple of helper functions to take its place, as the DOM API is quite verbose. If you like jQuery's set-based nature, you might even make them set-based:

function MyQuery(selector) {
    if (!selector) {
        this.data = [];
    } else if (typeof selector === "string") {
        // (jQuery takes it further than this, search in an unminified version for `rquickExpr`)
        var id = /#([\w-]+)/.match(selector);
        if (id) {
            var e = document.getElementById(id[0]);
            this.data = e ? [e] : [];
        } else {
            this.data = Array.from(document.querySelector(selector));
        }
    } else {
        /* ...handle other things, such as DOM elements or arrays of them...? */
        this.data = /*...*/;
    }
}
MyQuery.prototype = {
    constructor: MyQuery,
    on: function(eventName, handler) {
        this.data.forEach(function(element) {
            element.addEventListener(eventName, handler);
        });
        return this;
    }
    // ...etc...
};
function qset(selector) {
    return new MyQuery(selector);
}

然后

qset("#logInButton").on("click", /*...*/);

当然,您可能会发现自己基本上在重新创建jQuery.但是如果保持精简...

Of course, you might find yourself basically recreating jQuery. But if you keep it lean...

侧面说明:在querySelectorAll的返回值上使用forEach需要最新的浏览器,或者您要对其进行填充:

Side note: Using forEach on the return value of querySelectorAll requires an up-to-date browser, or that you polyfill it:

if (typeof NodeList !== "undefined" &&
    NodeList.prototype &&
    !NodeList.prototype.forEach) {
    Object.defineProperty(NodeList.prototype, "forEach", {
        value: Array.prototype.forEach
    });
}

对于真正淘汰的浏览器(例如IE8),您必须首先填充Array.prototype.forEach.

For truly obsolete browsers (like IE8), you'd have to polyfill Array.prototype.forEach first.

这篇关于不在DOM中的元素上的document.querySelector()吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆