为了遵守 DRY 原则,我想创建一个基于
<template>
的自定义组件。代码看起来像这样(请原谅我在通宵达旦后在手机上打字时的偷工减料):
// base.html
<template id="player">
<div class="card">
<div class="card-body">
<slot name="user-username"></slot>
</div>
</div>
</template>
// app.js
class PlayerCard extends HTMLElement {
constructor(){
super();
let tmpl = querySelector...;
this.appendChild(tmpl.content.cloneNode();
}
}
define('player-card', PlayerCard);
// index.html
{% for user in users %}
<player-card>
<div slot="user-username">{{ user }}</div>
</player-card>
{% end for %}
但是在梦想破灭和长时间的研究之后,我了解到插槽只能在 Shadow DOM 中使用。使用 SDOM 的问题是内部样式受到保护,不能直接受外部 CSS 影响。
这意味着,一方面,我无法将数据注入到模板实例中,也无法在不重新实现 Bootstrap 的情况下使用 Shadow DOM。
我被困住了。对我的大脑来说,一定有一种方法可以实现这一点,但我的大脑无法找到它 - 要么因为它太复杂,要么因为它太琐碎和容易。
请问有什么建议吗?
是的,
<SLOT>s
只能在shadowDOM内部使用
但是您可以使用样式槽做更多事情。
有关详细答案,请参阅:::用于shadowDOM插槽中嵌套子项的开槽CSS选择器
customElements.define('player-card', class extends HTMLElement {
constructor() {
let template = (id) => document.getElementById(id).content.cloneNode(true);
super()
.attachShadow({mode: 'open'})
.append(template(this.nodeName));
this.onclick = (evt) => this.style.color='blue';
}
});
/* GLOBAL CSS */
player-card { /* inheritable styles trickle down into shadowDOM */
font: 20px Arial;
color: green;
}
[slot="username"] { /* lightDOM styles are REFLECTED to SLOTs */
width: 200px;
border: 2px solid green;
}
<template id="PLAYER-CARD">
<style shadowDOM-CSS >
div { /* styles do not style content in SLOTs */
padding: 1em;
background:gold;
}
::slotted(*) { /* slotted can only style the lightDOM 'skin' */
background: lightgreen;
}
</style>
<div>
<slot name="username"></slot>
</div>
</template>
<player-card>
<!-- lightDOM, hidden when shadowDOM is used, then REFLECTED to SLOT -->
<div slot="username">Ahmed</div>
</player-card>
<player-card>
<!-- lightDOM, hidden when shadowDOM is used, then REFLECTED to SLOT -->
<div slot="username">Danny</div>
</player-card>
Danny 是对的,但还值得一提的是 外部样式表可以通过 Web 组件使用 100% 原始代码导入。您的组件可以访问该样式表的规则,对于敏锐的开发人员来说,您会很高兴知道浏览器将从其缓存中获取它,而不是发出另一个请求(假设之前已下载)。像这样:
<!-- Component's template -->
<template>
<p>I'm salmon colored!</p>
<button ord="primary">Primary button styles come from the imported stylesheet</button>
<div class="fnt-bold">Bold class also comes from the imported stylesheet</div>
<!-- Component's styles -->
<style>
/* Importing global stylesheets will penetrate shadow DOM. Browsers use cached file if already downloaded. */
@import "https://unpkg.com/[email protected]/dist/m-min.css";
/* :host selects the custom element, i.e. <x-counter>, not the template. */
:host { display: block }
/* Anything else is scoped to this template. */
p { color: lightsalmon }
</style>
</template>
完整示例:https://github.com/jfbrennan/single-file-web-component/blob/master/x-counter.html#L15
我不记得在哪里学到了有关导入的知识,但如果我能找到资源,我会更新我的答案。