43

トリガークラスを含むdivタグが変更されたときにイベントがトリガーされるようにしたいと思います。

クラスの追加イベントをリッスンさせる方法がわかりません。

<div id="test">test</div>

<script type="text/javascript">
    document.getElementById.setAttribute("class", "trigger");

    function workOnClassAdd() {
       alert("I'm triggered");
    }
</script>
4

5 に答える 5

64

未来はここにあり、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()
                    }
                }
            }
        }
    }
}
于 2018-12-24T13:28:20.547 に答える
27

ミューテーションイベントはありましたが、非推奨になり、将来的にはミューテーションオブザーバーが登場しますが、長い間完全にはサポートされません。では、その間に何ができるでしょうか?

タイマーを使用して要素をチェックできます。

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

于 2012-05-16T04:51:51.580 に答える
19

クラス属性の変更でコールバックをトリガーする方法の簡単で基本的な例を次に示します
MutationObserverAPI

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>

于 2020-06-18T12:25:47.693 に答える
3

この関数を使用して、要素が変更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>

于 2021-12-18T15:08:39.113 に答える
0

プロジェクトのクラス更新リスナーが必要だったので、これを作成しました。最終的には使用しなかったため、完全にはテストされていませんが、Element.classListDOMTokenListをサポートするブラウザーでは問題ないはずです。

ボーナス:たとえば、サポートされている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')
于 2021-08-26T06:55:27.637 に答える