有没有一个way/workaround在不使用ShadowDOM的情况下在hyperHTML中有插槽原理?
Is there a way/workaround to have the slot principle in hyperHTML without using Shadow DOM?
我喜欢 hyperHtml 和 lit-html 的简单性,它们使用 'Tagged Template Literals' 仅更新模板的 'variable parts'。简单 javascript,不需要虚拟 DOM 代码和推荐的不可变状态。
我想尝试尽可能简单地将自定义元素与 hyperHtml 结合使用
在模板中支持 <slot/>
原则,但没有 Shadow DOM。如果我没看错的话,插槽只能用 Shadow DOM?
有没有一种方法或解决方法可以在不使用 Shadow DOM 的情况下在 hyperHTML 中使用 <slot/>
原则?
<my-popup>
<h1>Title</h1>
<my-button>Close<my-button>
</my-popup>
虽然有好处,但有些原因我不想使用 Shadow DOM:
- 我想看看我是否可以转换我现有的 SPA:所有必需的 CSS 样式现在存在于 SASS 个文件中,并编译为 1 个 CSS 文件。在 Shadow DOM 组件 is not easily possible 中使用全局 CSS,我不想解开 SASS(现在)
- 阴影 DOM 有一些性能成本
- 我不希望大阴影 DOM polyfill 有插槽(webcomponents-lite.js:84KB - 未缩小)
让我开始描述什么是槽以及它们解决的问题。
刚刚停放数据
在您的布局中设置插槽是 HTML 尝试让您在布局中放置一些数据,稍后通过 JavaScript 解决它。
你甚至不需要 Shadow DOM 来使用槽,你只需要一个带有命名槽的模板,它将把值放在适当的位置。
<user-data>
<img src="..." slot="avatar">
<span slot="nick-name">...</span>
<span slot="full-name">...</span>
</user-data>
你能找出该组件与以下组件之间的区别吗 JavaScript?
const userData = {
avatar: '...',
nickName: '...',
fullName: '...'
};
换句话说,使用像下面这样的函数,我们已经可以将槽转换为由属性寻址的有用数据。
function slotsAsData(parent) {
const data = {};
parent.querySelectorAll('[slot]').forEach(el => {
// convert 'nick-name' into 'nickName' for easy JS access
// set the *DOM node* as data property value
data[el.getAttribute('slot').replace(
/-(\w)/g,
([=12=], ) => .toUpperCase())
] = el; // <- this is a DOM node, not a string ;-)
});
return data;
}
插槽作为超HTML插值
既然我们已经找到了解决插槽的方法,我们所需要的就是将它们放置在我们的布局中的方法。
理论上,我们不需要自定义元素即可实现。
document.querySelectorAll('user-data').forEach(el => {
// retrieve slots as data
const data = slotsAsData(el);
// place data within a more complex template
hyperHTML.bind(el)`
<div class="user">
<div class="avatar">
${data.avatar}
</div>
${data.nickName}
${data.fullName}
</div>`;
});
但是,如果我们想使用 Shadow DOM 来保护样式和节点免受不需要的页面/第 3 部分污染,我们可以根据自定义元素按照 this Code Pen example 中所示进行操作.
如您所见,唯一需要的 API 是 attachShadow,还有一个超级 lightweight polyfill for just that,最小压缩重量为 1.6K。
最后但并非最不重要的一点是,您可以在 hyperHTML 模板文字中使用插槽并让浏览器进行转换,但这需要更重的 polyfill,我不建议在生产中使用它,特别是当存在是更好更轻便的替代品,如此处所示。
希望这个回答对您有所帮助。
我有类似的方法,我创建了一个基本元素(来自 HyperElement),它检查构造函数中自定义元素内的子元素,如果该元素没有插槽属性,我只是将它们发送到默认插槽
import hyperHTML from 'hyperhtml/esm';
class HbsBase extends HyperElement {
constructor(self) {
self = super(self);
self._checkSlots();
}
_checkSlots() {
const slots = this.children;
this.slots = {
default: []
};
if (slots.length > 0) {
[...slots].map((slot) => {
const to = slot.getAttribute ? slot.getAttribute('slot') : null;
if (!to) {
this.slots.default.push(slot);
} else {
this.slots[to] = slot;
}
})
}
}
}
自定义元素,我正在使用自定义汇总插件加载模板
import template from './customElement.hyper.html';
class CustomElement extends HbsBase {
render() {
template(this.html, this, hyperHTML);
}
}
然后在模板上customElement.hyper.html
<div>
${model.slots.body}
</div>
使用元素
<custom-element>
<div slot="body">
<div class="row">
<div class="col-sm-6">
<label for="" class="">Name</label>
<p>
<a href="#">${model.firstName} ${model.middleInitial} ${model.lastName}</a>
</p>
</div>
</div>
...
</div>
</custom-element>
没有阴影的插槽 dom 受多个实用程序和框架的支持。
Stencil 启用 without shadow DOM enabled. slotted-element 无需框架即可提供支持。
我喜欢 hyperHtml 和 lit-html 的简单性,它们使用 'Tagged Template Literals' 仅更新模板的 'variable parts'。简单 javascript,不需要虚拟 DOM 代码和推荐的不可变状态。
我想尝试尽可能简单地将自定义元素与 hyperHtml 结合使用
在模板中支持 <slot/>
原则,但没有 Shadow DOM。如果我没看错的话,插槽只能用 Shadow DOM?
有没有一种方法或解决方法可以在不使用 Shadow DOM 的情况下在 hyperHTML 中使用 <slot/>
原则?
<my-popup>
<h1>Title</h1>
<my-button>Close<my-button>
</my-popup>
虽然有好处,但有些原因我不想使用 Shadow DOM:
- 我想看看我是否可以转换我现有的 SPA:所有必需的 CSS 样式现在存在于 SASS 个文件中,并编译为 1 个 CSS 文件。在 Shadow DOM 组件 is not easily possible 中使用全局 CSS,我不想解开 SASS(现在)
- 阴影 DOM 有一些性能成本
- 我不希望大阴影 DOM polyfill 有插槽(webcomponents-lite.js:84KB - 未缩小)
让我开始描述什么是槽以及它们解决的问题。
刚刚停放数据
在您的布局中设置插槽是 HTML 尝试让您在布局中放置一些数据,稍后通过 JavaScript 解决它。
你甚至不需要 Shadow DOM 来使用槽,你只需要一个带有命名槽的模板,它将把值放在适当的位置。
<user-data>
<img src="..." slot="avatar">
<span slot="nick-name">...</span>
<span slot="full-name">...</span>
</user-data>
你能找出该组件与以下组件之间的区别吗 JavaScript?
const userData = {
avatar: '...',
nickName: '...',
fullName: '...'
};
换句话说,使用像下面这样的函数,我们已经可以将槽转换为由属性寻址的有用数据。
function slotsAsData(parent) {
const data = {};
parent.querySelectorAll('[slot]').forEach(el => {
// convert 'nick-name' into 'nickName' for easy JS access
// set the *DOM node* as data property value
data[el.getAttribute('slot').replace(
/-(\w)/g,
([=12=], ) => .toUpperCase())
] = el; // <- this is a DOM node, not a string ;-)
});
return data;
}
插槽作为超HTML插值
既然我们已经找到了解决插槽的方法,我们所需要的就是将它们放置在我们的布局中的方法。
理论上,我们不需要自定义元素即可实现。
document.querySelectorAll('user-data').forEach(el => {
// retrieve slots as data
const data = slotsAsData(el);
// place data within a more complex template
hyperHTML.bind(el)`
<div class="user">
<div class="avatar">
${data.avatar}
</div>
${data.nickName}
${data.fullName}
</div>`;
});
但是,如果我们想使用 Shadow DOM 来保护样式和节点免受不需要的页面/第 3 部分污染,我们可以根据自定义元素按照 this Code Pen example 中所示进行操作.
如您所见,唯一需要的 API 是 attachShadow,还有一个超级 lightweight polyfill for just that,最小压缩重量为 1.6K。
最后但并非最不重要的一点是,您可以在 hyperHTML 模板文字中使用插槽并让浏览器进行转换,但这需要更重的 polyfill,我不建议在生产中使用它,特别是当存在是更好更轻便的替代品,如此处所示。
希望这个回答对您有所帮助。
我有类似的方法,我创建了一个基本元素(来自 HyperElement),它检查构造函数中自定义元素内的子元素,如果该元素没有插槽属性,我只是将它们发送到默认插槽
import hyperHTML from 'hyperhtml/esm';
class HbsBase extends HyperElement {
constructor(self) {
self = super(self);
self._checkSlots();
}
_checkSlots() {
const slots = this.children;
this.slots = {
default: []
};
if (slots.length > 0) {
[...slots].map((slot) => {
const to = slot.getAttribute ? slot.getAttribute('slot') : null;
if (!to) {
this.slots.default.push(slot);
} else {
this.slots[to] = slot;
}
})
}
}
}
自定义元素,我正在使用自定义汇总插件加载模板
import template from './customElement.hyper.html';
class CustomElement extends HbsBase {
render() {
template(this.html, this, hyperHTML);
}
}
然后在模板上customElement.hyper.html
<div>
${model.slots.body}
</div>
使用元素
<custom-element>
<div slot="body">
<div class="row">
<div class="col-sm-6">
<label for="" class="">Name</label>
<p>
<a href="#">${model.firstName} ${model.middleInitial} ${model.lastName}</a>
</p>
</div>
</div>
...
</div>
</custom-element>
没有阴影的插槽 dom 受多个实用程序和框架的支持。 Stencil 启用 without shadow DOM enabled. slotted-element 无需框架即可提供支持。