簡體   English   中英

自定義元素不選擇屬性

[英]Custom element not picking up attributes

我正在嘗試查看自定義元素及其工作方式,雖然 MDN 上的示例工作正常,但我似乎無法自己復制它們。

MDN 文章在這里

是來自 MDN 的一個工作示例。

我的問題是我似乎永遠無法將屬性傳遞到我的組件中,它們總是以 null 形式出現,而不是傳遞參數的值。

我的 JS 是 (test.js)

  class PopUpInfo extends HTMLElement {
    constructor() {
      // Always call super first in constructor
      super();
  
      // Create a shadow root
      const shadow = this.attachShadow({mode: 'open'});
  
      // Create spans
      const wrapper = document.createElement('span');
      const info = document.createElement('span');
 
      // Take attribute content and put it inside the info span
      const text = this.getAttribute('foo'); // <-- this always returns null
      info.textContent = `(${text})`;

      shadow.appendChild(wrapper);
      wrapper.appendChild(info);
    }
  }
  
  // Define the new element
  customElements.define('popup-info', PopUpInfo);

還有我的 HTML:

<html>
    <head>
        <script src="test.js"></script>
    </head>
    <body>

        <hr>

        <popup-info foo="Hello World"></popup-info> 

        <hr>

    </body>
</html>

我期待在屏幕上看到的是文字

(你好,世界)

但我所看到的只是

(空值)

當我調試時,我可以看到this.attributes的長度為 0,所以它沒有被傳入。

有沒有人在創建自定義元素時見過這個?

保持埃米爾的答案為正確答案。

只是為了表明有可能的替代和更短的符號:

 customElements.define('popup-info', class extends HTMLElement { static get observedAttributes() { return ['foo']; } constructor() { const wrapper = document.createElement('span'); super().attachShadow({mode:'open'})// both SETS and RETURNS this.shadowRoot .append(wrapper); this.wrapper = wrapper; } attributeChangedCallback(name, oldValue, newValue) { switch(name) { case 'foo': this.wrapper.textContent = `(${newValue})`; break; } } });
 <popup-info foo="Hello World" onclick="this.setAttribute('foo','Another world')" > </popup-info>

盡管當我嘗試在代碼段中運行您的示例時,它似乎運行良好,但我仍然想提出改進建議。

使用observedAttributes靜態getter 來定義組件應該關注的屬性列表。 當屬性的值已更改並且屬性的名稱在列表中時,則調用attributeChangedCallback回調。 在那里,您可以在更改屬性值時斷言要做什么的邏輯。

在這種情況下,您可以構建您想要的字符串。 這也有副作用,只要屬性值再次更改,字符串就會更新。

 class PopUpInfo extends HTMLElement { /** * Observe the foo attribute for changes. */ static get observedAttributes() { return ['foo']; } constructor() { super(); const shadow = this.attachShadow({ mode: 'open' }); const wrapper = document.createElement('span'); const info = document.createElement('span'); wrapper.classList.add('wrapper'); wrapper.appendChild(info); shadow.appendChild(wrapper); } /** * Returns the wrapper element from the shadowRoot. */ get wrapper() { return this.shadowRoot.querySelector('.wrapper') } /** * Is called when observed attributes have a changed value. */ attributeChangedCallback(attrName, oldValue, newValue) { switch(attrName) { case 'foo': this.wrapper.textContent = `(${newValue})`; break; } } } // Define the new element customElements.define('popup-info', PopUpInfo);
 <html> <head> <script src="test.js"></script> </head> <body> <hr> <popup-info foo="Hello World"></popup-info> <hr> </body> </html>

您在 HTML 中的腳本導入中缺少 defer 屬性,並且它沒有正確加載,這就是問題所在。 defer 屬性允許在頁面解析后執行腳本

 class PopUpInfo extends HTMLElement { constructor() { // Always call super first in constructor super() // Create a shadow root const shadow = this.attachShadow({ mode: 'open' }) // Create spans const wrapper = document.createElement('span') const info = document.createElement('span') // Take attribute content and put it inside the info span const text = this.getAttribute('foo') // <-- this always returns null info.textContent = `(${text})` shadow.appendChild(wrapper) wrapper.appendChild(info) } } // Define the new element customElements.define('popup-info', PopUpInfo)
 <html> <head> <script src="app.js" defer></script> </head> <body> <hr /> <popup-info foo="Hello World"></popup-info> <hr /> </body> </html>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM