如何在Javascript中动态声明选择器?
How to declare selectors dynamically in Javascript?
我有重复的变量声明,我认为它们可以用 for 循环改进,但我的尝试失败了。
我尝试了数组的 for 循环声明器,但我的语法不起作用。
我有这个 "Working code":
<div class ="menu1 item1-1"></div>
<div class ="menu1 item1-2"></div>
<div class ="menu1 item1-3"></div>
<div class ="menu1 item1-4"></div>
<div class ="menu2 item2-1"></div>
<div class ="menu2 item2-2"></div>
<div class ="menu2 item2-3"></div>
<div class ="menu2 item2-4"></div>
<div class ="menu3 item3-1"></div>
<div class ="menu3 item3-2"></div>
<div class ="menu3 item3-3"></div>
<div class ="menu3 item3-4"></div>
<div class ="menu4 item4-1"></div>
<div class ="menu4 item4-2"></div>
<div class ="menu4 item4-3"></div>
<div class ="menu4 item4-4"></div>
var menu1 = document.getElementsByClassName('menu1');
var menu2 = document.getElementsByClassName('menu2');
var menu3 = document.getElementsByClassName('menu3');
var menu4 = document.getElementsByClassName('menu4');
for (let i = 1; i < menu1.length; i++) {
menu1[i].addEventListener('click', function(){ menu1[i].classList.add("test"); });
}
for (let i = 1; i < menu2.length; i++) {
menu2[i].addEventListener('click', function(){ menu2[i].classList.add("test"); });
}
for (let i = 1; i < menu3.length; i++) {
menu3[i].addEventListener('click', function(){ menu3[i].classList.add("test"); });
}
for (let i = 1; i < menu4.length; i++) {
menu4[i].addEventListener('click', function(){ menu4[i].classList.add("test"); });
}
我试图减少它是这样的:
var MENU = [];
for (let i = 1; i <= 4; i++) {
MENU.push("menu" + i + =document.getElementsByClassName('menu' + i +));
}
for (let j = 1; j < 5; j++) {
for (let i = 0; i < MENU[j].length; i++) {
MENU[j][i].addEventListener('click', function(){ MENU[j][i].classList.add("test"); });
}
}
预期结果:
与 "Working code" 相同的结果:
当我点击 "menu1" div:
<div class ="menu1 item1-1 test"></div>
<div class ="menu1 item1-2 test"></div>
<div class ="menu1 item1-3 test"></div>
<div class ="menu1 item1-4 test"></div>
<div class ="menu2 item2-1"></div>
<div class ="menu2 item2-2"></div>
<div class ="menu2 item2-3"></div>
<div class ="menu2 item2-4"></div>
<div class ="menu3 item3-1"></div>
<div class ="menu3 item3-2"></div>
<div class ="menu3 item3-3"></div>
<div class ="menu3 item3-4"></div>
<div class ="menu4 item4-1"></div>
<div class ="menu4 item4-2"></div>
<div class ="menu4 item4-3"></div>
<div class ="menu4 item4-4"></div>
实际错误信息:
"Unexpected token ="
"Uncaught TypeError: MENU[0][i].addEventListener is not a function"
编辑:我发现了巨大的语法错误,已修复,但我现在收到此错误。
Edit2:我的问题过于开放且不具体,我缩小了范围并更正了评论建议的一些语法。
Edit3:我正在尝试:
单击一个 "menu1" 元素以 select 所有 "menu1" 元素。
单击一个 "menu2" 元素到 select 所有 "menu2" 元素。
单击一个 "menu3" 元素到 select 所有 "menu3" 元素。
单击 "menu4" 元素到 select 所有 "menu4" 元素。
你为什么不给他们另一个特殊的属性就像<div class="whatever" specialAttribute>Some Html content</div>
一样?然后像 const selectors=document.querySelectorAll("[specialAttribute]");
一样使用选择器
如果您将项目分配到索引中的顺序位置,那就容易多了。
MENU[i] = document.getElementsByClassName('menu" + i);
那么MENU[1]就是第一个元素的引用,等等
你不应该推送字符串,只推送调用函数的结果。
MENU.push(document.getElementsByClassName('menu' + i));
请注意,数组索引从 0
开始。所以 MENU[0]
将包含具有 class menu1
的元素,依此类推。
向每个 menu
或 panl
等添加一个通用 class,例如:menu
。这样您的元素看起来像:
<div class="menu menu1"></div>
<div class="menu menu2"></div>
<div class="menu menu3"></div>
<div class="menu menu4"></div>
现在您可以 select 使用单个 selector.
的所有元素
var menus = document.getElementsByClassName('menu');
console.log(menus[0]); // <div class="menu menu1"></div>
console.log(menus[1]); // <div class="menu menu2"></div>
console.log(menus[2]); // <div class="menu menu3"></div>
console.log(menus[3]); // <div class="menu menu4"></div>
并且它们存储在 HTMLCollection
中,您可以使用 for
循环对其进行循环。
for (var i = 0; i < menus.length; i++) {
console.log(menus[i]); // Logs each <div class="menu"> element.
}
检查 the documentation of MDN 以查看有关如何使用 getElementsByClassName
方法的更多示例。
您可以使用 querySelectorAll
.
像这样:
const selector = '';
for (let i = 1; i <= 4; i++) {
selector += `${selector ? ', ' : ''}menu${i}, panel${i}, navprev${i}, navrtrn${i}, navnext${i}`
}
document.querySelectorAll(selector).forEach(element => {
element.addEventListener('click', (event) => {
// check if it is a menu:
if (event.target.matches('[class^=menu]')) {
// a menu was clicked
}
});
});
如果您不想更改任何其他代码,可以这样做:
const classNamePrefixes = ['menu', 'panel', 'navprev', 'navrtrn', 'navnext'];
const varNameAndClassNamePrefix = classNamePrefixes.map((cnp) => {
const varName = cnp.replace('nav', '').replace('panel', 'panl');
return {
varName,
cnp
};
});
for (let i = 1; i <= 4; i++) {
varNameAndClassNamePrefix.forEach(({ varName, cnp }) => {
window[`${varName}${i}`] = document.getElementsByClassName(`${cnp}${i}`)
});
}
我有重复的变量声明,我认为它们可以用 for 循环改进,但我的尝试失败了。
我尝试了数组的 for 循环声明器,但我的语法不起作用。
我有这个 "Working code":
<div class ="menu1 item1-1"></div>
<div class ="menu1 item1-2"></div>
<div class ="menu1 item1-3"></div>
<div class ="menu1 item1-4"></div>
<div class ="menu2 item2-1"></div>
<div class ="menu2 item2-2"></div>
<div class ="menu2 item2-3"></div>
<div class ="menu2 item2-4"></div>
<div class ="menu3 item3-1"></div>
<div class ="menu3 item3-2"></div>
<div class ="menu3 item3-3"></div>
<div class ="menu3 item3-4"></div>
<div class ="menu4 item4-1"></div>
<div class ="menu4 item4-2"></div>
<div class ="menu4 item4-3"></div>
<div class ="menu4 item4-4"></div>
var menu1 = document.getElementsByClassName('menu1');
var menu2 = document.getElementsByClassName('menu2');
var menu3 = document.getElementsByClassName('menu3');
var menu4 = document.getElementsByClassName('menu4');
for (let i = 1; i < menu1.length; i++) {
menu1[i].addEventListener('click', function(){ menu1[i].classList.add("test"); });
}
for (let i = 1; i < menu2.length; i++) {
menu2[i].addEventListener('click', function(){ menu2[i].classList.add("test"); });
}
for (let i = 1; i < menu3.length; i++) {
menu3[i].addEventListener('click', function(){ menu3[i].classList.add("test"); });
}
for (let i = 1; i < menu4.length; i++) {
menu4[i].addEventListener('click', function(){ menu4[i].classList.add("test"); });
}
我试图减少它是这样的:
var MENU = [];
for (let i = 1; i <= 4; i++) {
MENU.push("menu" + i + =document.getElementsByClassName('menu' + i +));
}
for (let j = 1; j < 5; j++) {
for (let i = 0; i < MENU[j].length; i++) {
MENU[j][i].addEventListener('click', function(){ MENU[j][i].classList.add("test"); });
}
}
预期结果:
与 "Working code" 相同的结果:
当我点击 "menu1" div:
<div class ="menu1 item1-1 test"></div>
<div class ="menu1 item1-2 test"></div>
<div class ="menu1 item1-3 test"></div>
<div class ="menu1 item1-4 test"></div>
<div class ="menu2 item2-1"></div>
<div class ="menu2 item2-2"></div>
<div class ="menu2 item2-3"></div>
<div class ="menu2 item2-4"></div>
<div class ="menu3 item3-1"></div>
<div class ="menu3 item3-2"></div>
<div class ="menu3 item3-3"></div>
<div class ="menu3 item3-4"></div>
<div class ="menu4 item4-1"></div>
<div class ="menu4 item4-2"></div>
<div class ="menu4 item4-3"></div>
<div class ="menu4 item4-4"></div>
实际错误信息: "Unexpected token =" "Uncaught TypeError: MENU[0][i].addEventListener is not a function"
编辑:我发现了巨大的语法错误,已修复,但我现在收到此错误。
Edit2:我的问题过于开放且不具体,我缩小了范围并更正了评论建议的一些语法。
Edit3:我正在尝试:
单击一个 "menu1" 元素以 select 所有 "menu1" 元素。 单击一个 "menu2" 元素到 select 所有 "menu2" 元素。 单击一个 "menu3" 元素到 select 所有 "menu3" 元素。 单击 "menu4" 元素到 select 所有 "menu4" 元素。
你为什么不给他们另一个特殊的属性就像<div class="whatever" specialAttribute>Some Html content</div>
一样?然后像 const selectors=document.querySelectorAll("[specialAttribute]");
如果您将项目分配到索引中的顺序位置,那就容易多了。
MENU[i] = document.getElementsByClassName('menu" + i);
那么MENU[1]就是第一个元素的引用,等等
你不应该推送字符串,只推送调用函数的结果。
MENU.push(document.getElementsByClassName('menu' + i));
请注意,数组索引从 0
开始。所以 MENU[0]
将包含具有 class menu1
的元素,依此类推。
向每个 menu
或 panl
等添加一个通用 class,例如:menu
。这样您的元素看起来像:
<div class="menu menu1"></div>
<div class="menu menu2"></div>
<div class="menu menu3"></div>
<div class="menu menu4"></div>
现在您可以 select 使用单个 selector.
的所有元素var menus = document.getElementsByClassName('menu');
console.log(menus[0]); // <div class="menu menu1"></div>
console.log(menus[1]); // <div class="menu menu2"></div>
console.log(menus[2]); // <div class="menu menu3"></div>
console.log(menus[3]); // <div class="menu menu4"></div>
并且它们存储在 HTMLCollection
中,您可以使用 for
循环对其进行循环。
for (var i = 0; i < menus.length; i++) {
console.log(menus[i]); // Logs each <div class="menu"> element.
}
检查 the documentation of MDN 以查看有关如何使用 getElementsByClassName
方法的更多示例。
您可以使用 querySelectorAll
.
像这样:
const selector = '';
for (let i = 1; i <= 4; i++) {
selector += `${selector ? ', ' : ''}menu${i}, panel${i}, navprev${i}, navrtrn${i}, navnext${i}`
}
document.querySelectorAll(selector).forEach(element => {
element.addEventListener('click', (event) => {
// check if it is a menu:
if (event.target.matches('[class^=menu]')) {
// a menu was clicked
}
});
});
如果您不想更改任何其他代码,可以这样做:
const classNamePrefixes = ['menu', 'panel', 'navprev', 'navrtrn', 'navnext'];
const varNameAndClassNamePrefix = classNamePrefixes.map((cnp) => {
const varName = cnp.replace('nav', '').replace('panel', 'panl');
return {
varName,
cnp
};
});
for (let i = 1; i <= 4; i++) {
varNameAndClassNamePrefix.forEach(({ varName, cnp }) => {
window[`${varName}${i}`] = document.getElementsByClassName(`${cnp}${i}`)
});
}