标签: web-component

创建具有不同子类型的自定义元素

我目前正在使用自定义元素(Web 组件)实现数据表元素。表格可以具有用于呈现每一行的不同类型的单元格(文本、数字、日期等)。

例如

<my-table>
    <my-table-cell-text column="name"></my-table-cell-text>
    <my-table-cell-date column="dob" format="YYYY-MM-DD"></my-table-cell-date>
    <my-table-cell-number column="salary" decimals="2"></my-table-cell-number >
</my-table>
Run Code Online (Sandbox Code Playgroud)

我还有一个MyTableCell所有单元格元素都扩展的类。这适用于共享通用功能,但样式可能很麻烦,因为每个单元格类型都是它自己的 html 标签。目前,我在扩展时添加了一个 css 类MyTableCell,但为了论证,可以说我不想这样做。

理想的解决方案是能够扩展自定义元素,使用is关键字,例如<my-table-cell is="my-table-cell-text">但只允许内置 html 元素


我可以想到解决这个问题的 3 种方法:

  1. 具有类似于 的语法<input type="">,但需要做更多的工作,因为您不再扩展基类,而是创建相同元素的变体,这意味着您需要一种自定义方式来注册不同的变体,例如静态MyTableCell.registerType

  2. 一种可组合的方法,我将渲染器元素 包裹<my-table-renderer-text>在通用<my-table-cell>. 这避免了自定义注册方法,但它更难编写,并导致更多元素和更多样板代码,这反过来意味着性能下降。

  3. 两者的混合,用户写入<my-table-cell type="text">和单元格在document.createElement('my-table-rendener-'+ type)内部使用类似的东西。这保留了选项 1 的更简单的语法,同时仍然避免了自定义寄存器方法,但它具有与选项 2 相同的性能影响。


你能提出更好的选择吗?我错过了什么吗?

html css dom web-component custom-element

5
推荐指数
1
解决办法
2030
查看次数

为什么 attributeChangedCallback 被调用两次?

我正在使用自定义元素 polyfill构建一个简单的自定义元素。我已经注册了一个要“监视”的属性(使用observedAttributes()),当我更改此属性的值时,该函数会attributeChangedCallback被调用两次。

这是 HTML 代码:

<my-component id="compo" foo="bar"></my-component>

<button id="myBtn">Change attribute value</button>
Run Code Online (Sandbox Code Playgroud)

这是我的组件定义:

class MyComponent extends HTMLElement {
  constructor() {
    super();
  }
  
  static get observedAttributes() {
    return ['foo'];
  }
  
  attributeChangedCallback(attrName, oldVal, newVal) {
    console.log('[my component] attribute', attrName, 'changed from', oldVal, 'to', newVal);
  }
}

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

// Change value of the component attribute
$('#myBtn').click(() => $('#compo').attr('foo', 'baz'));
Run Code Online (Sandbox Code Playgroud)

在该页面上,当我单击按钮时,我在以下日志中有以下日志console.log

[我的组件] 属性 foo 从 bar 更改为 baz

[我的组件] 属性 foo 从 bar …

html javascript web-component custom-element

5
推荐指数
1
解决办法
1287
查看次数

在嵌套的 shadow DOM 中重新分配重复的槽元素

背景:这个问题与 Chrome 最新版本扩展的开发有关。它依赖于 javascript 功能,例如并非在所有浏览器上都可用的 HTML 导入和自定义元素,但在这种情况下是可以的。

我正在尝试实现一个简化的 HTML 自定义元素,如下所示:

<custom-el>
    <span slot="head">Great</span>

    <span slot="item">Item one</span>
    <span slot="item">Item two</span>

    <span slot="foot">done</span>
</custom-el>
Run Code Online (Sandbox Code Playgroud)

我注册了<custom-el>. 每次创建元素时,我的代码的自定义元素类都会附加一个影子根并附加到以下模板中的影子根内容:

<template id="main">
    <h1><slot name="head"></slot></h1>
    <ul>
        <slot name="item"></slot>
    </ul>
    <i><slot name="foot"></slot></i>
</template>
Run Code Online (Sandbox Code Playgroud)

我想将每个<span>属性重新分配slot="item"给负责呈现单个项目的辅助模板:

<template id="sub">
    <li><slot name="item"></slot></li>
</template>
Run Code Online (Sandbox Code Playgroud)

带属性的槽数name="item"不固定。它从数据库生成并定期更改。

我知道可以通过将 shadowRoot 附加到插槽的父元素并设置插槽的插槽属性来重新分配插槽,例如<slot name="item" slot="newItem">. 但我认为这在我的情况下不起作用,因为子模板需要包装每个项目实例,而不是项目列表。

我可以将影子根和子模板附加到主文档中的每个项目。这会起作用,但我的偏好是主模板导入并应用任何嵌套的 shadowRoots 和模板。这样,主文档只需要导入包含主模板的文件。组件细节的实现被封装在主模板html文件中。

我还可以使用slotchange事件和HTMLSlotElement.assignedNodes方法来拼凑脚本解决方案。但我宁愿不走那条路。

还有另一种方法吗?我的实际用例涉及更复杂的 HTML 结构。或者我的架构或对 Web 组件的理解有缺陷?

html web-component google-chrome-extension shadow-dom custom-element

5
推荐指数
1
解决办法
832
查看次数

在 shadow DOM 内部和外部使用非 shadow DOM 自定义元素

我有一个自定义元素(没有 shadow DOM),我希望能够在任何地方使用,甚至在另一个可能使用 shadow DOM 的自定义元素中。但是,我不确定如何让样式在这两个地方都有效。

例如,假设我创建了一个简单的fancy-button元素:

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

    this.innerHTML = `
      <style>
      fancy-button button {
        padding: 10px 15px;
        background: rgb(62,118,194);
        color: white;
        border: none;
        border-radius: 4px
      }
      </style>
      <button>Click Me</button>`;
  }
}

customElements.define('fancy-button', fancyButton);
Run Code Online (Sandbox Code Playgroud)
<fancy-button></fancy-button>
Run Code Online (Sandbox Code Playgroud)

在 shadow DOM 元素内,插入的样式标签将允许fancy-button样式工作。但是,如果在 shadow DOM 元素之外使用此组件,则每次使用该元素时都会复制样式标记。

相反,如果我将样式标记添加为 html 导入文件的一部分,那么样式只能在 shadow DOM 之外工作,但至少它们只声明一次。

<!-- fancy-button.html -->
<style>
fancy-button button {
  padding: 10px 15px;
  background: rgb(62,118,194);
  color: white;
  border: none;
  border-radius: 4px
}
</style>

<script> …
Run Code Online (Sandbox Code Playgroud)

html web-component shadow-dom custom-element

5
推荐指数
1
解决办法
3100
查看次数

Web 组件渲染性能

与原生 HTML 元素相比,Web 组件是否提供更好的性能。因为每个元素只有在附加到 DOM 时才会发生变异。因此,元素回调中的昂贵操作会导致性能不佳。

我写了一个示例 Web 组件,在 connectedCallback 句柄中有一些昂贵的实现,当我尝试渲染组件时,每个组件都以连续的顺序花费时间。

我在 Web Components 上没有看到任何与参考相关的性能指标。


更新 1

我创建了一个带有 Native 和 Web Component 实现的小页面,似乎 Web Components 页面需要 4ms 才能完成,但 Native 只需要 1ms。请参阅我的性能屏幕。在 Web 组件中,脚本编写需要更多时间。

原生 HTML 示例:

本机示例


Web 组件示例:

在此处输入图片说明

html javascript web-component html-rendering web-performance

5
推荐指数
3
解决办法
5377
查看次数

如何使用 CSS 选择子类自定义元素

考虑以下:

class MyElem extends HTMLElement {};
customElements.define('my-element', MyElem);

class MyMoreSpecificElem extends MyElem {};
customElements.define('my-more-specific-element', MyMoreSpecificElem);
Run Code Online (Sandbox Code Playgroud)

在对象继承的说法中,第二个类的实例与第一个类具有“is-a”关系: aMyMoreSpecificElem 是 a MyElem

这种关系在 JavaScript 中被捕获:

let subclassInstance = document.querySelector('my-more-specific-element');
let parentClass = document.querySelector('my-element').constructor;

subclassInstance instanceof parentClass; // true
Run Code Online (Sandbox Code Playgroud)

但是我想不出任何MyElem使用 CSS 选择器选择所有s(包括子类 MyMoreSpecificElem)的方法。标签选择器只会获得超类或子类,我知道的所有关系描述选择器(例如~、>)都是关于文档中的位置,而不是类层次结构。

我的意思是,当然,我可以在构造函数中添加一个 CSS 类并通过它进行选择,调用super将确保甚至可以以这种方式选择子类实例。但这很粗糙。有没有办法在纯 CSS 中做到这一点?

javascript css subclassing web-component custom-element

5
推荐指数
1
解决办法
596
查看次数

将函数传递给模板组件

是否可以将函数传递给stencilJs组件?

就像是:

@Prop() okFunc: () => void;
Run Code Online (Sandbox Code Playgroud)

我有一个模态,想Ok在模态页脚中单击的按钮上动态调用传递的函数,就像onClick在普通 HTML 按钮上一样。

html function stencils web-component

5
推荐指数
2
解决办法
4560
查看次数

Lit-elements,编写受控组件的惯用方式

我正在通过@open-wc使用lit-elements,目前正在尝试编写一组嵌套的组件,其中内部组件是一个输入字段,并且某些祖先组件必须支持一些任意重写规则,例如“不允许输入数字” '。

我想弄清楚的是使用 lit-elements 构建它的正确方法什么。在React 中,我会使用一个“受控组件”,在这里可以轻松地强制所有组件提交给根组件属性。

下面的示例是我使用 Lit-Elements 提出的。有没有更好的方法来做到这一点

请注意; 因为我想忽略一些字符,所以挑战变得稍微困难​​一些。如果没有e.target.value = this.value;at 级别 5,输入 elmement 将与忽略字符上的组件状态不同。我希望整个组件链正确同步,因此以标头标签为例。

export class Level1 extends LitElement {
  static get properties() {
    return {
      value: { type: String }
    };
  }

  render() {
    return html`
      <div>
        <h1>${this.value}</h1>
        <level-2 value=${this.value} @input-changed=${this.onInput}></level-2>
      </div>`;
  }

  onInput(e) {
    this.value = e.detail.value.replace(/\d/g, ''); 
  }
}

... …
Run Code Online (Sandbox Code Playgroud)

javascript web-component lit-element controlled-component

5
推荐指数
1
解决办法
643
查看次数

Web 组件 - 字体和材质图标不起作用 (@font-face)

我正在尝试通过运行以下命令使用 vue cli 3 创建一个 Web 组件

vue-cli-service build --target wc --name wc-demo 'src/App.vue'

我在 Web 组件中加载字体和材质图标时遇到问题。

我进口的Roboto-font.scss材料icon.scss的风格标签内App.vue这是用于创建Web组件条目。

<style lang='scss'>
// @import url('https://fonts.googleapis.com/css?family=Roboto:400,700&display=swap');
@import "~@/assets/fonts/roboto-font/roboto-font.scss";
@import "~@/assets/fonts/material-icons/material-icons.scss";
</style>
Run Code Online (Sandbox Code Playgroud)

Material-icon.scss

$font-dir: "assets/fonts/material-icons/web-font/";

@font-face {
  font-family: 'Material Icons';
  font-style: normal;
  font-weight: 400;
  // src: url('https://fonts.gstatic.com/s/materialicons/v48/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.woff2') format("woff2");

  src: url("#{$font-dir}flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.woff2") format("woff2"),
  url("#{$font-dir}flUhRq6tzZclQEJ-Vdg-IuiaDsNa.woff") format("woff");
}

.material-icons {
  font-family: 'Material Icons';
  font-weight: normal;
  font-style: normal;
  display: inline-block;
  line-height: 1;
  text-transform: none;
  letter-spacing: normal;
  word-wrap: normal;
  white-space: nowrap;
  direction: ltr;
} …
Run Code Online (Sandbox Code Playgroud)

fonts font-face web-component

5
推荐指数
1
解决办法
1106
查看次数

用于自定义 Web 组件的 Visual Studio Intellisense

我有一些 Web 组件自定义元素,在这种情况下是用 StencilJS 构建的。它们通过 npm 包安装到我的解决方案中,然后通过脚本标签全局包含在布局中。

如何让 Visual Studio 了解这些元素并在 .cshtml 视图中为自定义元素及其属性提供智能感知?

StencilJS 输出一个 TypeScript *.d.ts 文件,其中包含这些元素的定义,以及描述这些元素的其他 JSON 文件。Visual Studio 可以使用其中任何一个吗?

似乎可以通过在html.customData设置中添加引用来配置 Visual Studio Code 以使用此 JSON ,Visual Studio 是否有等效的东西?

visual-studio web-component stenciljs

5
推荐指数
1
解决办法
510
查看次数