javascript - 自定义元素 : attribute won't update component state

标签 javascript html web-component

我是 Web 组件的新手,当我用 html 编写组件并直接在 html 中添加属性时遇到问题。 问题是组件没有触发设置属性函数。

仅当我设置属性或使用 javascript 创建组件并将其添加到 DOM 时,设置属性函数才有效。

我创建了一支笔来举例说明我的问题:

Go to Pen

window.addEventListener('load', () => {
  document.body.getElementsByTagName('news-article')[1].article = {
    title: 'dynamic value'
  };

  let element = document.createElement('news-article');
  element.article = {
    'title': 'dynamic element'
  };

  document.body.appendChild(element);
})

class NewsArticle extends HTMLElement {

  static get observedAttributes() {
    debugger
    return ['article'];
  }

  constructor() {
    debugger
    super();
    this.root = this.attachShadow({
      mode: 'open'
    });
  }

  set article(val) {
    debugger
    this.root.innerHTML = `
						<style>
							:host {
								display: block;
								border: 3px solid #000;
								padding:	15px;
							}

							h2 {
								text-transform: uppercase;
							}
						</style>


						<h2>${val.title}</h2>
					`;
  }

  get article() {
    debugger
    return this.getAttribute('article');
  }

  attributeChangedCallback(attrName, oldVal, newVal) {
    debugger
    this.setAttribute(attrName) = JSON.parse(newVal);
  }
}

window.customElements.define('news-article', NewsArticle);
<news-article article="{ title: 'static value' }"></news-article>
<news-article></news-article>

最佳答案

@connexo 对属性发生了什么、如何操纵它们以及如何提取它们的值给出了很好的解释。

我想通过稍微改变结构来添加他的解决方案。

Getters 和 setters:使用 getters 和 setters 来操作元素的属性。这样,您可以通过使用 news-article.article = { title: 'Breaking news' } 更改属性值和 HTML 来更改 article 属性,并使用 news-article.article 获取 article 属性的当前值。

因为您正在观察 article 属性,当您更改 article 属性值时,它将触发 attributeChangedCallback。你应该把你的逻辑放在那里改变一切属性的值。在您的情况下,更改 Shadow DOM 的 innerHTML

class NewsArticle extends HTMLElement {

  /**
   * Fire the attributeChangedCallback when the article
   * attribute has been changed.
   */
  static get observedAttributes() {
    return ['article'];
  }

  constructor() {
    super();
    this.attachShadow({
      mode: 'open'
    });
  }

  /** 
   * Set the article attribute value.
   *
   * This will fire the attributeChangedCallback because
   * 'article' is in the observedAttributes array.
   */
  set article(val) {
    this.setAttribute('article', JSON.stringify(val));
  }

  /** 
   * Gets the current article attribute value.
   */
  get article() {
    return JSON.parse(this.getAttribute('article'));
  }

  /** 
   * Do something when an attribute is changed.
   *
   * In this case change the innerHTML of the shadowRoot
   * when the 'article' attribute has changed.
   */
  attributeChangedCallback(attrName, oldVal, newVal) {
    if (attrName === 'article') {
      const { title } = JSON.parse(newVal);
      this.shadowRoot.innerHTML = `
        <style>
          :host {
            display: block;
            border: 3px solid #000;
            padding: 15px;
          }

          h2 {
            text-transform: uppercase;
          }
         </style>
         <h2>${title}</h2>`;
    }
  }

}

感谢@connexo 的出色工作!

关于javascript - 自定义元素 : attribute won't update component state,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57543618/

相关文章:

javascript - 从列表中删除/隐藏大量元素的最快方法

javascript - 精简代码

javascript - jquery 删除类()

javascript - 声音管理器 2 : Stop a playing sound when playing another

javascript - 处理 polymer 元素继承的最佳方法

javascript - 使用 Jquery ui Droppable 将元素直接插入 div

javascript - 使用 jquery.scrollTo 时使用 jQuery 处理元素 ID 中的冒号

html - 如何使用 Twig 函数返回和插入 HTML 代码?

javascript - 使用 webcomponenetsjs 的 HTMLImports 以意外的执行顺序加载导入 - firefox

polymer - 如何用 Jest 测试 Web 组件(lit-element)