是否可以将自定义属性/属性注入本机 Web 组件?
Is it possible to inject custom attributes / properties into native web components?
我正在学习网络组件(本机和框架)。是否可以像我在 Vue.js?
中那样将属性注入本机组件
这是我的-component.js:
const templateComponent = document.createElement('template');
templateComponent.innerHTML = `<div>{{ test }}</div>`;
class MyComponent extends HTMLElement {
connectedCallback() {
this._container = this.querySelector("DIV");
}
}
window.customElements.define("my-component", MyComponent);
这是index.html:
<!doctype html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<my-component test="Does this work?"></my-component>
<script src="my-component.js"></script>
</body>
</html>
是也不是。
没有内置模板。但这并不意味着你做不到。
function render(el) {
el.shadowRoot.innerHTML = `<div>${el._test}</div>`;
}
class MyComponent extends HTMLElement {
static get observedAttributes() {
return ['test'];
}
constructor() {
super();
this.attachShadow({mode: 'open'});
}
attributeChangedCallback(attrName, oldVal, newVal) {
if (oldVal !== newVal) {
this[`_${attrName}`] = newVal;
render(this);
}
}
}
window.customElements.define("my-component", MyComponent);
<my-component test="Does this work?"></my-component>
<my-component test="Yes it does"></my-component>
您使用 observedAttributes
来指示您想要监视哪些属性的变化。当其中之一发生变化时,您使用 attributeChangedCallback
作为处理程序。
然后就看你把属性值取到DOM中了。如果 DOM 很简单,你可以像我一样做,每次都重新生成它。
更复杂的东西需要更复杂的算法。
有些人会告诉您使用 LITHtml。我觉得这很烦人。我的大部分组件都非常小,不需要那么复杂。
扩展
是的,您可以将回调函数作为字符串传递。换句话说,您将回调函数的名称作为字符串传递,然后在您的组件中调用 eval
。 但是 我不推荐它。这样做有很多限制,并且可以用于邪恶和邪恶的目的。 :)
改为:
- 在可以设置回调函数的组件上提供一个属性。
- 在您将使用回调函数调用的组件上提供一个函数
- 从组件调度事件并让
addEventListener
为您处理。你能提供更多关于你想用这个函数做什么的细节吗
这里有两个有用的 questions/answers:
*
*
更新
问题是在设置了多个属性或属性时,如何避免比需要更频繁地渲染。这通常称为 "debouncing".
这是一个选项:
let renderTimeout = null;
function render(el) {
if (renderTimeout) {
clearTimeout(renderTimeout);
}
renderTimeout = setTimeout(() => {
el.shadowRoot.innerHTML = `<div>${el._test}</div>`;
}, 0);
}
这将设置一个 0
超时,这意味着它将尽快发生,通常是在当前代码完成后立即发生 运行。然后会发生渲染操作。
我正在学习网络组件(本机和框架)。是否可以像我在 Vue.js?
中那样将属性注入本机组件这是我的-component.js:
const templateComponent = document.createElement('template');
templateComponent.innerHTML = `<div>{{ test }}</div>`;
class MyComponent extends HTMLElement {
connectedCallback() {
this._container = this.querySelector("DIV");
}
}
window.customElements.define("my-component", MyComponent);
这是index.html:
<!doctype html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<my-component test="Does this work?"></my-component>
<script src="my-component.js"></script>
</body>
</html>
是也不是。
没有内置模板。但这并不意味着你做不到。
function render(el) {
el.shadowRoot.innerHTML = `<div>${el._test}</div>`;
}
class MyComponent extends HTMLElement {
static get observedAttributes() {
return ['test'];
}
constructor() {
super();
this.attachShadow({mode: 'open'});
}
attributeChangedCallback(attrName, oldVal, newVal) {
if (oldVal !== newVal) {
this[`_${attrName}`] = newVal;
render(this);
}
}
}
window.customElements.define("my-component", MyComponent);
<my-component test="Does this work?"></my-component>
<my-component test="Yes it does"></my-component>
您使用 observedAttributes
来指示您想要监视哪些属性的变化。当其中之一发生变化时,您使用 attributeChangedCallback
作为处理程序。
然后就看你把属性值取到DOM中了。如果 DOM 很简单,你可以像我一样做,每次都重新生成它。
更复杂的东西需要更复杂的算法。
有些人会告诉您使用 LITHtml。我觉得这很烦人。我的大部分组件都非常小,不需要那么复杂。
扩展
是的,您可以将回调函数作为字符串传递。换句话说,您将回调函数的名称作为字符串传递,然后在您的组件中调用 eval
。 但是 我不推荐它。这样做有很多限制,并且可以用于邪恶和邪恶的目的。 :)
改为:
- 在可以设置回调函数的组件上提供一个属性。
- 在您将使用回调函数调用的组件上提供一个函数
- 从组件调度事件并让
addEventListener
为您处理。你能提供更多关于你想用这个函数做什么的细节吗
这里有两个有用的 questions/answers:
*
更新
问题是在设置了多个属性或属性时,如何避免比需要更频繁地渲染。这通常称为 "debouncing".
这是一个选项:
let renderTimeout = null;
function render(el) {
if (renderTimeout) {
clearTimeout(renderTimeout);
}
renderTimeout = setTimeout(() => {
el.shadowRoot.innerHTML = `<div>${el._test}</div>`;
}, 0);
}
这将设置一个 0
超时,这意味着它将尽快发生,通常是在当前代码完成后立即发生 运行。然后会发生渲染操作。