我正在使用 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 的话,有什么解决方法或改进吗?
最佳答案
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/