[英]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.