WebC
- Ant Design
*.tsx - Astro
*.astro - Bootstrap
*.html - Chakra UI
*.tsx - Docsify
*.md - Docusaurus
*.mdx - ESBuild
*.js - Eleventy
*.11ty.js - Gatsby
*.js - GitBook
*.md - Gridsome
*.vue - Hexo
*.ejs - Hugo
*.html - Jekyll
*.html - Mantine
*.tsx - Material-UI
*.js - MkDocs
*.md - Next.js
*.js - Nuxt.js
*.vue - Parcel
*.html - Remix
*.tsx - Rollup
*.js - Storybook
*.stories.js - Sphinx
*.rst - SvelteKit
*.svelte - SWC
*.ts - Tailwind CSS
*.css - Turbopack
*.ts - Vite
*.ts - VitePress
*.md - VuePress
*.vue - Webpack
*.js - 自定义框架
*.*

| Type | Value |
|---|---|
| Eleventy Name | webc |
| File Extension | *.webc |
| npm | @11ty/webc and @11ty/eleventy-plugin-webc |
| GitHub | 11ty/webc and 11ty/eleventy-plugin-webc |
为什么使用 WebC?
- 为 Eleventy 带来一流的组件支持。
- 使用 Web 标准定义的约定将任何 HTML 元素(包括自定义元素)扩展为 HTML。
- 这意味着使用 WebC 创建的 Web 组件与服务器端渲染兼容(无需重复作者编写的标记)
- WebC 组件支持渐进增强。
性能
- 创建精简的组件驱动、缓存友好的页面特定 JavaScript 和 CSS 包。用户只需加载渲染该页面所需的代码(或该岛屿的代码)。
- 当与
--incremental一起使用时,获得一流的增量构建(用于页面模板、组件和 Eleventy 布局) - 流友好(在边缘流式传输 👀)
与标准兼容
- 使用
parse5解析 WebC HTML,就像现代浏览器一样(向 @DasSurma 的 Vite 工作致敬) - Shadow DOM 和声明式 Shadow DOM 友好(轻松在 Light DOM 和 Shadow DOM 之间切换组件)
编写
- 鼓励无怪异模式 HTML 编写(doctype 是可选的)。如果 WebC 遇到怪异模式标记,会抛出一个有用的错误。
- 轻松限定组件 CSS 的作用域(或使用您自己的作用域工具)。
- 厌倦了导入组件?使用全局或每页无需导入的组件。
- 异步友好:所有配置扩展/钩子都默认支持异步。
- 对于更复杂的模板需求,在 WebC 内部渲染任何现有的 Eleventy 模板语法(Liquid、markdown、Nunjucks 等)。
Resources
WebC 简介 (11ty.rocks) 作者:
W. Evan Sheehan
理解 WebC 特性和概念 (11ty.rocks) 作者:
Stephanie Eckles- WebC 数字计数器示例源代码和演示
- 使用图像比较组件的渐进增强七个演示和源代码
- 使用 Eleventy 的 WebC 插件的初次体验
zachleat.com: 使用 WebC 为 Eleventy 添加组件:WebC 背后动机的简要历史,包括来自 Svelte 和 Vue 社区的影响。
11ty.webc.fun:WebC 食谱集合!
Robin Cussol: 使用 Eleventy Image 和 WebC 优化您的 img 标签
安装
该插件位于 npm 上的 @11ty/eleventy-plugin-webc!
npm install @11ty/eleventy-plugin-webc
要在 Eleventy 中添加对 .webc 文件的支持,请在您的 Eleventy 配置文件中添加该插件:
import pluginWebc from "@11ty/eleventy-plugin-webc";
export default function(eleventyConfig) {
eleventyConfig.addPlugin(pluginWebc);
};
const pluginWebc = require("@11ty/eleventy-plugin-webc");
module.exports = function(eleventyConfig) {
eleventyConfig.addPlugin(pluginWebc);
};
完整选项列表(显示默认值)
import pluginWebc from "@11ty/eleventy-plugin-webc";
export default function (eleventyConfig) {
eleventyConfig.addPlugin(pluginWebc, {
// 查找无需导入的全局组件的 Glob
//(默认值在 Eleventy WebC v0.7.0 中从 `false` 改变)
components: "\_components/\*_/_.webc",
// 添加 Eleventy WebC 转换来处理所有 HTML 输出
useTransform: false,
// 在 Eleventy WebC 转换中使用的额外全局数据
transformData: {},
// 传递给 @11ty/eleventy-plugin-bundle 的选项
bundlePluginOptions: {},
});
};
const pluginWebc = require("@11ty/eleventy-plugin-webc");
module.exports = function (eleventyConfig) {
eleventyConfig.addPlugin(pluginWebc, {
// 查找无需导入的全局组件的 Glob
//(默认值在 Eleventy WebC v0.7.0 中从 `false` 改变)
components: "\_components/\*_/_.webc",
// 添加 Eleventy WebC 转换来处理所有 HTML 输出
useTransform: false,
// 在 Eleventy WebC 转换中使用的额外全局数据
transformData: {},
// 传递给 @11ty/eleventy-plugin-bundle 的选项
bundlePluginOptions: {},
});
};
查看 Bundle 插件的完整选项列表。例如,您可以使用 transforms 数组通过 postcss 修改包内容。
语法高亮
因为 WebC 就是 HTML,您可以配置编辑器将 .webc 文件视为 HTML,这应该能正确语法高亮您的 WebC 文件。您选择的编辑器应该有一些关于如何实现这一功能的文档。
用法
在 Eleventy 中使用 WebC 有几种不同的方式:
添加一个新的 .webc 文件
添加插件将为您的 Eleventy 项目启用 .webc 文件支持。只需在您的 Eleventy 输入目录中创建一个新的 .webc HTML 文件,Eleventy 就会为您处理它!值得注意的是,.webc 文件将运行打包器模式下的 WebC,聚合每个单独页面上使用的 CSS 和 JS,以创建该页面上使用的资源包。
WebC 使用 HTML 解析器处理输入文件:在这里使用任何 HTML!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>WebC Example</title>
</head>
<body>
WebC *is* HTML.
</body>
</html>
非传统的 WebC 用法
使用 Render 插件
使用 Eleventy 内置的 Render 插件 允许您在现有的 Liquid、Nunjucks 或 11ty.js 模板中渲染 WebC。
{% renderTemplate "webc" %}
<my-custom-component></my-custom-component>
{% endrenderTemplate %}
{% renderTemplate "webc" %}
<my-custom-component></my-custom-component>
{% endrenderTemplate %}
export default async function () {
let content = await this.renderTemplate(
`<my-custom-component></my-custom-component>`,
"webc"
);
return content;
};
module.exports = async function () {
let content = await this.renderTemplate(
`<my-custom-component></my-custom-component>`,
"webc"
);
return content;
};
将 HTML 输入预处理为 WebC
您可以使用配置选项将默认的 HTML 预处理器(从 liquid)更改为 webc。这可能看起来像 htmlTemplateEngine: "webc"。更多关于 Eleventy 文档:HTML 文件的默认模板引擎的信息。
将 HTML 输出后处理为 WebC
这是一个(最后手段?)通用选项,让 WebC 处理项目中的 .html 输出文件(跳过任何 .webc 输入文件以避免重复处理模板)。此功能使用 Eleventy 转换,当您希望在现有项目上快速启动并运行 WebC 时最有用。
转换方法有几个缺点:
- 这是在项目中实现 WebC 的构建性能最慢的方法,所以请先尝试其他方法!
- WebC Eleventy 转换在打包器模式禁用下运行,这意味着处理 WebC 但不会聚合组件 JS 或 CSS。(支持此增强请求)
转换默认是禁用的,您需要使用 useTransform 选项来启用它。
import pluginWebc from "@11ty/eleventy-plugin-webc";
export default function (eleventyConfig) {
eleventyConfig.addPlugin(pluginWebc, {
useTransform: true,
});
};
const pluginWebc = require("@11ty/eleventy-plugin-webc");
module.exports = function (eleventyConfig) {
eleventyConfig.addPlugin(pluginWebc, {
useTransform: true,
});
};
WebC 参考
注意: 所有 webc: 属性都会从渲染的输出 HTML 中移除。
仅 HTML 组件
- 相关:在 WebC 中定义组件
当组件只有内容 HTML(没有 CSS 或 JavaScript)时,它将在输出 HTML 中忽略宿主组件标签。这使得仅 HTML 组件能够实现零开销 HTML。(您可以使用 webc:keep 选择退出此行为。)
展开查看示例
my-component)的限制。您可以使用 p、blockquote、h1、img 或任何有效的 HTML 标签名称。<!DOCTYPE html>
<title>WebC Example</title>
<my-component></my-component>
组件不需要根元素,各位。
输出:
<!DOCTYPE html>
<html>
<head>
<title>WebC Example</title>
</head>
<body>
组件不需要根元素,各位。
</body>
</html>
资源打包
对于不是仅 HTML 的组件(它们确实有 CSS 或 JS),WebC 将在输出标记中包含组件标签(例如 <my-component>)(用于样式或客户端脚本)。(您可以使用 webc:nokeep 选择退出此行为。)
展开查看示例
my-component)的限制。您可以使用 p、blockquote、h1、img 或任何有效的 HTML 标签名称。<!DOCTYPE html>
<title>WebC Example</title>
<my-component></my-component>
组件不需要根元素,各位。
<style>
/* 嗨 */
</style>
输出:
<!DOCTYPE html>
<html>
<head>
<title>WebC Example</title>
</head>
<body>
<my-component>组件不需要根元素,各位。</my-component>
</body>
</html>
Eleventy 在打包器模式下运行 WebC。这意味着当它在组件定义中找到 <style>、<link rel="stylesheet"> 或 <script> 元素时,它们会从输出标记中移除,并且它们的内容会聚集在一起,以便在页面上的资源包中重复使用。更多关于 WebC 中的 CSS 和 JS的信息。(您可以使用 webc:keep 选择退出此行为。)
webc:keep
对于仅 HTML 组件,您可以在宿主组件上使用 webc:keep 来保留标签:
<html-only-component webc:keep></html-only-component>
您也可以使用 webc:keep 选择退出组件定义中单个元素的资源打包:
<style webc:keep></style>
<script webc:keep></script>
您也可以使用 webc:keep 来保存 <slot> 以在客户端自定义元素中使用。
webc:nokeep
对于 CSS/JS 组件(不是仅 HTML 组件),您可以在宿主组件上使用 webc:nokeep 来丢弃标签:
<css-js-component webc:nokeep></css-js-component>
webc:import
WebC 将扩展它找到的任何使用已知组件的组件。您也可以使用 webc:import 来内联导入组件定义。此导入路径相对于组件文件路径。WebC 检查循环组件依赖,如果遇到循环依赖会抛出错误。
- 相关:在 WebC 中定义组件(全局或作用域)
<any-tag-name webc:import="./components/my-component.webc"></any-tag-name>
您可以直接从已安装的 npm 包导入。Eleventy 将开始为现有插件提供 WebC 组件。语法高亮器(4.2.0 或更新版本)提供了今天可以使用的一个:
<syntax-highlight
language="js"
webc:import="npm:@11ty/eleventy-plugin-syntaxhighlight"
>
function myFunction() { return true; }
</syntax-highlight>
这使用组件标签名称(syntax-highlight)在 node_modules/@11ty/eleventy-plugin-syntaxhighlight/syntax-highlight.webc 处查找 WebC 组件,并将其导入到此节点上使用。这也适用于通过 webc:is 的标签名称覆盖。
webc:if
使用 webc:if 来有条件地渲染元素。接受任意 JavaScript(并且是异步友好的)。与动态属性类似,这也可以访问组件属性和特性。
<div webc:if="true">这将会渲染</div>
<div webc:if="false">这不会渲染</div>
<div webc:if="myAsyncHelper()">如果 helper promise 解析为真值,这将会渲染</div>
您可以使用 webc:type="js" (WebC v0.7.1+) 来使用 JavaScript 进行更复杂的条件逻辑(更多内容请参阅下文)。
webc:elseif 和 webc:else
webc:if 的相邻兄弟元素可以使用 webc:elseif="" 和 webc:else 进行额外的条件逻辑。
<div webc:if="false">这不会渲染</div>
<!-- 插入注释也可以正常工作 -->
<div webc:elseif="true">这将会渲染</div>
<div webc:else>这不会渲染</div>
webc:for 循环
使用 webc:for 循环遍历数据的 HTML。它适用于对象和任何可迭代对象(String、Array、Map、Set 等)。
语法应该感觉类似于 JavaScript 的 for 语句。
数组(或其他可迭代对象)
<!-- 渲染三个 div 元素 -->
<div webc:for="item of [1, 2, 3]" @text="item"></div>
<!-- 访问循环索引(从零开始) -->
<div webc:for="(item, index) of [1, 2, 3]" @text="index"></div>
<!-- 可以随心所欲地命名这些 -->
<div webc:for="myItem of [1, 2, 3]" @text="myItem"></div>
<div webc:for="(myItem, myIndex) of [1, 2, 3]" @text="myIndex"></div>
<!-- any iterable -->
<div webc:for="item of new Set([1, 2, 3])" @text="item"></div>
对象
注意使用 in 而不是 of。
<!-- 渲染两个 div 元素 -->
<div webc:for="key in { a: 1, b: 2 }" @text="key"></div>
<!-- 访问值 -->
<div webc:for="(key, value) in { a: 1, b: 2 }" @text="value"></div>
<!-- 访问循环索引(从零开始) -->
<div webc:for="(key, value, index) in { a: 1, b: 2 }" @text="index"></div>
<!-- 可以随心所欲地命名这些 -->
<div
webc:for="(myKey, myValue, myIndex) in { a: 1, b: 2 }"
@text="myIndex"
></div>
<!-- 可以使用 `Object.values` 或 `Object.keys` -->
<div webc:for="value of Object.values({ a: 1, b: 2 })"></div>
<div webc:for="key of Object.keys({ a: 1, b: 2 })"></div>
嵌套 webc:for
循环可以嵌套,但从内循环访问外作用域目前不起作用。更多内容请参见 issue #175。
插槽
子内容也可以选择使用 <slot> 和 [slot] 进行预编译。此示例使用的是仅 HTML 组件。
<my-component></my-component> <my-component>这是默认插槽</my-component>
<p><slot>后备插槽内容</slot></p>
编译为:
<p>后备插槽内容</p>
<p>这是默认插槽</p>
如果您的 WebC 组件想要在编译标记中输出 <slot> 标签(用于客户端 JavaScript),请使用 webc:keep 属性(例如 <slot webc:keep>)。
<style>/<script>),则隐含 <slot></slot>,并且将自动包含默认插槽内容。如果 WebC 组件文件确实包含内容标记,则作为默认插槽传入的内容需要包含 <slot>。命名插槽
这也适用于命名插槽(例如 <span slot="named-slot">)。
展开查看示例
<my-component>
这是默认插槽。
<strong slot="named-slot">这是一个命名插槽</strong>
这也是默认插槽。
</my-component>
<p><slot name="named-slot"></slot></p>
编译为:
<p><strong>这是一个命名插槽。</strong></p>
属性和 webc:root
<my-component class="sr-only"></my-component>
在您的组件定义内部,您可以使用 webc:root 向外部宿主组件添加属性:
<template webc:root class="another-class"> 一些组件内容 </template>
class 和 style 属性值在宿主组件和 webc:root 元素之间按预期合并。
覆盖宿主组件标签
您可以使用 webc:root="override" 来覆盖宿主组件标签名称!这对于仅 HTML 组件(省略宿主组件标签)不是很有用,但当您的组件有样式/脚本时非常有用。
<button webc:root="override">一些组件内容</button>
<style>
/* 嗨 */
</style>
- 以前,上述功能通常通过在元素上同时使用
webc:root和webc:keep来完成。
嵌套
值得注意的是,webc:root 也可以嵌套在其他内容内部——它不需要存在于组件定义的顶层。(框架爱好者们喜欢深度嵌套在 div 中的东西,对吧?)
<div>
<div>
<template webc:root="override" class="another-class">
一些组件内容
</template>
</div>
</div>
Props(属性)
通过在属性前添加 @ 前缀,将任何属性变为 prop。Props 是仅服务器的"私有"属性,不会出现在输出 HTML 中(它们对 WebC 是私有的)。它们与属性相同,只是从输出 HTML 中过滤掉。
<my-component @prop="Hello"></my-component>
<p @text="prop"></p>
<!-- 输出 <p>Hello</p> -->
- 在 HTML 规范中,属性名称是小写的。带有连字符的属性或属性名称在 JS 中会转换为驼峰命名(例如
<my-component @prop-name="test">可以像@text="propName"一样使用)。更多信息请参见 issue #71。
动态属性和特性
通过在属性前添加冒号(:)前缀,使任何属性或属性动态化(使用 JavaScript 作为值而不是字符串)。您可以在这里访问宿主组件属性、props 和页面数据!
<avatar-image
src="my-image.jpeg"
alt="Zach is documenting this project"
:@dynamic-prop="'hello'"
></avatar-image>
<img :src="src" :alt="alt" class="avatar-image" />
:@动态属性前缀是在 WebC v0.9.0 中添加的。- 在 HTML 规范中,属性名称是小写的。带有连字符的属性或属性名称在 JS 中会转换为驼峰命名(例如
<my-component @prop-name="test">可以像@text="propName"一样使用)。更多信息请参见 #71。
- 目前唯一支持动态值的
webc:*配置属性是webc:bucket。更多内容即将推出:#143 #148
@attributes
您可以使用 @attributes 将所有属性(包括宿主组件上的)渲染到当前节点。
<!-- 将渲染所有属性,包括来自宿主组件的 `src` 和 `alt` -->
<img @attributes class="avatar-image" />
您也可以使用此功能将任意对象作为属性渲染(注意使用括号以避免 JavaScript 解析为 block + label):
<img @attributes="({ myattribute: 'myValue'})" />
@html
我们提供了一个特殊的 @html prop 来用自定义 JavaScript 覆盖任何标签内容。
<template @html="'Template HTML'"></template>
<template @html="dataProperty"></template>
<!-- webc:nokeep will replace the outer element -->
<template @html="'Template HTML'" webc:nokeep></template>
- 从
@html属性返回的内容将被处理为 WebC——在这里返回任何 WebC 内容!
- 使用
webc:raw将阻止结果作为 WebC 处理 - 使用
@raw作为webc:raw @html的别名
<!-- 不作为 WebC 重新处理(在 Eleventy 布局中有用) -->
<!-- 其中 `myHtmlContent` 是一个保存任意 HTML 字符串的变量 -->
<template @raw="myHtmlContent" webc:nokeep></template>
@raw
如 @html 中所述,您可以使用 @raw 作为 webc:raw @html 的别名。
@text
我们提供了一个特殊的 @text prop 来用自定义 JavaScript 覆盖任何标签内容。这里返回的整个值将被转义!
<p @text="dataProperty"></p>
<!-- 当 dataProperty 包含 `<p>This is text</p>` 时,这将渲染为: -->
<p><p>This is text</p></p>
<!-- webc:nokeep will replace the outer element -->
<p @text="dataProperty" webc:nokeep></p>
- 从
@text属性返回的内容不会被处理为 WebC。
webc:is
将组件重新映射到另一个组件名称。
<div webc:is="my-component"></div>
<!-- equivalent to -->
<my-component></my-component>
webc:scoped
我们包含了一个轻量级机制(webc:scoped)来限定组件 CSS 的作用域。选择器会以一个新的组件类名为前缀。类名基于样式内容的哈希值(用于精美地去除相同组件样式的重复)。
展开查看示例
<my-component>Default slot</my-component>
如果您使用 :host,它将被替换为该类选择器。
<style webc:scoped>
:host {
color: blue;
}
:host:defined {
color: rebeccapurple;
}
</style>
这会输出:
<my-component class="wcl2xedjk">Default slot</my-component>
并将以下 CSS 聚合到包中:
.wcl2xedjk {
color: blue;
}
.wcl2xedjk:defined {
color: rebeccapurple;
}
- 渐进增强的故事需要在关键渲染路径中的内容使用之前获得普遍的浏览器支持。
- 它需要在组件的每个实例中重复
<style>。
请注意这些权衡。并记住您可以在 WebC 中使用两种方法!
webc:scoped="my-prefix"
您也可以为 webc:scoped 指定一个属性值来硬编码自己的组件前缀(例如 <style webc:scoped="my-prefix">)。这允许 CSS 看起来更友好和可读。我们将自动检查组件树中的重复值,如果发生冲突则抛出错误。
使用 JavaScript 设置组件
您现在还可以使用 <script webc:setup> 来运行任意 JavaScript 并为您的组件提供数据和标记。这里声明的任何顶级变量都可作为本地数据在您的组件中使用。
这类似于在 Front Matter 中使用 JavaScript 作为自定义 Eleventy Front Matter 类型,尽管 webc:setup 中的数据作用于组件,并且不会在数据级联中回流。
<script webc:setup>
const myHtml = "<my-webc-component></my-webc-component>"
function alwaysBlue() {
return "blue"
}
</script>
<div @html="myHtml"></div>
<div @raw="myHtml"></div>
<!-- @raw does not reprocess as WebC -->
<div @html="alwaysBlue()"></div>
适用于 var、let、const、function、Array 和 Object 解构赋值。
使用模板语法生成内容
Eleventy WebC 插件中的自定义转换功能(例如 webc:type)已连接到 Eleventy Render 插件,允许您在 WebC 内部使用现有的 Eleventy 模板语法。
webc:type="11ty" 功能是 Eleventy WebC 插件独有的,在非 Eleventy 独立 WebC 中不可用。使用 webc:type="11ty" 和 11ty:type 属性来指定有效的模板语法。
---
frontmatterdata: "Hello from Front Matter"
---
<template webc:type="11ty" 11ty:type="liquid,md">
{% assign t = "Liquid in WebC" %}
## {{ t }}
_{{ frontmatterdata }}_
</template>
- 您在这里完全访问数据级联(注意
frontmatterdata是在上面 在 front matter 中设置 的)。 - 从
<template>(或webc:is="template")节点上的自定义转换返回的内容将被处理为 WebC——在这里返回任何 WebC 内容!
使用 JavaScript 生成内容
您也可以使用 webc:type 转换单个元素内容。除了 webc:type="11ty" 之外,还有另外三种捆绑类型:
webc:type="js"webc:type="render"(superseded bywebc:type="js")webc:type="css:scoped"(internal forwebc:scoped—but overridable!)
JavaScript 渲染函数:webc:type="js" 和 webc:type="render"
在 WebC 中运行任何任意服务器端 JavaScript。输出脚本中执行的最后一条语句的结果。异步友好(返回一个 promise,我们会解析它)。
<img
src="my-image.jpeg"
alt="An excited Zach is trying to finish this documentation"
/>
<script webc:type="js" webc:root>
if (!alt) {
throw new Error("oh no you didn't")
}
;`<img src="${src}" alt="${alt}">`
</script>
Expand to see this example with webc:type="render"
<script webc:type="render">
export default function () {
if (!this.alt) {
throw new Error("oh no you didn't")
}
// 免费建议:使用 Eleventy Image 插件返回优化的标记
return `<img src="${this.src}" alt="${this.alt}">`
}
</script>
或者使用 JavaScript 渲染函数生成一些 CSS:
<style webc:is="add-banner-to-css" @license="MIT licensed">
p {
color: rebeccapurple;
}
</style>
<template webc:is="style" webc:root="override">
<script webc:type="js">
export default function ({license}) {
return `/* ${license} */`
}
</script>
<slot></slot>
</template>
Expand to see this example with webc:type="render"
<template webc:is="style" webc:root="override">
<script webc:type="render">
export default function () {
return `/* ${this.license} */`
}
</script>
<slot></slot>
</template>
展开查看另一个使用 webc:type="js" 的更复杂条件示例
注意您也可以使用 webc:if!
<script webc:type="js">
export default function ({src, alt}) {
if (alt) {
return `<img src="${src}" alt="${alt}">`
} else {
return `<a href="${src}">Your image didn't have an alt so you get this link instead.</a>`
}
}
</script>
额外提示:
- 您可以使用
webc:scoped webc:is="style" webc:type="js"(或webc:type="render")来使用 JavaScript 生成作用域 CSS!更多信息请参见webc:scoped。 - 您在渲染函数中可以访问组件属性和 props(这在另一节中介绍!)。
- 使用
webc:type="js"具有隐含的webc:is="template"来返回将被重新处理为 WebC (HTML) 的内容。您可以使用自己的webc:is属性来覆盖此项以生成不同的标签(例如webc:is="script"或webc:is="style")。 - 使用
webc:type="js"具有隐含的webc:nokeep来跳过输出外部节点。您可以添加webc:keep来覆盖此行为。
JavaScript 渲染函数的额外数据
webc.attributes: an object literal representing the current element's attributes.webc.renderAttributes: a method to render public attributes to a string.webc.filterPublicAttributes: 一个过滤webc.attributes的方法,返回仅包含公开属性的对象。用法:webc.filterPublicAttributes(webc.attributes)webc.escapeText: 编码 HTML 文本中所有需要转义的字符(通过entities包)webc.escapeAttribute: 编码 HTML 属性中所有需要转义的字符(通过entities包)
阅读更多关于 Issue #104 的信息。
Expand to see an img component example
可以想象一个这样的 <img> 组件定义,它正确地合并和重用所有宿主组件属性:
<script webc:type="js" webc:root="override">
;`<img ${webc.renderAttributes(webc.attributes)}>`
</script>
webc:raw
使用 webc:raw 来选择不对当前节点的所有子内容进行 WebC 模板处理。值得注意的是,当前节点的属性将被处理。这与 <template> 配合得很好!
<template webc:raw>
别把我包含进去。
<style>
p {
color: rebeccapurple;
}
</style>
</template>
- 相关:
@raw属性
webc:ignore
使用 webc:ignore 来完全忽略一个节点,不处理或输出任何相关内容。适用于服务器端注释或组件文档。
<template webc:ignore>
这是您可能使用此组件的方式:
<my-component>Nothing in here will be processed</my-component>
</template>
仅服务端注释
与将显示在渲染输出中的 HTML 注释不同,您可以在开头/结尾添加一个或多个破折号来告诉 WebC 从输出中剥离此内容。非常适合服务器端注释。
<!--- WebC will remove this --->
<!-- 这不会*被*移除并且会渲染到输出中 -->
<!------- WebC will remove this, too ------->
自定义转换
此插件开箱即用地提供了一些转换:webc:type="js", webc:type="render", webc:type="css:scoped", 和 webc:type="11ty"。
然而,在 Eleventy WebC 插件中,直接向 WebC 添加您自己的webc:type 自定义转换 尚不可用!如果这是大家希望看到添加的功能,请告诉我们!
请注意您可以添加自己的自定义模板引擎,这将通过 webc:type="11ty" 提供(例如 <style webc:type="11ty" 11ty:type="sass">)。
辅助函数
WebC 帮助器 是可在动态属性、@html、@raw 和渲染函数中使用的 JavaScript 函数。
Eleventy 提供的辅助函数
Eleventy WebC 包含了 JavaScript 模板函数 和 通用过滤器 作为 WebC 帮助器自动提供。
<!-- Use the Eleventy provided `url` universal filter -->
<a :href="url('/local-path/')">My Link</a>
提供自己的辅助函数
export default function (eleventyConfig) {
// via Universal Filter
eleventyConfig.addFilter("alwaysRed", () => "Red");
// or via JavaScript Template Function directly
eleventyConfig.addJavaScriptFunction("alwaysBlue", () => "Blue");
// Don't forget to add the WebC plugin in your config file too!
};
module.exports = function (eleventyConfig) {
// via Universal Filter
eleventyConfig.addFilter("alwaysRed", () => "Red");
// or via JavaScript Template Function directly
eleventyConfig.addJavaScriptFunction("alwaysBlue", () => "Blue");
// Don't forget to add the WebC plugin in your config file too!
};
<div @html="alwaysRed()"></div>
<div @html="alwaysBlue()"></div>
<!-- 渲染为: -->
<div>Red</div>
<div>Blue</div>
细节和限制
空元素
自定义元素(根据规范)不被支持作为空元素:它们需要开始和结束标签。
实际上,这意味着 WebC 组件不能是自闭合的。您可以使用 webc:is 来解决此限制(例如 <img webc:is="my-component">)。
<head> Components
使用 HTML 解析器与自定义元素时有一些问题。值得注意的是,解析器试图强制将 <head> 中的自定义元素子元素移动到 <body> 中。要解决此限制,请使用 webc:is。
Expand for a few example workarounds
<head webc:is="my-custom-head">
<!-- 这是插槽内容,是的,您也可以在这里使用命名插槽 -->
</head>
<head>
<!-- <my-custom-head> is not allowed here but
<meta webc:is="my-custom-head> is -->
<meta webc:is="my-custom-head" />
<title webc:is="my-custom-title">Default Title</title>
</head>
<table> Components
由于 WebC 使用 parse5 库,所有要处理的 WebC 文件都会像网络浏览器解析它们一样进行解析和标记化。因此,将 <table> 标签放在自定义 WebC 元素中,并将其 <tr> 和 <td> 标签放在插槽中以插入到表格中,会导致 <tr> 和 <td> 元素在初始解析时被移除,表格的所有内部内容将被放置为其兄弟元素。这是由于 parse5 库认为 <tr> 和 <td> 标签是孤立的。
要解决此限制,请对 <table>, <tr>, 和 <td> 元素使用 webc:is。
Expand for an example workaround
上述示例假设存在 _includes/my-layout.webc(一个 Eleventy 布局)。
...
<my-table>
<x webc:is="tr">
<x webc:is="td"> My Table Content </x>
</x>
</my-table>
...
<x webc:is="table">
<slot></slot>
</x>
渲染模式
Eleventy 中有两种不同的渲染模式:page 和 component。我们尝试根据您提供的标记来猜测您想要的渲染模式。page 渲染模式用于渲染完整的 HTML 页面。component 渲染模式用于 HTML 片段。大多数情况下您不需要担心这种区别,但为了文档的完整性,这里包含了它。
page在标记以<!doctype(或<!DOCTYPE)或<html开头时使用(WebC 强制无怪异模式解析)。- 否则使用
component。
与 HTML 解析的差异
WebC 处理 <template> 和 <noscript> 标签内部的内容。HTML 解析器将这些视为纯文本。
Eleventy + WebC 功能
Front Matter
Eleventy 中的 WebC 自动适用于 front matter 的标准 Eleventy 约定(尽管 Eleventy 中的 front matter 是可选的)。
---
layout: "my-layout.webc"
---
WebC *is* HTML.
展开查看 my-layout.webc 示例
上述示例假设存在 _includes/my-layout.webc(一个 Eleventy 布局)。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>WebC Example</title>
</head>
<body @raw="content"></body>
</html>
重要提示:front matter(根据标准 Eleventy 约定)仅在页面级模板(输入目录中的 .webc 文件)中受支持,而不在组件中(见下文)。
定义组件
组件是 WebC 的 魔法,在 WebC 中有几种定义组件的方法:
- 使用在配置文件中指定的全局无需导入组件。
- 在数据级联中的目录或模板级别指定无需导入组件的 glob。
- 您可以在组件内部使用
webc:import来直接导入另一个组件。
全局无需导入组件
使用在 Eleventy 配置文件中传递给 addPlugin 的选项中的 components 属性来指定可在任何页面中使用的项目范围的 WebC 组件文件。
我们接受:
- 字符串(文件路径或 glob)
- 数组(文件路径或 glob 数组)
npm:前缀别名
import pluginWebc from "@11ty/eleventy-plugin-webc";
export default function (eleventyConfig) {
eleventyConfig.addPlugin(pluginWebc, {
// 查找无需导入的全局组件的 Glob
// 此路径相对于项目根目录!
// 显示默认值:
components: "\_components/\*_/_.webc",
// or an Array (Eleventy WebC v0.9.2+)
components: [
"_components/**/*.webc",
"npm:@11ty/is-land/*.webc",
"npm:@11ty/eleventy-plugin-syntaxhighlight/*.webc",
],
});
};
const pluginWebc = require("@11ty/eleventy-plugin-webc");
module.exports = function (eleventyConfig) {
eleventyConfig.addPlugin(pluginWebc, {
// 查找无需导入的全局组件的 Glob
// 此路径相对于项目根目录!
// 显示默认值:
components: "\_components/\*_/_.webc",
// or an Array (Eleventy WebC v0.9.2+)
components: [
"_components/**/*.webc",
"npm:@11ty/is-land/*.webc",
"npm:@11ty/eleventy-plugin-syntaxhighlight/*.webc",
],
});
};
值得注意的是,components 的路径是相对于您的项目根目录(不是您的项目的 input 目录)。
在 glob 中找到的组件文件名决定了您项目中使用的全局标签名(例如,_components/my-component.webc 将让您能够使用 <my-component>)。
在 Front Matter 中声明组件
您也可以在 front matter 中使用和配置特定组件(或者,通过数据级联的任何部分——作用于文件夹或模板),通过将 glob(或 glob 数组)分配给 webc.components 属性:
---
layout: "my-layout.webc"
webc:
components: "./webc/*.webc"
---
<my-webc-component>WebC *is* HTML.</my-webc-component>
默认情况下,这些路径是相对于模板文件的。如果您要在应用于多个子文件夹深度的目录数据文件中的数据级联中设置此选项,最好:
- 使用全局无需导入组件选项。
- 使用
~/作为前缀(例如~/my-directory/webc/*.webc)来别名到项目的根目录。
官方 WebC 组件
以下插件为您的项目提供官方 WebC 组件:
@11ty/is-land提供<is-land>- 示例:
<is-land webc:import="npm:@11ty/is-land"> - 更多信息请参见与
is-land一起使用
- 示例:
@11ty/eleventy-plugin-syntaxhighlight提供<syntax-highlight>- 示例:
<syntax-highlight language="js" webc:import="npm:@11ty/eleventy-plugin-syntaxhighlight"> - 更多信息请参见语法高亮插件
- 示例:
@11ty/eleventy-img提供<eleventy-image>- 示例:
<img webc:is="eleventy-image" webc:import="npm:@11ty/eleventy-img"> - 更多信息请参见图像 WebC 组件。
- 示例:
CSS 和 JS(打包器模式)
Eleventy WebC 将打包任何特定页面的资源(页面上组件使用的 CSS 和 JS)。当组件使用 <script>、<script src>、<style> 或 <link rel="stylesheet"> 时,这些资源会自动汇总。您可以使用此功能实现组件驱动的关键 CSS。
<style>
/* 这是组件 CSS */
</style>
<script>
/* 这是组件 JS */
</script>
<!-- Local file references work too -->
<link rel="stylesheet" href="my-file.css" />
<script src="my-file.js"></script>
如上所示,当 URL 指向文件系统上的文件时,这也包括 <link rel="stylesheet"> 和 <script src>(尚不支持远程 URL 源)。
您可以使用 webc:keep 按元素选择退出打包。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>WebC Example</title>
<!-- inline bundles -->
<style @raw="getBundle('css')" webc:keep></style>
<script @raw="getBundle('js')" webc:keep></script>
<!-- or write your bundle to a file -->
<link rel="stylesheet" :href="getBundleFileUrl('css')" webc:keep />
<script :src="getBundleFileUrl('js')" webc:keep></script>
</head>
<body @raw="content"></body>
</html>
- Eleventy WebC 在后台使用Bundle 插件来实现打包。现在可以分别使用
getBundle('css')和getBundle('js')来代替getCss(page.url)和getJs(page.url)。 - 在您的布局文件中,
<style>和<script>上需要webc:keep来防止重新打包这些包。 getCss和getJs辅助函数现在可以无限制地在所有 WebC 模板中使用。以前的版本要求它们在 Eleventy 布局 文件中使用。@raw曾经是。以前的版本可以使用webc:raw @html。
包代码顺序
这些包中代码的顺序由组件的依赖关系决定,从最具体到最不具体!
展开查看示例
假设我们有一个使用 header.webc 组件的 index.webc 页面。
<style>
/* index.webc */
</style>
<header></header>
<style>
/* header.webc */
</style>
CSS 包将看起来像这样:
/* header.webc */
/* index.webc */
在其他模板引擎中访问打包文件
您也可以在其他模板类型中访问这些包(.html、.liquid 等)。
Eleventy WebC 在后台使用 Bundle 插件来实现打包。此插件提供 getBundle 和 getBundleFileUrl 通用短代码,可在任何模板类型中使用(包括上面显示的 WebC)。
WebC v0.8.0 及更早版本:查看已弃用(但为了向后兼容仍然保留)的用于包输出的 webcGetCss 和 webcGetJs 通用过滤器。
<style>{{ page.url | webcGetCss | safe }}</style>
<script>{{ page.url | webcGetJs | safe }}</script>
<!-- write to a file -->
<link rel="stylesheet" href="{% getBundleFileUrl "css" %}">
<style>{{ page.url | webcGetCss }}</style>
<script>{{ page.url | webcGetJs }}</script>
资源分桶
这里有一个额外的打包层,您可以使用它,我们称之为分桶。组件可以使用 webc:bucket 输出到任何任意的桶名称。
在这个组件中,我们有输出到两个独立桶的组件代码:
<style>
/* 此 CSS 被放入默认桶中 */
</style>
<script>
/* 此 JS 被放入默认桶中 */
</script>
<style webc:bucket="defer">
/* 此 CSS 被放入 `defer` 桶中 */
</style>
<script webc:bucket="defer">
/* 此 JS 被放入 `defer` 桶中 */
</script>
当 <my-webc-component> 在页面上使用时,它将资源滚动到页面特定的 CSS 和 JavaScript 桶包中。
然后您可以在页面的任何位置输出这些桶包,如下所示(这里我们使用 Eleventy 布局文件):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>WebC Example</title>
<!-- Default bucket -->
<style @raw="getBundle('css')" webc:keep></style>
<script @raw="getBundle('js')" webc:keep></script>
</head>
<body>
<template @raw="content" webc:nokeep></template>
<!-- `defer` bucket -->
<style @raw="getBundle('css', 'defer')" webc:keep></style>
<script @raw="getBundle('js', 'defer')" webc:keep></script>
</body>
</html>
- 在布局文件中,
<style>和<script>上需要webc:keep来防止重新打包这些包。 :webc:bucket(动态属性)支持通过 JavaScript 设置此值。#120
级联资源桶
Additionally webc:bucket can be added to any tag and will cascade to all child content.
考虑这个 WebC 页面:
<!-- 具有隐含的 webc:bucket="default" -->
<my-component></my-component>
<div webc:bucket="defer">
<!-- 这些每个都有 webc:bucket="defer" -->
<!-- (也包括内部的任何嵌套组件) -->
<footnote-references></footnote-references>
<my-footer></my-footer>
</div>
设置 webc:bucket 现在会级联到所有子元素,就像它们每个都被单独分配了 webc:bucket="defer" 一样。这些组件中使用的所有资源现在将被汇总到 defer 桶中。
冲突和提升
当组件在多个不同的桶中使用时会发生什么?
<!-- 具有隐含的 webc:bucket="default" -->
<my-component></my-component>
<div webc:bucket="defer">
<my-component></my-component>
</div>
当出现重复和冲突时,WebC 会将组件代码提升到最近的共享桶。在上面的例子中,<my-component> 的 CSS 和 JS 将在 default 桶中加载,并且只在 default 桶中加载。
与 is-land 一起使用
您也可以开箱即用地使用 Eleventy 的is-land 组件进行 Web 组件水合。
在组件级别,组件可以声明自己的 is-land 加载条件。
<is-land on:visible webc:import="npm:@11ty/is-land">
<template data-island>
<!-- CSS -->
<style webc:keep>
/* 此 CSS 在:visible 时适用 */
</style>
<link rel="stylesheet" href="arbitrary.css" webc:keep />
<!-- JS -->
<script type="module" webc:keep>
console.log("此 JavaScript 在:visible 时运行")
</script>
<script type="module" src="arbitrary.js" webc:keep></script>
</template>
</is-land>
来自社区
×2 个资源通过 11tybundle.dev 由
Bob Monsour 整理。