WebComponent

优点

  1. 可以通过shadowDOM实现css隔离
  2. 原生的组件化开发

Custom elements

  1. 继承自 HTMLElement 抽象类的自主自定义标签
  2. 继承自内建的HTML元素的自定义内建元素

提示:Custom element 名称必须包括一个短横线 -,这是为了保证和内建html元素标签不冲突

自主自定义标签

class MyElement extends HTMLElement {
  constructor() {
    super();
    // 元素在这里创建
  }

  connectedCallback() {
    // 在元素被添加到文档之后,浏览器会调用这个方法
    //(如果一个元素被反复添加到文档/移除文档,那么这个方法会被多次调用)
  }

  disconnectedCallback() {
    // 在元素从文档移除的时候,浏览器会调用这个方法
    // (如果一个元素被反复添加到文档/移除文档,那么这个方法会被多次调用)
  }

  static get observedAttributes() {
    return [/* 属性数组,这些属性的变化会被监视 */];
  }

  attributeChangedCallback(name, oldValue, newValue) {
    // 当上面数组中的属性发生变化的时候,这个方法会被调用
  }
}
// 注册元素
customElements.define("my-element", MyElement);

自定义内建元素

class HelloButton extends HTMLButtonElement { /* custom element 方法 */ }

// 使用时通过<button is="hello-button"></button>来展示
customElements.define('hello-button', HelloButton, {extends: 'button'});

Template

  • 本身被视为超出文档结构的的范围,不会对文档产生影响,可以用做webcomponent的html结构
  • 内部可以增加style标签来写样式

Shadow DOM

    ele.attachShadow({ mode: 'open/close' });

如果mode设置为true,则可以使用elem.shadowRoot来获取shadowDOM 的root节点,否则只能用attachShadow方法返回值来获取

Shadow DOM slot

占槽元素来自 light DOM,所以它们使用文档样式。局部样式不会影响占槽内容, 可以使用slot[name=xxx]或::slotted(xxx) 来设置

// 自主自定义标签
const template = document.createElement('template');
template.innerHTML = `
  <style>
    ::slotted(span) {
      color: blue;
    }
  </style>
  <div>
    <slot name="inner"></slot>
  </div>
`;
class CustromElement extends HTMLElement {
  constructor() {
    super();
  }
  connectedCallback() {
    console.log(template.content);
    this.attachShadow({ mode: 'open' });
    this.shadowRoot.appendChild(template.content.cloneNode(true));
  }
}
customElements.define('custom-element', CustromElement);

Shadow DOM Event

当事件在组件外部捕获时,shadow DOM 中发生的事件将会以 host 元素作为目标。
事件仅仅是在它们的 composed 标志设置为 true 的时候才能通过 shadow DOM 边界。

触发自定义事件

// 自定义事件
element.dispatchEvent(new CustomEvent('test', {
  bubbles: true,
  composed: true,
  // 通过detail属性传递数据
  detail: "composed"
}));

将DOM结构、样式写在同一个文件

const template = document.createElement('template');

template.innerHTML = `
  <style>
    .container {
      padding: 8px;
    }

    button {
      display: block;
      overflow: hidden;
      position: relative;
      padding: 0 16px;
      font-size: 16px;
      font-weight: bold;
      text-overflow: ellipsis;
      white-space: nowrap;
      cursor: pointer;
      outline: none;

      width: 100%;
      height: 40px;

      box-sizing: border-box;
      border: 1px solid #a1a1a1;
      background: #ffffff;
      box-shadow: 0 2px 4px 0 rgba(0,0,0, 0.05), 0 2px 8px 0 rgba(161,161,161, 0.4);
      color: #363636;
    }
  </style>

  <div class="container">
    <button>Label</button>
  </div>
`;

class Button extends HTMLElement {
  constructor() {
    super();

    this._shadowRoot = this.attachShadow({ mode: 'open' });
    this._shadowRoot.appendChild(template.content.cloneNode(true));
  }
}

window.customElements.define('my-button', Button);

·

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容