首页 > 解决方案 > 带有占位符的 Web 组件和 JS DOM 元素

问题描述

最近,每个人都在跳上与框架无关的 UI 元素的 Web 组件火车。虽然我正在阅读此内容,但它看起来是一种通过浏览器编写自定义元素的本机方式。但我有一个问题。它与扩展 div(占位符)以增强和提供我们需要的一些功能的 js 方式有何不同。

例如:如果我想要一个表格组件Web组件:<my-table></my-table>----JS中的相应代码---编译为js文件并在外部脚本中使用

JS方式:<div id="my-table"></div>---- JS中的代码---- 编译成JS并在外部脚本标签中使用我以ag-grid的例子来说明清楚

例如:ag-grid https://www.ag-grid.com/javascript-grid/

<div id="myGrid" style="height: 200px; width:500px;" class="ag-theme-alpine"></div>

new agGrid.Grid(gridDiv, gridOptions);

一个比另一个有什么区别和好处?请帮忙

标签: javascriptwebpolymerweb-component

解决方案


我的第一反应是,

ES5 和 ES6 有什么区别?(除非你还在做 ES3)

有很多差异,很快就会成为苹果和苹果的比较。

阅读那里的所有博客,使用自定义元素,学习。


TL;博士

  • 使用带有 Javascript 的 DOM 元素 -需要顺序(可以切换 1 和 2)

    1. 加载 JavaScript
    2. 创建 DOM 元素
    3. 运行 JavaScript
    4. 转换 DOM 元素
  • 使用自定义元素 API:-顺序无关紧要

  • 创建自定义 DOM 元素

  • 加载 JavaScript


差异和好处

假设客户想要页面上的三个网格:

  • 添加 3 个 DIV:
    <div id="myGrid1" .../>
    <div id="myGrid2" .../>
    <div id="myGrid3" .../>

  • 要激活它们,您还必须添加:
    new agGrid.Grid(document.getElementById("myGird1")
    new agGrid.Grid(document.getElementById("myGird2")
    new agGrid.Grid(document.getElementById("myGird3")

  • 如果 JavaScript在DOM 元素存在之前
    执行,就会出现严重错误 所以你添加一个事件监听器:
    window.addEventListner("onload",()=>ActivateGrids());

请注意您必须如何在此处添加(某种类型的)全局函数;
所以请交叉手指,没有其他人会覆盖您宝贵的代码;

  • 考虑到上述影响,您决定谨慎行事:

    • 您将所有 ID 重命名为真正独特的东西(而且非常不可读)
    • 您将所有 BEM 选择器重命名为真正唯一(且不可读)的名称
    • React、Angular、Vue (部分)为您执行此操作,
      但您执行的是 Native JavaScript,因此必须手动执行。
  • 为什么它不起作用?
    你按下 F12,调试,然后猛击你的脑袋……你在 de ID 中打错了……gridgird

  • 两天后……
    该死!客户想要第四格!
    在他第 5 次骚扰您之前,您决定重构您的 ActivateGrids 函数以处理页面中的任意数量的网格

[...document.querySelectorAll('[id*="MyuniQueIDgridComponent_KUT!"]')].forEach(...)

我们有一个组件!!播放:女王,我们是冠军!

  • 3 周后,客户有一个非常简单的要求,你可以在半小时内完成,他说。我们要改变背景颜色,在DIV上有一个属性

  • 你被难住了!
    使用 DIV 属性更改属性!?!
    为什么他们不能只调用 JavaScript Grid 实例?!?

    多年前您曾尝试教育客户;语义 HTML 没有未来!
    只雇用高级 Web 开发人员……但他不听

    有什么意义<my-grid background=green></my-grid>

    当你可以用很酷的程序员方式做到这一点时:

    document.getElementById("myGird1").mySetPropperty("background","green");

    但是客户支付了您的抵押贷款;
    所以你了解了一个 MutationObserver,并将它贴在 BODY 标签上。
    这句话很容易写,但需要认真编码!

  • 5 个月后,客户说他不想再雇用你了,因为在他们的 SPA 中添加/删除网格会导致内存泄漏。

输入自定义元素 API(又名 Web 组件)

使用框架,以上所有内容(仅略微)更容易。

但是你想构建一个可重用的组件,而不是一个组件构建的应用程序

  • 所以你决定使用 Native Custom Elements API

    您考虑过使用 Lit 或 Stencil 或 Hybrids 或 Component Libray X;
    但决定反对他们。
    使用 Native JavaScript 只需要几行额外的代码,
    但最重要的是你不想引入依赖项(你记得早期的 jQuery 时代,那里有十几个替代方案,你不得不放弃一个 $$$ 项目,因为开发人员选择了 Mootools )

只要浏览器支持 JavaScript,本机JavaScript 就可以工作。

  • 您设计(最终)用户将如何使用您的组件:

    <KCB-grid rows=3 columns=5 background=color ></KCB-grid>

  • 然后对组件进行编程。
    我从你的 Twitter 句柄中获取了KCB-
    命名空间 这个命名空间(就像你的全局函数一样)需要在页面
    中是唯一的 请参见下面的代码,它是一个文本字符串,因此可以动态创建!
    <KCB-Grid-Customer rows=3 columns=5 background=color ></KCB-grid-Customer>

  • 适用于任何现代浏览器
    IE11 有一个 polyfill;但坦率地说,避免使用 IE11。
    您在 9 年前停止支持 IE。有一段时间停止支持 IE11,那一刻就是现在..甚至微软一年多前就这么说过

  • 适用于所有框架和库
    (除了在 React 中你需要做额外的工作。
    因为 Facebook 仍然试图将他们的“标准”强加到世界其他地方)
    https://custom-elements-everywhere.com/libraries/react /results/results.html

  • 没有onload问题,在脚本之前或之后声明元素都没有关系。自定义元素自动升级。

  • 你可以随时做.innerHTML = "<KCB-Grid></KCB-Grid>"
    客户也希望这样
    做,但聘请了另一位程序员使用下面的自定义元素来完成

  • 没有 CSS 选择器唯一性问题......而且可能根本不做 BEM

  • rows并且columns可以随时更改
    运行代码片段,单击网格

<template id="KCB-GRID">
  <!-- use TEMPLATES! don't mess with JSX, CSSinJS or HTML in textstrings! -->
  <style>
    #grid { /* no BEM, no forced unique IDs or style names */
      display: grid;
      grid-template-columns: repeat(var(--columns), 1fr);
      grid-auto-rows:        minmax(min-content, max-content);
      gap: .2em;
    }
    #grid div {
      background: var(--background);
      text-align: center;
    }
  </style>
  <div id=grid></div>
</template>

<KCB-Grid columns=5 rows=3 background=#FF9933></kcb-grid>
<KCB-Grid columns=3 rows=3 background=white  ></kcb-grid>
<KCB-Grid columns=4 rows=3 background=#138808></kcb-grid>

<script>
  customElements.define('kcb-grid', class extends HTMLElement {
    static get observedAttributes() {
      return [ "columns", "rows" ] // only these can be changed at any time
    }
    constructor() {
      super().attachShadow({ mode: 'open' })
             .append(document.getElementById(this.nodeName).content.cloneNode(true));
      this.grid = this.shadowRoot.querySelector("#grid");
    }
    connectedCallback() {
      const random = (x, y) => Math.floor(Math.random() * (y + 1 - x) + x);
      this.setProperty("background");
      this.grid.onclick = () => {
                this.setAttribute("columns", random(2, 6));
                this.setAttribute("rows",    random(2, 4));
      }
    }
    attributeChangedCallback(name, oldValue, newValue) {
      let columns = this.setProperty("columns");
      let rows =    this.setProperty("rows"   );
      this.grid.innerHTML = "<div>Hello World!</div>".repeat(columns * rows);
    }
    setProperty(name, value = this.getAttribute(name)) {
      this.grid.style.setProperty("--" + name, value);
      return value;
    }
    disconnectedCallback() {} //clean memory, remove listeners, etc.
  });
</script>

提示 Tom Lehrer 的Elements歌曲:https ://www.youtube.com/watch?v=AcS3NOQnsQM

还有更多自定义元素

你可以玩 KCB-Grid

在这个 JSFiddle 中:https ://jsfiddle.net/CustomElementsExamples/nk9co3bu/


推荐阅读