如何设置动态observedAttributes

问题描述 投票:0回答:2

我的目标是动态设置

observedAttributes
,因此我的 Web 组件将仅监视遵循某种模式的属性,例如冒号 (:attr)
<my-element static="value1" :dynamic=${dynamic}/>

在这种情况下,
<my-element>
应仅为属性
observedAttributes
 设置 
:dynamic

问题是

static get observedAttributes()
甚至在
this
之前运行,解释于 https://andyogo.github.io/custom-element-reactions-diagram/

所以这行不通

static get observedAttributes() {
   return this.getAttributeNames().filter((item) => item.startsWith(':'));
}

当然也没有

constructor() {
        super();
        this._observedAttributes = this.getAttributeNames().filter((item) => item.startsWith(':'));
    }
    static get observedAttributes() {
        return this._observedAttributes;
    }

谢谢!

<!DOCTYPE html>

<body>
    <my-element static="value1" :dynamic="value2" ></my-element>
    <script>
        class MyElement extends HTMLElement {
            constructor() {
                super();
                this._observedAttributes= this.getAttributeNames().filter((item) => item.startsWith(':'));
                console.log('observedAttributes',this._observedAttributes);
            }
            static get observedAttributes() {
                return this._observedAttributes;
            }
            attributeChangedCallback(name, oldValue, newValue) {
                console.log(name, oldValue, newValue); //doesn't log anything
            }
        }
        customElements.define("my-element", MyElement);
        setTimeout(() => {
            console.log('setting dynamic attribute. This should trigger attributeChangedCallback. But no.');
            document.querySelector('my-element').setAttribute(':dynamic', 'value3');
        }, 2000);
    </script>
</body>

</html>

javascript web-component native-web-component
2个回答
1
投票

您可以使用以下垫片来添加在元素的每个实例上动态观察属性变化的功能。您可以定义默认情况下在所有实例上观察到的属性,也可以在运行时添加仅在特定实例上观察到的属性。

class BaseClass extends HTMLElement {
  constructor({stat = BaseClass} = {}) {
    super()
        // console.log('constructor')
        this.#stat = stat
        this.#setAttribute = this.setAttribute
        this.setAttribute = function(name, value){
            // console.log('attribute', name, this.observedAttributes, (this.observedAttributes.includes(name)))
            if (this.observedAttributes.includes(name)){
                // do your stuff
                // console.log('attribute includes')
                this.attributeChangedCallback(name, this.getAttribute(name), value)
            }
            else {
            // do what you want
            }
            this.#setAttribute(name, value)
        }
  }
    #observedAttributes = []
    get observedAttributes(){
        return [...this.#stat.observedAttributes, ...this.#observedAttributes]
    }
    #setAttribute = null
    #stat = null
    addObservedProp(name){
        this.#observedAttributes.push(name)
    }
  connectedCallback() {}
  disconnectedCallback() {}
  attributeChangedCallback(name, oldValue, newValue) {
        console.log('change', name, oldValue, newValue)
    }
  adoptedCallback() {}
  static get observedAttributes() {
    return ['a', 'b', 'c']
  }
}

window.customElements.define('base-com', BaseClass)

const test = document.getElementById('test')
test.setAttribute('d', 'status 1')
test.addObservedProp('d')
test.setAttribute('d', 'status 2')
console.log(test)
<base-com id="test">Base com</base-com>


0
投票

按照 @Danny '365CSI' Engelman 的建议,我查看了 MutationObserver API 并提出了一个简单的解决方案,我认为它提供的不仅仅是

observedAttributes

<my-element static="value1" :dynamic="value2"></my-element>
<script>
  class MyElement extends HTMLElement {
    constructor() {
      super();
    }
    mutationObserverCallback(mutationList, observer) {
      for (const mutation of mutationList) {
        if (mutation.type === 'attributes' &&
          mutation.attributeName.startsWith(':') &&
          mutation.oldValue !== mutation.target.getAttribute(mutation.attributeName)) {
          console.log(`The dynamic ${mutation.attributeName} attribute was modified.`);
        }
      }
    }
    connectedCallback() {
      this.mutationObserver = new MutationObserver(this.mutationObserverCallback);
      this.mutationObserver.observe(this, {
        attributes: true,
        attributeOldValue: true
      });
    }
    disconnectedCallback() {
      this.mutationObserver.disconnect();
    }
  }
  customElements.define("my-element", MyElement);
  setTimeout(() => {
    console.log('setting dynamic attribute for :dynamic and static attributes. This should trigger mutationObserverCallback for :dynamic only.');
    // ▼ will trigger mutationObserverCallback
    document.querySelector('my-element').setAttribute(':dynamic', 'value3');
    // ▼ will not trigger mutationObserverCallback
    document.querySelector('my-element').setAttribute('static', 'value4');
  }, 200);
</script>

© www.soinside.com 2019 - 2024. All rights reserved.