[英]Event trigger on a class change
我希望在更改包含触发器class 的 div 标签时触发我的事件。
我不知道如何让它监听班级的添加事件。
<div id="test">test</div>
<script type="text/javascript">
document.getElementById.setAttribute("class", "trigger");
function workOnClassAdd() {
alert("I'm triggered");
}
</script>
未来就在这里,您可以使用MutationObserver接口来监视特定的类更改。
let targetNode = document.getElementById('test')
function workOnClassAdd() {
alert("I'm triggered when the class is added")
}
function workOnClassRemoval() {
alert("I'm triggered when the class is removed")
}
// watch for a specific class change
let classWatcher = new ClassWatcher(targetNode, 'trigger', workOnClassAdd, workOnClassRemoval)
// tests:
targetNode.classList.add('trigger') // triggers workOnClassAdd callback
targetNode.classList.add('trigger') // won't trigger (class is already exist)
targetNode.classList.add('another-class') // won't trigger (class is not watched)
targetNode.classList.remove('trigger') // triggers workOnClassRemoval callback
targetNode.classList.remove('trigger') // won't trigger (class was already removed)
targetNode.setAttribute('disabled', true) // won't trigger (the class is unchanged)
我用一个简单的类包装了MutationObserver :
class ClassWatcher {
constructor(targetNode, classToWatch, classAddedCallback, classRemovedCallback) {
this.targetNode = targetNode
this.classToWatch = classToWatch
this.classAddedCallback = classAddedCallback
this.classRemovedCallback = classRemovedCallback
this.observer = null
this.lastClassState = targetNode.classList.contains(this.classToWatch)
this.init()
}
init() {
this.observer = new MutationObserver(this.mutationCallback)
this.observe()
}
observe() {
this.observer.observe(this.targetNode, { attributes: true })
}
disconnect() {
this.observer.disconnect()
}
mutationCallback = mutationsList => {
for(let mutation of mutationsList) {
if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
let currentClassState = mutation.target.classList.contains(this.classToWatch)
if(this.lastClassState !== currentClassState) {
this.lastClassState = currentClassState
if(currentClassState) {
this.classAddedCallback()
}
else {
this.classRemovedCallback()
}
}
}
}
}
}
嗯,有突变事件,但它们已被弃用,未来会有突变观察者,但在很长一段时间内不会得到完全支持。 那么在此期间你能做什么呢?
您可以使用计时器来检查元素。
function addClassNameListener(elemId, callback) {
var elem = document.getElementById(elemId);
var lastClassName = elem.className;
window.setInterval( function() {
var className = elem.className;
if (className !== lastClassName) {
callback();
lastClassName = className;
}
},10);
}
运行示例: jsFiddle
这是一个简单的基本示例,说明如何在 Class 属性更改时触发回调
MutationObserver API
const attrObserver = new MutationObserver((mutations) => { mutations.forEach(mu => { if (mu.type !== "attributes" && mu.attributeName !== "class") return; console.log("class was modified!"); }); }); const ELS_test = document.querySelectorAll(".test"); ELS_test.forEach(el => attrObserver.observe(el, {attributes: true})); // Example of Buttons toggling several .test classNames document.querySelectorAll(".btn").forEach(btn => { btn.addEventListener("click", () => ELS_test.forEach(el => el.classList.toggle(btn.dataset.class))); });
.blue {background: blue;} .gold {color: gold;}
<div class="test">TEST DIV</div> <button class="btn" data-class="blue">BACKGROUND</button> <button class="btn" data-class="gold">COLOR</button>
我需要一个项目的类更新监听器,所以我做了这个。 我最终没有使用它,所以它没有经过全面测试,但在支持 Element.classList DOMTokenList 的浏览器上应该没问题。
奖励:允许“链接”4 个支持的方法,例如el.classList.remove(“inactive”).remove(“disabled”).add(“active”)
function ClassListListener( el ) {
const ecl = el.classList;
['add','remove','toggle','replace'].forEach(prop=>{
el.classList['_'+prop] = ecl[prop]
el.classList[prop] = function() {
const args = Array.from(arguments)
this['_'+prop].apply(this, args)
el.dispatchEvent(new CustomEvent(
'classlistupdate',
{ detail: { method: prop, args } }
))
return this
}
})
return el
}
用途:
const el = document.body
ClassListListener(el).addEventListener('classlistupdate', e => {
const args = e.detail.args.join(', ')
console.log('el.classList.'+e.detail.method+'('+args+')')
}, false)
el.classList
.add('test')
.replace('test', 'tested')
可以使用这个onClassChange
函数来观察元素的classList
何时发生变化
function onClassChange(element, callback) { const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { if ( mutation.type === 'attributes' && mutation.attributeName === 'class' ) { callback(mutation.target); } }); }); observer.observe(element, { attributes: true }); return observer.disconnect; } var itemToWatch = document.querySelector('#item-to-watch'); onClassChange(itemToWatch, (node) => { node.classList.contains('active') ? alert('class added') : alert('class removed'); node.textContent = 'Item to watch. classList: ' + node.className; }); function addClass() { itemToWatch.classList.add('active'); } function removeClass() { itemToWatch.classList.remove('active'); }
<div id="item-to-watch">Item to watch</div> <button onclick="addClass();">Add Class</button> <button onclick="removeClass();">Remove Class</button>
这个想法是用包装器替换 class 操作函数,例如“添加”、“删除”...,这些函数在 class 列表更改之前或之后发送 class 更改消息。 使用非常简单:
选择元素或选择元素的查询,并将其传递给 function。
将 'class-change' 和/或 'class-add'、'class-remove'... 处理程序添加到元素或其容器(例如,'document')。
之后,任何通过添加、删除、替换或切换方法更改的 class 列表都会触发相应的事件。
事件顺序为:
A) 'class-change' 请求事件被触发,如果需要,处理程序可以通过 preventDefault() 拒绝该事件。 如果被拒绝,则 class 更改将被取消。
B) class 更改 function 将被执行
B) 'class-add' 或 'class-remove'... 信息事件被触发。
function addClassChangeEventDispatcher( el )
{
// select or use multiple elements
if(typeof el === 'string') el = [...document.querySelectorAll( el )];
// process multiple elements
if(Array.isArray( el )) return el.map( addClassChangeEventDispatcher );
// process single element
// methods that are called by user to manipulate
let clMethods = ['add','remove','toggle','replace'];
// substitute each method of target element with wrapper that fires event after class change
clMethods.forEach( method =>
{
let f = el.classList[method];
el.classList[method] = function()
{
// prepare message info
let detail = method == 'toggle' ? { method, className: arguments[0] } :
method == 'replace' ? { method, className: arguments[0], newClassName: arguments[1] } :
{ method, className: arguments[0], classNames: [...arguments] };
// fire class change request, and if rejected, cancel class operation
if(!el.dispatchEvent( new CustomEvent( 'class-change', {bubbles: true, cancelable: true, detail} ))) return;
// call original method and then fire changed event
f.call( this, ...arguments );
el.dispatchEvent( new CustomEvent( 'class-' + method, {bubbles: true, detail} ));
};
});
return el;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.