得物技术Web Components初探

简介

在我们的日常工作中,'组件'一词很是熟悉。无论是在react、vue项目中,都经常会去封装一些自定义个性化的组件,来达到某些特定的功能,但是这些组件都需要外部模块的支持。Web Components API便提供了一种方式,在不依赖外部模块的情况下封装自定义的组件。

Web Components API 介绍

它由三项主要技术组成:

  • Custom elements(自定义元素):一组JavaScript API,允许您定义custom elements及其行为,然后可以在您的用户界面中按照需要使用它们。
  • Shadow DOM(影子DOM):一组JavaScript API,用于将封装的“影子”DOM树附加到元素(与主文档DOM分开呈现)并控制其关联的功能。通过这种方式,您可以保持元素的功能私有,这样它们就可以被脚本化和样式化,而不用担心与文档的其他部分发生冲突。
  • HTML templates(HTML模板): template 和 slot 元素使您可以编写不在呈现页面中显示的标记模板。然后它们可以作为自定义元素结构的基础被多次重用。

Custom elements(自定义元素)

自定义元素 Custom elements 是 Web components 技术的核心。

CustomElementRegistry

CustomElementRegistry:包含自定义元素相关功能。

CustomElementRegistry.define()方法可以用来注册新的自定义元素。

window.customElements返回的就是CustomElementRegistry对象的引用。

注意点:

  • 自定义元素类的基类是 HTMLElement ,所以继承了 HTML 元素的特性。也可以继 HTMLElement 的子类,比如 HTMLDivElement 、 HTMLTableElement 、 HTMLButtonElement 等。
  • 自定义元素标签的名称必须包含连字符 - ,用来和内置的HTML标签做区别。
  • 浏览器如果没有解析到自定义元素,会当做空的 div 元素处理。
class MyComponent extends HTMLElement {
  constructor() {
    super();
    // ...
  }
}
// 注册一个自定义元素
window.customElements.define('my-component', MyComponent);

创建自定义内置元素的扩展

is 属性:HTML的全局属性,使用 is 属性可以把一个HTML的内置属性标记成一个已注册的自定义内置元素。

class NewButton extends HTMLButtonElement {
  // ...
}
// 注册时,提供元素的扩展
window.customElements.define('new-button', NewButton, { extends: 'button' })

// 使用时

生命周期

自定义组件的特殊回调函数:

class MyComponent extends HTMLElement {
  constructor() {
    super()
    
  }
  
  connectedCallback(){
    // 当自定义元素第一次被连接到文档DOM时被调用
  }
  disconnectedCallback(){
    // 当自定义元素与文档DOM断开连接时被调用
  }
  adoptedCallback(){
    // 当自定义元素被移动到新文档时被调用
  }
  attributeChangedCallback(){
    // 当自定义元素的一个属性被增加、移除或更改时被调用
  }
}

自定义方法和属性

自定义元素就是javascript的类,因此自定义元素的方法和属性的用法和class一样。

class MyComponent extends HTMLElement {
  constructor() {
    super()
    
  }
  // 自定义方法
  hello() {
    const name = this.getAttribute('name')
    console.log('hello' + name)
  }
  
  // 也可以设置取值器和赋值器
  set name(name) {
    const oldName = this.getAttribute('name')
    if(name !== oldName) {
      this.setAttribute('name', name)
    }
  }
  get name() {
    return this.getAttribute('name')
  }
}
window.customElements.define('my-component', MyComponent);

// 使用


const el = document.querySelector('my-component');
el.hello();

css伪类

  • :defined :匹配任何已定义的元素,包括内置元素和自定义的元素。
  • :host :Shaow Host,组自定元素挂载的节点。

Shadow DOM(影子DOM)

如果我们希望自定义元素的内部代码不允许被外部访问到,我们可以设置Shadow DOM来将其与外部隔离,这样外部的设置无法影响到其内部,而内部的设置也不会影响到外部。

Shadow DOM 特有的术语:

  • Shadow host:一个常规 DOM节点,Shadow DOM 会被附加到这个节点上。
  • Shadow tree:Shadow DOM内部的DOM树。
  • Shadow boundary:Shadow DOM结束的地方,也是常规 DOM开始的地方。
  • Shadow root: Shadow tree的根节点。

得物技术Web Components初探_第1张图片

Shadow DOM 最大的好处:

  • 向用户隐藏细节,直接提供组件。
  • 可以封装内部样式表,不会影响到外部。

例子:




  
  
  Web Components
  






不使用shadow Dom

在不使用shadow Dom的时,内外部样式相互影响,优先级受选择器和加载顺序影响。
得物技术Web Components初探_第2张图片

使用shadow Dom

使用shadow Dom的时,内外部样式互不影响。

class MyComponent extends HTMLElement {
  constructor() {
    super();
    // 使用 shadow dom
    var shadow = this.attachShadow( { mode: 'open' } );
    var con = document.createElement('div');
    con.classList.add('btn');
    con.innerHTML = "自定义元素";

    let style = document.createElement('style');
    style.innerText = '.btn { font-weight: 600; color: red;}';

    shadow.appendChild(style);
    shadow.appendChild(con);
  }
}

得物技术Web Components初探_第3张图片

mode设置

通过设置 mode 为 open 或 closed 能够控制是否可以在外部访问到组件的shadowRoot。




  
  
  Web Components
  






当 mode:'open' 时,点击获取shadowRoot按钮:
得物技术Web Components初探_第4张图片
当 mode:'closed' 时,点击获取shadowRoot按钮:
得物技术Web Components初探_第5张图片

HTML templates(HTML模板)

template模版

上文中在JavaScript中撸dom、style是很麻烦的一件事。Web Components API提供了 template 标签,包含一个HTML片段,不会在文档初始化时渲染。但是可以在运行时使用JavaScript显示。




  
  



  





Slot

slot> 元素,也叫插槽。作为Web Components技术的一部分,是Web组件内的一个占位符。该占位符可以在后期使用自己的标记语言填充,这样您就可以创建单独的DOM树,并将它与其它的组件组合在一起。插槽也分为默认插槽和具名插槽。




  
  



  
left
right
content

参考文献

MDN Web Components:
https://developer.mozilla.org...

你可能感兴趣的:(得物技术Web Components初探)