javascript - Web 组件 : setter not being called

标签 javascript web-component

假设我有一个 Web 组件:

customElements.define("custom-list", class CustomList extends HTMLElement {
  get filter() {
    console.log("get filter");
    return this.getAttribute("filter");
  }

  set filter(value) {
    console.log("set filter");
    this.setAttribute("filter", value);
  }
});

我想使用 setter 方法进行一些初始属性验证,但从未调用过 setter。我尝试通过 HTML 设置属性:

<custom-list filter="some value"></custom-list>

只有当我使用 JavaScript 以编程方式设置属性时,setter 才会被调用:

var list = document.querySelector("custom-list");
list.filter = "some value";

list.setAttribute("filter", "some value"); // DOESN'T WORK EITHER

因此,似乎通过 HTML 设置属性或使用 setAttribute 不会触发 setter,我部分可以理解。我的问题是:

  • 只有当我想以编程方式设置属性时才需要 setter 吗?
  • 如何对属性进行初始验证?在 connectedCallback 中?假设我只想接受某个字符串,我该如何检测?
  • 既然属性 filter 无论如何都会被填充,如果我不使用 JavaScript 来设置我的属性,我还需要 setter 吗?

最佳答案

getter 和 setter 是一种定义属性的方式,允许您的代码接收和返回字符串以外的值。

元素的属性总是字符串值。您可以通过解析值来模拟属性中的非字符串。但它们总是作为字符串设置并作为字符串读回。

如果您希望在属性更改时运行代码,则需要添加 attributeChangedCallback 函数并在 observedAttributes 静态 getter 中指明您正在观察的属性。

可以通过调用 setAttributeremoveAttribute 在 JavaScript 中设置属性。当浏览器由于页面加载或设置 innerHTML 解析您的 HTML 时,也会设置它们。但即便如此,浏览器也不会设置这些,直到浏览器调用构造函数后,浏览器最终在后台调用 setAttribute

customElements.define("custom-list", class CustomList extends HTMLElement {
  static get observedAttributes() { return ['filter']; }

  constructor() {
    super();
    this._filter = null; // Save the initial value
  }

  attributeChangedCallback(attr, oldVal, newVal) {
    if (oldVal != newVal) {
      // Only set this value if it is different
      this.filter = newVal; // Call the setter
    }
  }

  get filter() {
    console.log("get filter");
    return this._filter; // Return the internal value
  }

  set filter(value) {
    // Only run this if the new value is different from the internal value
    if (value !== this._filter) {
      console.log(`set filter ${value}`);
      this._filter = value; // Set the internal value
      this.textContent = value;
      // If you want the filter property to always show
      // in the attributes then do this:
      if (value !== null) {
        this.setAttribute('filter', value);
      } else {
        this.removeAttribute('filter');
      }
    }
  }
});

const el = document.querySelector('custom-list');
setTimeout(() => {
  el.filter = 'happy';
}, 2000);
<custom-list filter="10"></custom-list>

始终检查函数attributeChangedCallback 中的oldValnewVal 是否不同。否则你可能会陷入无限循环。

还建议您在 setter 中检查不同的值。 同样,避免陷入无限循环。

Setter 还允许您获取特定的数据类型。例如,您可以检查 value 的值是否为数字,如果不是,则抛出一个 TypeError。或者您只是将传入的值转换为正确的类型。

Setter 还允许您确保一个值是有效的。也许它必须是正数或三个可能的字符串之一。如果不是,您可以抛出一个 RangeError

但您必须记住,属性始终是字符串,属性可以是任何内容。

关于javascript - Web 组件 : setter not being called,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56547019/

相关文章:

javascript - 用html在jsp页面上将文本移到左侧

javascript - Fabric .js : Is there a way to make the "move" listener fire when moved as part of a selection?

javascript - 如何使用 jquery 隐藏特定的 li

javascript - 单击正文关闭下拉组件

javascript - Web 组件 : Dom Exception: This name has already been used

polymer - 如何从 lit-element 中的槽元素引用槽元素?

javascript - 如何使用 JAVASCRIPT 获取 <option> 标签内自定义属性的值

javascript - 如何使用 JavaScript 中具有短签名的 key 对数据进行签名

javascript - 使用 this.set 更改数组值时会导致 dom-repeat 出现奇怪的结果

polymer - 如何从子元素更改应用程序路由位置