有多个按钮。
按钮按钮必须更改其样式/类三次,而不更改其他按钮的样式。
var bt = document.getElementById('b1');
var cl = ['cls cls1', 'cls cls2', 'cls cls3'];
var current = 0;
bt.addEventListener ('click', function() {
current++;
current %= cl.length;
bt.className = cl[current];
});
.cls {margin:10px 0; padding:3px 30px;
border:1px solid gray; outline:0; cursor:pointer;}
.cls1 {background:gold;}
.cls2 {background:aqua;}
.cls3 {background:lime;}
<button class="cls cls1" id="b1">b1</button>
<button class="cls cls1" id="">b2</button>
<button class="cls cls1" id="">b3</button>
fiddle example 但适用于一个按钮'b1'逐个id。
如何通过id修改所有按钮的示例?
有没有一种方法没有id,纯粹的javascript上课? 谢谢。
通过使用getElementById()
,您只定位一个按钮,并将特定的id
作为参数传递。
要将event
附加到所有按钮,您必须先选择所有按钮。你可以使用querySelectorAll()
。然后使用forEach()
循环每个按钮并附加event
。
Element方法querySelectorAll()返回一个静态(非实时)NodeList,表示与指定的选择器组匹配的文档元素列表。
forEach()方法为每个数组元素执行一次提供的函数。
工作守则:
var bt = document.querySelectorAll('.cls.cls1');
var cl = ['cls cls1', 'cls cls2', 'cls cls3'];
bt.forEach(function(b){
var current = 0;
b.addEventListener ('click', function() {
current++;
current %= cl.length;
b.className = cl[current];
});
});
.cls {margin:10px 0; padding:3px 30px;
border:1px solid gray; outline:0; cursor:pointer;}
.cls1 {background:gold;}
.cls2 {background:aqua;}
.cls3 {background:lime;}
<button class="cls cls1" id="b1">b1</button>
<button class="cls cls1" id="">b2</button>
<button class="cls cls1" id="">b3</button>
请注意:querySelectorAll()
有一些浏览器问题。在这种情况下,您可以使用getElementsByClassName()
尝试以下方式:
var bt = document.getElementsByClassName('cls');
var cl = ['cls cls1', 'cls cls2', 'cls cls3'];
[].forEach.call(bt, function(b){
var current = 0;
b.addEventListener ('click', function() {
current++;
current %= cl.length;
b.className = cl[current];
});
});
.cls {margin:10px 0; padding:3px 30px;
border:1px solid gray; outline:0; cursor:pointer;}
.cls1 {background:gold;}
.cls2 {background:aqua;}
.cls3 {background:lime;}
<button class="cls cls1" id="b1">b1</button>
<button class="cls cls1" id="">b2</button>
<button class="cls cls1" id="">b3</button>
这很简单:只需使用document.querySelectorAll('.cls')
选择所有按钮,然后遍历NodeList集合并将click事件监听器附加到每个按钮:
var buttons = document.querySelectorAll('.cls');
var cl = ['cls cls1', 'cls cls2', 'cls cls3'];
Array.prototype.slice.call(buttons).forEach(function(button) {
// Each button should have its own store for the current index
var current = 0;
// Add event listener
button.addEventListener('click', function() {
current++;
current %= cl.length;
button.className = cl[current];
});
});
这样,您就不必担心为要应用此行为的所有按钮分配唯一ID。
笔记:
Array.prototype.slice.call(<NodeList>)
,因为NodeList
返回的document.querySelectorAll
本身不是数组。这样做会将它转换为一个数组,你可以使用.forEach
:)var current = 0
移动到循环中。概念验证示例:
var buttons = document.querySelectorAll('.cls');
var cl = ['cls cls1', 'cls cls2', 'cls cls3'];
Array.prototype.slice.call(buttons).forEach(function(button) {
// Each button should have its own store for the current index
var current = 0;
// Add event listener
button.addEventListener('click', function() {
current++;
current %= cl.length;
button.className = cl[current];
});
});
.cls {
color: white;
}
.cls1 {
background-color: red;
}
.cls2 {
background-color: green;
}
.cls3 {
background-color: blue;
}
<button class="cls cls1" id="b1">b1</button>
<button class="cls cls1" id="">b2</button>
<button class="cls cls1" id="">b3</button>
如果你在ES6中写作很舒服,它会变得更好:
const buttons = document.querySelectorAll('.cls');
const cl = ['cls cls1', 'cls cls2', 'cls cls3'];
Array.from(buttons).forEach((button) => {
// Each button should have its own store for the current index
let current = 0;
// Add event listener
button.addEventListener('click', () => {
current++;
current %= cl.length;
button.classList = cl[current];
});
});
.cls {
color: white;
}
.cls1 {
background-color: red;
}
.cls2 {
background-color: green;
}
.cls3 {
background-color: blue;
}
<button class="cls cls1" id="b1">b1</button>
<button class="cls cls1" id="">b2</button>
<button class="cls cls1" id="">b3</button>
而不是id
,在querySelectorAll
中使用tagname并使用forEach
进行迭代(大多数逻辑保持相同)
var btns = document.querySelectorAll('button');
var cl = ['cls cls1', 'cls cls2', 'cls cls3'];
var current = 0;
Array.from(btns).forEach(bt => bt.addEventListener('click', function(e) {
current++;
current %= cl.length;
e.currentTarget.className = cl[current];
}));
演示
var btns = document.querySelectorAll('button');
var cl = ['cls cls1', 'cls cls2', 'cls cls3'];
var current = 0;
Array.from(btns).forEach(bt => bt.addEventListener('click', function(e) {
current++;
current %= cl.length;
e.currentTarget.className = cl[current];
}));
.cls1
{
background-color: red;
}
.cls2
{
background-color: blue;
}
.cls3
{
background-color: green;
}
<button class="cls cls1" id="b1">b1</button>
<button class="cls cls1" id="">b2</button>
<button class="cls cls1" id="">b3</button>
这里有四个概念可以帮到你:
1)您可以向元素询问其当前类,而不是使用计数器来跟踪状态。这样每个按钮都可以跟踪自己的状态,而不是每个按钮需要一个变量。
2)事件可能会冒泡。因此,如果您将单击处理程序放置在按钮的包装元素上,则所有按钮都将使用相同的事件,因此您只需添加所需数量的按钮,而无需为每个按钮添加事件。
3)所有事件在其回调中都有一个event
参数。通过使用event.target
,您可以直接引用所单击的元素。
4)所有元素都有一个classList对象,您可以使用它来检查有关其CSS类的各种事物。
因此,如果我们将这些结合起来,我们最终会得到这样的结果:
const DEFAULT_CLASSES = [ 'cls1', 'cls2', 'cls3' ];
document.querySelector( '#comp_buttons' ).addEventListener( 'click', event => {
if ( event.target.nodeName === 'BUTTON' ) {
const button = event.target;
const cls_current = DEFAULT_CLASSES.find( cls => button.classList.contains( cls ) );
const cls_index = DEFAULT_CLASSES.indexOf( cls_current );
const cls_next = DEFAULT_CLASSES[ cls_index + 1 ] || DEFAULT_CLASSES[ 0 ];
button.classList.replace( cls_current, cls_next );
}
} );
.cls {
color: white;
}
.cls1 {
background-color: red;
}
.cls2 {
background-color: green;
}
.cls3 {
background-color: blue;
}
.cls4 {
background-color: yellow;
}
<div id="comp_buttons">
<button class="cls cls1">b1</button>
<button class="cls cls1">b2</button>
<button class="cls cls1">b3</button>
</div>
这种方法的最大优点是可以在div中添加任意数量的按钮,而无需更改事件处理程序。
您也可以添加任意数量的类,只要在css中定义类并将其名称放入DEFAULT_CLASSES数组中即可。这些类现在甚至可以有随机名称,sicne我们不依赖于计数器或数字来标识按钮的当前类。