组件
通用的 Lume 组件
组件是可以用于其他模板的模板片段。一些模板引擎,如 Vento、Nunjucks、Pug 或 Liquid,具有代码复用的方法(如 includes、macros 等)。Lume 组件具有以下优点:
- 它们与模板引擎无关。例如,你可以使用 JSX 或 JavaScript 创建组件,并在 Nunjucks 中使用它们。
- 它们不仅可以生成 HTML 代码,还可以生成客户端所需的 CSS 和 JavaScript 代码。
- 它们在任何地方都自动可用;无需手动导入。
- 对于基于 ESM 模块的组件(如 JavaScript、TypeScript、JSX 或 TSX),这是热重载组件而无需停止和重启本地服务器的唯一方法。
Important
Lume 组件不在浏览器中运行。它们旨在构建时生成静态 HTML 代码。
对于交互式的客户端组件(带有 onclick
回调和类似功能),你可能需要使用 esbuild 插件 来编译你的 JavaScript 代码。但代码架构由你决定 (Lume 不是一个前端框架)。
创建你自己的组件
组件存储在 _components
目录中。与 _data
类似,你可以在不同的子目录中创建 _components
目录,以使它们仅对特定页面可用。要创建一个新组件,只需在此目录中创建一个文件,文件名为你组件的名称,扩展名为你想使用的模板引擎的扩展名。例如,一个用 Vento 编写的渲染按钮的组件可以存储在 _components/button.vto
中:
<button class="button">{{ text }}</button>
此组件在你的布局中通过 comp
变量可用(你可以在 _config.ts
中配置不同的变量名)。它是一个全局变量,包含所有组件。在我们的示例中,我们可以使用 comp.button()
函数渲染按钮组件:
<h1>欢迎来到我的网站。</h1>
{{ comp.button({ text: "登录" }) }}
请注意,该组件接受一个带有属性的对象。此组件在任何其他模板引擎中都可用。例如,JavaScript:
export default function ({ comp }) {
return `
<h1>欢迎来到我的网站。</h1>
${comp.button({ text: "登录" })}
`;
}
Vento 模板:
<h1>欢迎来到我的网站。</h1>
{{ comp.button({ text: "登录" }) }}
Nunjucks 模板:
<h1>欢迎来到我的网站。</h1>
{{ comp.button({ text: "登录" }) | safe }}
Eta 模板:
<h1>欢迎来到我的网站。</h1>
<%= comp.button({ text: "登录" }) %>
如果你正在使用 JSX 插件,Lume 组件可以像 React 组件一样使用:
export default function ({ comp }) {
return (
<>
<h1>欢迎来到我的网站。</h1>
<comp.Button text="登录" />
</>
);
}
请注意,使用基于文本的模板引擎(如 Vento 或 Nunjucks)创建的组件在 JSX 模板中无法按预期工作,因为 HTML 代码将被转义。要修复它,你必须使用 dangerouslySetInnerHTML
属性:
export default function ({ comp }) {
// comp.Button 是一个 Vento 组件:它返回一个字符串,而不是一个 JSX 元素。
return (
<>
<h1>欢迎来到我的网站。</h1>
<div
dangerouslySetInnerHTML={{ __html: <comp.Button text="登录" /> }}
/>
</>
);
}
嵌套组件
在 Vento 中,你可以通过这种方式嵌套组件:
{{ comp Container }}
Container 组件的内容
{{ comp Button }}
这是 Container 组件内部的一个按钮
{{ /comp }}
{{ /comp }}
在 Nunjucks 中,它非常相似:
{% comp "Container" %} Container 组件的内容 {% comp "Button" %}
这是 Container 组件内部的一个按钮 {% endcomp %} {% endcomp %}
组件的内容通过 content
变量传递:
<section class="container">{{ content }}</section>
<button>{{ content }}</button>
组件资源
组件可以导出 CSS 和 JS 代码。为此,组件需要导出 css
或 js
变量。
在我们的示例中,我们可能想为按钮应用一些样式。在 Nunjucks 模板中,导出数据的方式是使用 front matter:
---
css: |
.button {
background-color: blue;
color: white;
}
---
<button class="button">{{ text }}</button>
此 CSS 代码将与其他已使用组件的 CSS 代码一起导出到你的 dest
文件夹中的 /components.css
文件中。请注意,如果组件未使用,则 CSS 代码将不会导出。这是一个有趣的功能,它允许你拥有一个包含许多组件的库,并且只导出你需要的 CSS 和 JS 代码。
组织你的组件
组件可以保存在子目录中。例如,button
组件可以保存在 ui
子目录中(在你的 src
文件夹中的 _components/ui/button.vto
)。在这种情况下,你可以使用 comp.ui.button()
访问此组件。
组件内部的组件
组件可以在内部使用其他组件。假设我们要创建内部使用 button
的 search
组件。让我们看一个使用 JS 模板的例子:
// _components/search.js
export const css = `
.search {
background: gray;
padding: 20px;
}
`;
export const js = `
import from "js/search.js"
`;
export default function ({ comp }) {
return `
<form class="search">
<label>
Search:
<input type="search" name="q">
</label>
${comp.button({ text: "Submit" })}
</form>
`;
}
在此示例中,除了 HTML 代码外,该组件还导出了 CSS 和 JS 代码。
从 _config 文件注册组件
除了 _components
文件夹之外,你还可以在 _config
文件中使用 site.component()
函数动态注册组件。此函数接受两个参数:组件上下文和组件对象:
site.component("ui", {
name: "button",
css: ".btn { background: blue; color: white }",
render({ text }) {
return `<button class="btn">${text}</button>`;
},
});
现在,你可以像往常一样使用该组件:
{{ comp.ui.button({ text: "登录" }) }}