Web Components —— Web 组件(下)

简介: Web Components —— Web 组件

[ 命名槽位(named slot)]

通过匹配的 slot/name 属性对实现的,比如下面的例子中,带有 slot="foo" 属性的元素会被投射到带有 name="foo" 的 <slot> 上.

document.body.innerHTML = ` 
    <div> 
    <p slot="foo">Foo</p> 
    <p slot="bar">Bar</p> 
    </div> 
  `;
    let shadowDom = document.querySelector('div').attachShadow({
      mode: 'open'
    });
    shadowDom.innerHTML = ` 
    <slot name="bar"></slot> 
    <slot name="foo"></slot> 
   `;
复制代码

影子 DOM 中的事件重定向

如果影子 DOM 中发生了浏览器事件(如 click),那么浏览器需要一种方式以让父 DOM 处理事件.

注意:事件重定向只会发生在影子 DOM 中实际存在的元素上,使用 <slot> 标签从外部投射进来的元素不会发生事件重定向,因为从技术上讲,这些元素仍然存在于影子 DOM 外部。

// 创建一个元素作为影子宿主
document.body.innerHTML = `
 <div onclick="console.log('Handled outside:', event.target)"></div>
`;
// 添加影子 DOM 并向其中插入 HTML
document.querySelector('div')
.attachShadow({ mode: 'open' })
.innerHTML = `
 <button onclick="console.log('Handled inside:', event.target)">Foo</button>
`;
// 点击按钮时:
// Handled inside: <button onclick="..."></button>
// Handled outside: <div onclick="..."></div>
复制代码

创建影子 DOM 的限制

考虑到安全及避免影子 DOM 冲突,并非所有元素都可以包含影子 DOM,尝试给无效元素或者已经有了影子 DOM 的元素添加影子 DOM 会导致抛出错误。

以下是可以容纳影子 DOM 的元素:

<任何以有效名称创建的自定义元素>
<article>
<aside>
<blockquote>
<body>
<div>
<footer>
<h1>
<h2>
<h3>
<h4>
<h5>
<h6>
<header>
<main>
<nav>
<p>
<section>
<span>
复制代码

自定义元素

自定义元素为 HTML 元素引入了面向对象编程的风格,基于这种风格,可以创建自定义的、复杂的和可重用的元素,而且只要使用简单的 HTML 标签或属性就可以创建相应的实例。

创建自定义元素

浏览器会尝试将无法识别的元素作为通用元素整合进 DOM,如下面的例子所示.

自定义元素在此基础上更进一步,利用自定义元素,可以在 <x-box> 标签出现时为它定义复杂的行为,同样也可以在 DOM 中将其纳入元素生命周期管理。

document.body.innerHTML = ` 
 <x-box>I'm inside a custom element.</x-box> 
`;
console.log(document.querySelector('x-box') instanceof HTMLElement); // true
复制代码

customElements.define()

调用 customElements.define() 方法可以创建自定义元素,自定义元素的强大之处在于类定义.

class BoxElement extends HTMLElement {
    constructor() {
        super();
        console.log('x-box')
    }
}
customElements.define('x-box', BoxElement);
document.body.innerHTML = `
    <x-box></x-box>
    <x-box></x-box>
    <x-box></x-box>
`;
// x-box
// x-box
// x-box
复制代码

is 和 extents

如果自定义元素继承了一个元素类,那么可以使用 is 属性和 extends 选项将标签指定为该自定义元素的实例.

class BoxElement extends HTMLDivElement {
    constructor() {
        super();
        console.log('x-box')
    }
}
customElements.define('x-box', BoxElement, { extends: 'div' });
document.body.innerHTML = `
    <div is="x-box"></div>
    <div is="x-box"></div>
    <div is="x-box"></div>
`;
// x-box
// x-box
// x-box
复制代码

添加自定义元素内容

class BoxElement extends HTMLElement {
  constructor() {
    super();
     // 方式一
     this.innerHTML = `<div>this is content1!</div>`;
     // 方式二
     let div = document.createElement('div');
     div.innerText = `this is content2!`;
     this.appendChild(div);
     // 方式三
     this.attachShadow({ mode: 'open' });
     this.shadowRoot.innerHTML = `
      <p>I'm inside a custom element!</p>
     `;
  }
}
customElements.define('x-box', BoxElement);
document.body.innerHTML += `<x-box></x-box`;
复制代码

使用自定义元素生命周期方法

自定义元素有以下 5 个生命周期方法:

  • constructor():在创建元素实例或将已有 DOM 元素升级为自定义元素时调用
  • connectedCallback():在每次将这个自定义元素实例添加到 DOM 中时调用
  • disconnectedCallback():在每次将这个自定义元素实例从 DOM 中移除时调用
  • attributeChangedCallback():在每次可观察属性的值发生变化时调用,在元素实例初始化时,初始值的定义也算一次变化
  • adoptedCallback():在通过 document.adoptNode()将这个自定义元素实例移动到新文档
class BoxElement extends HTMLElement {
  constructor() {
    super();
    console.log('ctor');
  }
  connectedCallback() {
    console.log('connected');
  }
  disconnectedCallback() {
    console.log('disconnected');
  }
}
customElements.define('x-box', BoxElement);
const BoxElement = document.createElement('x-box');
// ctor 
document.body.appendChild(BoxElement);
// connected 
document.body.removeChild(BoxElement);
// disconnected
复制代码

升级自定义元素

并非始终可以先定义自定义元素,然后再在 DOM 中使用相应的元素标签。可以通过 Web 组件在 CustomElementRegistry 上的一些方法,用来检测自定义元素是否定义完成,然后可以用它来升级已有元素。

  • 如果自定义元素已经有定义,那么 CustomElementRegistry.get() 方法会返回相应自定义元素的类
  • CustomElementRegistry.whenDefined() 方法会返回一个期约,当相应自定义元素有定义之后解决
customElements.whenDefined('x-box').then(() => console.log('defined!'));
console.log(customElements.get('x-box')); // undefined 
customElements.define('x-box', class {});// defined! 
console.log(customElements.get('x-box'));// class BoxElement {}
复制代码

连接到 DOM 的元素在自定义元素有定义时会自动升级,如果想在元素连接到 DOM 之前强制升级,可以使用 CustomElementRegistry.upgrade() 方法.

// 在自定义元素有定义之前会创建 HTMLUnknownElement 对象
const boxElement = document.createElement('x-box');
// 创建自定义元素
class BoxElement extends HTMLElement {}
customElements.define('x-box', BoxElement);
console.log(boxElement instanceof BoxElement); // false
// 强制升级
customElements.upgrade(boxElement);
console.log(boxElement instanceof BoxElement); // true
复制代码

总结

到现在,你应该发现了 web 组件中的一些内容和 vue 中的某些内容是不是很相似,如:

vuejs

  • <template> 标签
  • <slot> 插槽
  • <style scope> 局部样式
  • vue 组件,即 .vue 文件
  • <component is="name"> 动态组件

web 组件

  • template 模板
  • 影子 DOM 中的 <slot> 插槽
  • 影子 DOM 中的 <style> 隔离样式
  • 自定义标签,即 自定义组件
  • 自定义组件中的 is 属性和 extends 选项

注意:当然相似归相似,其本质还是不同的,所以千万不要进行混淆,但是可以认为概念上是有所借鉴的,至此不难发现很多知识内容其实是相通的。


目录
相关文章
|
4月前
|
JavaScript 前端开发 开发者
哇塞!Vue.js 与 Web Components 携手,掀起前端组件复用风暴,震撼你的开发世界!
【8月更文挑战第30天】这段内容介绍了Vue.js和Web Components在前端开发中的优势及二者结合的可能性。Vue.js提供高效简洁的组件化开发,单个组件包含模板、脚本和样式,方便构建复杂用户界面。Web Components作为新兴技术标准,利用自定义元素、Shadow DOM等技术创建封装性强的自定义HTML元素,实现跨框架复用。结合二者,不仅增强了Web Components的逻辑和交互功能,还实现了Vue.js组件在不同框架中的复用,提高了开发效率和可维护性。未来前端开发中,这种结合将大有可为。
167 0
|
4月前
|
Web App开发 JavaScript 前端开发
[译] 用 Web Worker 改善 Vue 组件性能
[译] 用 Web Worker 改善 Vue 组件性能
|
2月前
|
前端开发 JavaScript 开发者
Web组件:一种新的前端开发范式
【10月更文挑战第9天】Web组件:一种新的前端开发范式
64 2
|
2月前
|
前端开发 JavaScript Go
前端开发趋势:从响应式设计到Web组件的探索
【10月更文挑战第1天】前端开发趋势:从响应式设计到Web组件的探索
42 3
|
1月前
|
消息中间件 监控 Kafka
Apache Kafka 成为处理实时数据流的关键组件。Kafka Manager 提供了一个简洁的 Web 界面
随着大数据技术的发展,Apache Kafka 成为处理实时数据流的关键组件。Kafka Manager 提供了一个简洁的 Web 界面,方便管理和监控 Kafka 集群。本文详细介绍了 Kafka Manager 的部署步骤和基本使用方法,包括配置文件的修改、启动命令、API 示例代码等,帮助你快速上手并有效管理 Kafka 集群。
47 0
|
5月前
|
Web App开发 前端开发 安全
2024年新一代WebOffice内嵌网页组件,Web网页在线编辑Word/Excel/PPT
WebOffice控件面临兼容性、用户体验和维护难题。随着浏览器更新,依赖插件的技术不再适用,如Chrome不再支持NPAPI和PPAPI。产品普遍不支持多版本Office并存,定制能力弱,升级复杂。猿大师办公助手提供了解决方案,它兼容多种浏览器,包括最新版和国产浏览器,不依赖插件,支持文档对比,具有丰富的功能和接口,兼容多种Office版本,允许源码级定制,提供终身技术支持,并实现静默在线升级。适用于多种行业和操作系统。
324 11
|
4月前
|
数据可视化 数据挖掘 持续交付
Axure Web端元件库:从Quick UI到500+组件的飞跃
在快速变化的数字世界中,产品设计不仅仅是功能的堆砌,更是用户体验的精心雕琢。原型设计作为产品开发过程中的关键环节,其重要性不言而喻。Axure,作为业界领先的原型设计工具,凭借其强大的交互设计和丰富的功能,赢得了全球设计师和开发者的信赖。而Axure Web端元件库,则是这一平台上的一颗璀璨明珠,它以超过500个精心设计的组件为基础,为设计师们打开了一扇通往高效、高质量原型设计的大门。
191 0
|
5月前
|
JavaScript 前端开发 API
Web Components详解-HTML Templates
Web Components详解-HTML Templates
90 6
|
5月前
|
设计模式 JavaScript 前端开发
Web Components详解-组件通信
Web Components详解-组件通信
104 6
|
5月前
|
JavaScript 前端开发
Web Components详解-Shadow DOM样式控制
Web Components详解-Shadow DOM样式控制
145 3