简介

组件(Components)

组件让你可以将应用的 UI 拆分为带有隔离状态的可复用片段。你可以使用组件来定义布局,或者创建一组不同的 UI 元素。

在进一步讨论组件之前,让我们先理解它们与前端生态中的组件有何不同。

  • 无响应式:由于 Edge 是一个后端模板引擎,Edge 及其组件层中都没有响应式的概念。

  • 不支持 CSS 或前端 JavaScript:Edge 模板不会经过构建工具处理。因此我们不会处理内联 CSS,也不会创建前端打包产物。

创建组件

组件就是普通的 Edge 模板,创建的初衷是为了复用。组件可以访问额外的运行时属性,如 $props$slots,这些是其他 Edge 模板无法访问的。

我们建议你在模板根路径下的 components 目录中创建组件。这有助于在组件与应用使用的其他模板之间建立视觉边界。

我们先来创建一个按钮组件。将其存放在 components/button.edge 文件中。

views/components/button.edge
<button type="{{ type || 'submit' }}"> {{ text }} </button>

使用组件

你必须使用 @component 标签在模板中渲染组件。component 标签接受模板路径作为第一个参数,并将 props 作为第二个参数。

<form>
@!component('components/button', { text: 'Login' })
@!component('components/button', { text: 'Cancel', type: 'reset' })
</form>

输出

<form>
<button type="submit"> Login </button>
<button type="reset"> Cancel </button>
</form>

来自具名磁盘的组件可以通过在前面加上磁盘名来引用。

@!component('uikit::components/button', { text: 'Login' })

传递 props

组件 props 通过 @component 标签的第二个参数传递。Props 始终表现为一个对象,你可以在组件模板中通过对象属性名来访问它们。

另请参阅:Props 参考

@component('components/button', {
type: 'submit',
class: 'btn btn-large',
text: 'Login'
})
在组件内部
{{ type }}
{{ class }}
{{ text }}

另一种访问 props 的方式是使用 $props 属性。例如:

{{ $props.get('type') }}
{{ $props.get('class') }}
{{ $props.get('text') }}

使用插槽(Slots)

插槽是带有内部标记、具名的输出口。由于在 props 中编写 HTML 标记很快就会变得混乱,插槽提供了更好的编写体验。

在下面的示例中,我们使用 $slots.main 函数渲染主插槽的内容。

另请参阅:Slots 参考

<button {{ $props.toAttrs() }}>
{{{ await $slots.main() }}}
</button>

main 插槽的内容位于开始与结束标签之间。

@component('components/button', {
class: ['flex', 'align-center', 'space-x-4']
})
<i class="fa-lock"></i>
<span> Login </span>
@end

以标签形式引用组件

Edge 允许你以标签的形式引用组件。因此,除了使用 @component 标签,你还可以使用组件文件名作为标签名来渲染它。

以标签形式引用组件仅适用于存放在 components 目录中的组件。

views/component/modal.edge
<div class="modal">
<header>
{{{ await $slots.header() }}}
</header>
<main>
{{{ await $slots.content() }}}
</main>
<footer>
{{{ await $slots.footer() }}}
</footer>
</div>

假设上面的模板存放在 modal.edge 文件中,你可以像下面这样渲染它。

@modal()
@slot('header')
<h2> Delete post </h2>
@end
@slot('content')
<p> You are about to delete the post permanently </p>
@end
@slot('footer')
<button> Yes, delete it </button>
<button> Cancel </button>
@end
@end

你可以通过在磁盘名前加一个点号分隔符,从具名磁盘以标签形式引用组件。

{{-- 来自 uikit 磁盘的标签形式组件 --}}
@!uikit.input()
{{-- 通过 component 标签 --}}
@!component('uikit::input')

文件名到标签名的转换

你可以将存放在 components 目录中的文件作为标签在 edge 模板中引用。在从文件名创建标签时,会应用以下转换规则。

模板路径标签名
form/input.edge@form.input
tool_tip.edge@toolTip
checkout_form/input.edge@checkoutForm.input
modal/index.edge@modal