javascript - Is there any way to observe all data attributes in a custom component? - Stack Overflow

I'm trying to use vanilla javascript to build a custom ponent which observes changes in all data a

I'm trying to use vanilla javascript to build a custom ponent which observes changes in all data attributes, e.g.:

class MyComponent extends HTMLElement {

  static get observedAttributes () {
      return ["data-one","data-two","data-three",so forth...]
  }

}

This ponent could in theory be assigned an arbitrary number of data attributes, so there's no way to predict exactly how many there would be, yet I need the ponent to do stuff every time a new data attribute is assigned to it, is there any way to do it? having to put into the array returned by "observedAttributes" the specific name of every attribute seems really restrictive

As a bonus, is there any way to observe attributes that don't have a specific name but follow a certain pattern? (e.g. they match against a regex string or something like that)

And as an extra bonus, is there any way to observe all attributes? (I know they made this not be the default behavior due to performance factors, but still it would be good to be able to enable it if needed)

I'm trying to use vanilla javascript to build a custom ponent which observes changes in all data attributes, e.g.:

class MyComponent extends HTMLElement {

  static get observedAttributes () {
      return ["data-one","data-two","data-three",so forth...]
  }

}

This ponent could in theory be assigned an arbitrary number of data attributes, so there's no way to predict exactly how many there would be, yet I need the ponent to do stuff every time a new data attribute is assigned to it, is there any way to do it? having to put into the array returned by "observedAttributes" the specific name of every attribute seems really restrictive

As a bonus, is there any way to observe attributes that don't have a specific name but follow a certain pattern? (e.g. they match against a regex string or something like that)

And as an extra bonus, is there any way to observe all attributes? (I know they made this not be the default behavior due to performance factors, but still it would be good to be able to enable it if needed)

Share Improve this question asked Jul 21, 2021 at 3:52 super potionsuper potion 3753 silver badges13 bronze badges 3
  • 2 No, use the MutationObserver API to capture attributes that where not assigned as observed attributes when the Custom Element was created. MDN: developer.mozilla/en-US/docs/Web/API/MutationObserver – Danny '365CSI' Engelman Commented Jul 21, 2021 at 10:21
  • Hmm, didn't know that existed, thanks. Well alright, that's one way to do it, was hoping there was a way to do it inside the observedAttributes getter that I was missing, but I guess there's no such thing – super potion Commented Jul 21, 2021 at 19:20
  • @Danny'365CSI'Engelman Is there any advantage of using observedAttributes() vs creating a MutationObserver then? Seems like the MutationObserver is much more flexible. – David Min Commented Jun 30, 2022 at 16:31
Add a ment  | 

3 Answers 3

Reset to default 3

As pointed out in ments by Danny, you can use MutationObserver to do this:

class MyCustomElement extends HTMLElement {
  constructor() {
    super();
  }

  connectedCallback() {
    const observer = new MutationObserver((mutationRecords) => {
      mutationRecords.forEach(record => {
        console.log(`${record.attributeName} has changed to ${this.getAttribute(record.attributeName)}`);
      });
    }).observe(this, { attributes: true });
  }
}

Here is a way to observe all data-attribute changes (using MutationObserver). The callback function filters the observed mutations.

See also

const observer = new MutationObserver(callback);

observer.observe(document, {
  attributes: true,
  subtree: true,
  attributeOldValue: true,
});

// change some data-attributes
const testElem = document.querySelector(`#test`);

// will be observed
testElem.dataset.new = `something else`;

// will NOT be observed
testElem.setAttribute(`title`, `added a title`);

setTimeout(_ => {
  testElem.dataset.first = "Hi";
  testElem.dataset.second = "universe!";
}, 2000);
setTimeout(_ => testElem.dataset.second = "milky way", 1000);

function callback(mutationList) {
  // filter relevant mutations (data-attributes)
  [...mutationList].filter(m => m.attributeName.startsWith(`data`))
  .forEach( mutation => {
      console.info(`✓ Attribute [${
        mutation.attributeName}] changed to '${
        mutation.target.getAttribute(mutation.attributeName)}' (was '${
        mutation.oldValue}')`);
  });
}
[data-second]:before {
  content: attr(data-first)' ';
}

[data-second]:after {
  content: attr(data-second);
}
<div id="test" data-first="hello" data-second="world"></div>

sure you can do so by using one of Custom element callbacks based on this

here are all Custom element lifecycle callbacks

  • and you need to focus on this one attributeChangedCallback

    // Create a class for the element
    class MyCustomElement extends HTMLElement {
    static observedAttributes = ["color", "size"];
    
    constructor() {
      // Always call super first in constructor
      super();
    }
    
    connectedCallback() {
      console.log("Custom element added to page.");
    }
    
    disconnectedCallback() {
      console.log("Custom element removed from page.");
    }
    
    adoptedCallback() {
      console.log("Custom element moved to new page.");
    }
    
    attributeChangedCallback(name, oldValue, newValue) {
      console.log(`Attribute ${name} has changed.`);
    }
    }
    
    customElements.define("my-custom-element", MyCustomElement);
    

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1742364980a4430133.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信