javascript - 带有占位符的 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);
一个比另一个有什么区别和好处?请帮忙
解决方案
我的第一反应是,
ES5 和 ES6 有什么区别?(除非你还在做 ES3)
有很多差异,很快就会成为苹果和苹果的比较。
阅读那里的所有博客,使用自定义元素,学习。
TL;博士
使用带有 Javascript 的 DOM 元素 -需要顺序(可以切换 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,调试,然后猛击你的脑袋……你在 de ID 中打错了……grid
和gird
两天后……
该死!客户想要第四格!
在他第 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
还有更多自定义元素
<slot></slot>
- 阴影部分
::part
- 可构造样式表
- 扩展 HTML 元素,使单个标签
<img is=flag-india>
显示 SVG 标志 - ...
- ...
你可以玩 KCB-Grid
在这个 JSFiddle 中:https ://jsfiddle.net/CustomElementsExamples/nk9co3bu/
推荐阅读
- javascript - 使用 angular-modal-service 在 Firefox 中以全屏模式破坏图像
- javascript - 类型“T [keyof T]”上不存在属性“toLowerCase”
- android-studio - Android Studio 和 Capacitor 找不到 console.log() 输出
- python - 我无法在 aws rdp 中访问 mongodb 集群
- python-3.x - 如何在python中高精度地将浮点数转换为整数比?
- flutter - 如何在颤动中播放特定持续时间的彩票动画
- android - 远程ADB识别设备,但本地ADB说离线,Android Studio说断开连接
- mysql - 如何找到 Google App Script 的客户端 IP
- r - 如何使用向量在数据框中添加列?
- optimization - 文档集!中断执行