leeeeee

自定义元素介绍 - DEV社区

原文链接: dev.to

引言

自定义元素是Web组件的一个子集,在我看来这是web 开发中最酷的概念之一,自定义元素让我们能够通过原生的 web 平台来构建组件,而不是依赖于 React、Angular Vue 或者其他的中间库或者框架。

在这篇文章中,我会向你阐述什么是自定义元素、如何创建以及如何在页面上展示。

Web组件的基础

所有自定义元素都将共享一些常用方法,可以在下面的代码示例中看到:

class MyComponent extends HTMLElement {
  static get observedAttributes() {
    return [];
  }

  constructor(...args) {
    super(...args);
  }

  connectedCallback() {}

  disconnectedCallback() {}

  adoptedCallback() {}

  attributeChangedCallback(attrName, oldVal, newVal) {}
}

window.customElements.define('my-component', MyComponent);


让我们分解一下这个组件里面做了哪些事情。

constructor() - 构造函数

构造函数是最先声明的,并将所有参数通过 super 方法传递给父级。

通常情况下,构造函数里可以放置一些事件侦听的代码,例如:

...
constructor(...args) {
    super(...args);
    this.addEventListener('click', this.handleClick);
}

handleClick(event) {}
...


connectedCallback()

每次将元素插入DOM时调用。

每次将组件添加到文档中的任何位置时,它都会立即触发此方法

disconnectedCallback()

每次从DOM中删除元素时调用。

例如,当我们删除DOM树中的该节点或该节点的父节点时,则此函数将触发,因为该节点本身也将从上述 DOM 树中删除。

当元素被移动到文档的其他地方或新页面的时候,disconnectedCallback 也会被调用。

adoptedCallback()

每次将自定义元素移动到新文档时调用。

如果将自定义元素移动到新页面或文档中的其他位置,则将触发此回调。

attributeChangedCallback(attrName, oldVal, newVal)

添加,删除,更新或替换元素的属性时会调用该方法

每当元素的属性变化时,attributeChangedCallback()回调函数就会执行,除非当前属性的改变是已经被监听着的,这个时候就会调用 observedAttributes 方法。

observedAttributes()

我们实际想要观察的自定义元素的属性会发生变化

如您所见,observedAttributes 被设计成是一个静态方法,这明显不同于其他方法的声明,这是因为我们希望能够被任何子类/组件继承,而且我们只想声明它一次引用,注意,它是静态的(为所有继承者包括它自己)和 gettable(供参考)。

这个方法返回一个字符串数组,数组中的每个字符串是你想要监听的属性的名称,例如:

...
static get observedAttributes() {
    return ['id', 'my-custom-attribute', 'data-something', 'disabled'];
}
...


自定义元素规范中还有一些其他的方法,但以上这些是我们日常主要使用的方法。

基本组件

让我们构建一个向用户打招呼的基本组件。

html 部分

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Custom Elements 101</title>
</head>
<body>
  <hello-component data-name="James"></hello-component>
  <script src="./hello-component.js"></script>
</body>
</html>


javascript 部分

class HelloComponent extends HTMLElement {
  static get observedAttributes() {
    return ['data-name'];
  }

  // custom methods
  render() {
    this.innerHTML = Hello ${this.name};
  }

  get name() {
    return this.getAttribute('data-name');
  }

  // lifecycle hooks
  connectedCallback() {
    this.render();
  }

  attributeChangedCallback(attrName, oldVal, newVal) {
    this.render();
  }
}

// add into the 'real' dom as a valid tag
window.customElements.define('hello-component', HelloComponent);



加载index.html,我们可以在页面上看到“Hello James”。

现在,打开浏览器的开发者工具并将data-name属性更改为除James 之外的其他值。你会发现我们有内置的反应!是不是很棒?!

当然,这只是一个非常基本的、非最佳实践、0用例,默认教程的实现,但他给了你一个基本的入门介绍,以便我们在后面的文章中做更详细的深入。

浏览器支持

以下是当前对Web组件的支持以及所有支持它们的API,包括Shadow DOM,自定义元素(我们刚刚查看的内容),HTML模板和插槽以及HTML导入:

Current support for Web Components APIs from the caniuse documentation at the time of writing this article

总结

自定义元素让我们有能力在无需借助框架的情况下实现反应式的 UI 开发。它们确实为我们提供了许多挑战,其中许多将在未来展望, 但是我们可以先去尝试一下,并把其他的「Web Component 」相关规范的 API 放在一起看下,它们真的让我们能够制作出很酷、很强大、反应灵敏的元素,让我们可以用很少的东西做很多事。

资料