javascript - document.querySelector() 对不在 DOM 中的元素?

标签 javascript jquery html

我正在使用 jQuery 开发一个网站,但我试图不再使用它。在 jQuery 中,您可以在不在网站上或尚未创建的元素上添加偶数监听器,这没有问题。我的元素仅在您登录时出现在 DOM 上,而且整个网站只有一个 JS 文件。

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

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

但是,使用 document.querySelector("#logInButton").onclick = somefunction 并且已经登录,它会抛出错误,因为 document.querySelector("#logInButton") 为空。

我可以这样做:

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

logInButton ? logInButton.onclick = somefunction : "";

效果很好,但我知道这不是一个好的做法。不使用 jQuery 的话,有什么解决方法或改进吗?

JSFiddle if what happens. (See console)

最佳答案

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

如果有#logInButton页面上的 是可选的,这是非常好的做法 - 除了使用 onclick而不是addEventListener (但这可能是风格问题)。当然,您可以将此代码放在链接到文档末尾的脚本中,就在 </body> 之前。标签(或通过DOMContentLoaded回调触发它)。

<小时/>

但是如果您想要 jQuery 的等价物,您需要以 jQuery 的“基于集合”的思维方式进行思考并使用 querySelectorAll :

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

除了 jQuery 使用 #id 优化查询格式为 getElementById调用(显着更快),然后使用 if (就像你的一样)用一个元素或零个元素构建集合。

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

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。但如果你保持精益......

<小时/>

旁注:使用forEach关于 querySelectorAll 的返回值需要最新的浏览器,或者您需要填充它:

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

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

关于javascript - document.querySelector() 对不在 DOM 中的元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46267161/

相关文章:

javascript - 使用 css 或 js 以一定倾斜 Angular 或椭圆形状旋转对象 360 度

php - 如何在一个php标签中定义的变量在另一个php标签中使用?

javascript - 无法使用 Jquery 从 Api 接收 Json 响应

javascript - jquery 解析具有无限子级类别的 xml

javascript - jQuery : swap two value and change style

javascript - 从许多相同的元素中单击时更改 HTML 选择标签

javascript - IE 与 Firefox 链接(哈希与 htm5)

javascript - jQuery - 添加图标以根据值选择选项

javascript - 在移动设备上查看主页不使用 jquery 重定向

html - 最后一个元素打破了绝对位置的所有 sibling