带有占位符的 Web 组件和 JS DOM 元素
Web components and JS DOM Elements with a placeholder
最近,每个人都在跳上与框架无关的 Web 组件火车UI 元素。
当我阅读这篇文章时,它看起来是一种通过浏览器编写自定义元素的本机方式。但我有一个问题。它与 js 扩展 div(占位符) 以增强和提供我们需要的一些功能的方式有何不同。
例如:
如果我想要一个 table 组件
Web Component: <my-table></my-table>
---- JS中对应代码 --- 编译成js文件,在外部脚本中使用
JS方式:<div id="my-table"></div>
---- code in JS ---- 编译成JS在外部script标签中使用
我正在以 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);
两者的区别和优势是什么?请帮助
我的第一反应是,
What is the difference between ES5 and ES6? (unless you are still doing ES3)
差别太大了,很快就要做苹果和苹果的比较了。
阅读所有博客,使用自定义元素,学习。
TL;DR
使用DOM元素与Javascript - 需要顺序(1和2可以切换):
- 加载JavaScript
- 创建 DOM 个元素
- 运行JavaScript
- 转换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,调试,然后猛撞你的头……你在 ID 中打错了字……grid
和 gird
2 天后...
该死的!客户想要第四格!
在他第 5 次打扰您之前,您决定重构 ActivateGrids 函数以处理页面中任意数量的网格
[...document.querySelectorAll('[id*="MyuniQueIDgridComponent_KUT!"]')].forEach(...)
我们有组件!! Play: Queen, We are the Champions!
3 周后,客户有一个非常简单的要求,你可以在半小时内完成,他说。 我们要改变背景颜色,用一个属性就DIV
你被难住了!
更改具有 DIV 个属性的属性!?!
为什么他们不能直接调用 JavaScript 网格实例?!?
您几年前曾尝试教育客户;语义 HTML 没有未来!
只雇用高级 Web 开发人员...但他不听
<my-grid background=green></my-grid>
有什么意义
当你可以用 酷 程序员的方式做到时:
document.getElementById("myGird1").mySetPropperty("background","green");
但是客户支付了您的抵押贷款;
所以你了解了 MutationObserver,并将其贴在 BODY 标签上。
(这句话很容易写,但编码很费功夫!)
5 个月后,客户说他不想再雇用你了,因为 adding/removing 他们 SPA 中的网格导致内存泄漏。
输入自定义元素API(又名 Web 组件)
使用框架,以上所有内容(只是稍微)更容易..
但是您想构建一个可重复使用的组件,而不是构建一个使用 组件
的应用程序
所以您决定使用原生自定义元素API
您考虑过使用 Lit 或 Stencil 或 Hybrids 或 Component Libray X;
但决定反对他们。
使用 Native JavaScript 只需要几行额外的代码,
但最重要的是,您不想引入依赖项(您还记得早期 jQuery 的日子,那里有许多替代方案,您不得不放弃 $$$ 项目,因为开发人员选择了 Mootools)
Native JavaScript will work as long as JavaScript is supported in the Browser.
您设计(最终)用户将如何使用您的组件:
<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 的时刻,那个时刻就是现在.. even Microsoft said so over a year ago
适用于所有框架和库
(除了在 React 中你需要做额外的工作..
因为 Facebook 仍然试图将他们的 'standard' 强加给世界其他地方)
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>
Cue Tom Lehrer 的 Elements 歌曲:https://www.youtube.com/watch?v=AcS3NOQnsQM
自定义元素还有更多内容
<slot></slot>
- shadowParts
::part
- Constructable StyleSheets
- 扩展 HTML 个元素,因此只有一个标签
<img is=flag-india>
displays a SVG flag
- ...
- ...
你可以玩KCB-Grid
在这个 JSFiddle 中:https://jsfiddle.net/CustomElementsExamples/nk9co3bu/
最近,每个人都在跳上与框架无关的 Web 组件火车UI 元素。 当我阅读这篇文章时,它看起来是一种通过浏览器编写自定义元素的本机方式。但我有一个问题。它与 js 扩展 div(占位符) 以增强和提供我们需要的一些功能的方式有何不同。
例如:
如果我想要一个 table 组件
Web Component: <my-table></my-table>
---- JS中对应代码 --- 编译成js文件,在外部脚本中使用
JS方式:<div id="my-table"></div>
---- code in JS ---- 编译成JS在外部script标签中使用
我正在以 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);
两者的区别和优势是什么?请帮助
我的第一反应是,
What is the difference between ES5 and ES6? (unless you are still doing ES3)
差别太大了,很快就要做苹果和苹果的比较了。
阅读所有博客,使用自定义元素,学习。
TL;DR
使用DOM元素与Javascript - 需要顺序(1和2可以切换):
- 加载JavaScript
- 创建 DOM 个元素
- 运行JavaScript
- 转换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,调试,然后猛撞你的头……你在 ID 中打错了字……grid
和gird
2 天后...
该死的!客户想要第四格!
在他第 5 次打扰您之前,您决定重构 ActivateGrids 函数以处理页面中任意数量的网格
[...document.querySelectorAll('[id*="MyuniQueIDgridComponent_KUT!"]')].forEach(...)
我们有组件!! Play: Queen, We are the Champions!
3 周后,客户有一个非常简单的要求,你可以在半小时内完成,他说。 我们要改变背景颜色,用一个属性就DIV
你被难住了!
更改具有 DIV 个属性的属性!?!
为什么他们不能直接调用 JavaScript 网格实例?!?您几年前曾尝试教育客户;语义 HTML 没有未来!
只雇用高级 Web 开发人员...但他不听
有什么意义<my-grid background=green></my-grid>
当你可以用 酷 程序员的方式做到时:
document.getElementById("myGird1").mySetPropperty("background","green");
但是客户支付了您的抵押贷款;
所以你了解了 MutationObserver,并将其贴在 BODY 标签上。
(这句话很容易写,但编码很费功夫!)5 个月后,客户说他不想再雇用你了,因为 adding/removing 他们 SPA 中的网格导致内存泄漏。
输入自定义元素API(又名 Web 组件)
使用框架,以上所有内容(只是稍微)更容易..
但是您想构建一个可重复使用的组件,而不是构建一个使用 组件
的应用程序所以您决定使用原生自定义元素API
您考虑过使用 Lit 或 Stencil 或 Hybrids 或 Component Libray X;
但决定反对他们。
使用 Native JavaScript 只需要几行额外的代码,
但最重要的是,您不想引入依赖项(您还记得早期 jQuery 的日子,那里有许多替代方案,您不得不放弃 $$$ 项目,因为开发人员选择了 Mootools)
Native JavaScript will work as long as JavaScript is supported in the Browser.
您设计(最终)用户将如何使用您的组件:
<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 的时刻,那个时刻就是现在.. even Microsoft said so over a year ago适用于所有框架和库
(除了在 React 中你需要做额外的工作..
因为 Facebook 仍然试图将他们的 'standard' 强加给世界其他地方)
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>
Cue Tom Lehrer 的 Elements 歌曲:https://www.youtube.com/watch?v=AcS3NOQnsQM
自定义元素还有更多内容
<slot></slot>
- shadowParts
::part
- Constructable StyleSheets
- 扩展 HTML 个元素,因此只有一个标签
<img is=flag-india>
displays a SVG flag - ...
- ...