我正在创建Aurelia组件,它们现在包装了material-components-web,cards specifically,并且想知道实现多个内容部分(操作等)的正确方法是什么。
插槽似乎是正确的选择,但我不能随时将动作div放在模板上,但只有在实际存在任何动作时才会出现。
简单地说,我需要检查是否在组件模板中定义了一个插槽。
<template>
<div class="card">
<div class="content">
<slot></slot>
</div>
<!-- somehow check here if the slot has been defined -->
<div class="actions">
<slot name="actions"></slot>
</div>
</div>
</template>
答案 0 :(得分:2)
开箱即用,没有直接的方法像$slots
属性那样执行此操作,但是您应该能够通过模板控制器实例本身访问插槽:au.controller.view.slots
- 此数组内部的特定插槽有关于插槽本身及其子节点的更多信息。
Here是具有模态组件(自定义模态元素)的Aurelia应用程序的示例。模态本身有一个插槽,可以在其中投影HTML。我们有标题,正文和页脚。
我们自定义元素中的每个预定义插槽都应显示在children
对象内,其中属性名称是插槽的名称。如果您没有为插槽(默认插槽)提供名称,则其内部名称为:__au-default-slot-key__
。
我们首先检查插槽是否存在然后检查其子节点的长度,每个插槽中都存在children
数组。如果插槽中没有投射HTML,则子节点长度为零。这是可靠的,因为在插槽内定义的默认内容不会放入children
数组中,只会投影HTML。
您将看到工作主要在modal.html
内完成,但要密切注意modal.js
,我们将注入自定义元素的元素引用,然后使用Aurelia实例访问au
到达包含我们插槽的控制器。
此方法有一点需要注意:您无法使用if.bind
有条件地删除自定义元素中的HTML。如果在包含插槽的DIV上使用if.bind
,它实际上会删除其插槽引用,因此无法检查它。要解决此问题,只需使用show.bind
(就像我在提供的运行示例中所做的那样)。
答案 1 :(得分:1)
CSS是这项工作的正确工具,而不是Aurelia。 :empty选择器将允许您在未填充插槽的情况下display: none
div.actions
。
.card .actions:empty {
display: none;
}
根据:empty selector spec如explained by CSS-Tricks,空白将导致空白无法匹配,因此我们只需要删除插槽周围的空白。>
<div class="actions"><slot name="actions"></slot></div>
此处的工作示例:https://gist.run/?id=040775f06aba5e955afd362ee60863aa
答案 2 :(得分:0)
这是我汇总的一种方法,用于检测是否有任何插槽有子级(HTML注释除外)
TypeScript
import { autoinject } from 'aurelia-framework';
@autoinject
export class MyClass {
private constructor(readonly element: Element) {
}
private attached() {
}
get hasSlotChildren(): boolean {
if (!this.element ||
!(this.element as any).au) {
return false;
}
let childrenCount = 0;
const slots = (this.element as any).au.controller.view.slots;
for (let slotName of Object.keys(slots)) {
const slot = slots[slotName];
if (slot.children &&
slot.children.length > 0) {
for (let child of slot.children) {
if (child instanceof Comment) {
// Ignore HTML comments
continue;
}
childrenCount++;
}
}
}
return childrenCount > 0
}
}
HTML
<template
class="my-class"
show.bind="hasSlotChildren"
>
<slot></slot>
</template>