ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Storybook Web Components 自定义元素清单配置:custom-elements.json 注册与 argTypes 自动生成实战

Storybook Web Components 自定义元素清单配置:custom-elements.json 注册与 argTypes 自动生成实战 Storybook Web Components 自定义元素清单配置custom-elements.json 注册与 argTypes 自动生成实战【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook在 Storybook 中为 Web Components 编写 Story 时浏览器无法像 React 或 Vue 那样通过组件对象直接推断出 props 与事件因此需要一份机器可读的custom-elements.json清单作为元数据来源。本文以 Storybook 仓库中 storybook-preview-custom-elements-config.md 为骨架完整讲解如何在.storybook/preview中通过setCustomElementsManifest注册该清单并结合web-componentsrenderer 的源码剖析 argTypes、控件与属性表格的生成原理帮助你为自定义元素项目一键获得完整的 Controls、自动文档与类型提示能力。为什么 Web Components 需要 custom-elements.jsonStorybook 默认会根据组件的定义和 args 的初始值来推断 argTypes 并生成对应的控件见 controls.mdx。但对于 Web Components组件是一个注册了标签名的自定义元素类Storybook 无法直接读取它的属性、事件与插槽声明必须依赖一份标准的清单文件。在 arg-types.mdx 的框架支持矩阵中WebComponents一行明确标注其 argTypes 来源为custom-element.json。这份文件既可以手写更推荐使用分析器从源码自动生成然后通过setCustomElementsManifest()注入 Storybook 的预览运行时使文档Props 表格与 Controls 面板都能基于真实声明渲染。生成 custom-elements.json可选分析器与 Stencil 配置在编写注册代码之前需要先拥有一份custom-elements.json。根据 Storybook 官方 addon-docs 对 Web Components 的说明见 WEB_COMPONENTS.md不同格式的清单对应不同分析器清单格式推荐分析器支持范围custom-elements.jsonv1.0.0schemaVersion 1.0.0custom-elements-manifest/analyzerVanilla、LitElement、FASTElement、Stencil、Catalyst、Atomico旧版本格式web-component-analyzerLitElement、Polymer、Vanilla、Stencil旧版本格式stenciljs自带docs-vscodeStencil元数据可能不完整如果使用 Stencil可在stencil.config.ts的outputTargets中加入docs-vscode目标来直接产出该文件{ type: docs-vscode, file: custom-elements.json }仓库中web-componentsrenderer 自带的测试夹具 custom-elements.json 就是一份 v1.0.0 规范的真实示例其顶层结构为{ schemaVersion: 1.0.0, readme: , modules: [ { kind: javascript-module, path: demo-wc-card/index.js, declarations: [], exports: [] }, { kind: javascript-module, path: demo-wc-card/DemoWcCard.js, declarations: [ { kind: class, description: This is a container looking like a card with a back and front side you can switch, name: DemoWcCard, tagName: demo-wc-card, customElement: true, members: [], properties: [], attributes: [], events: [], slots: [], cssProperties: [], cssParts: [] } ] } ] }注意 v1.0.0 规范中组件的属性、事件、插槽、CSS 自定义属性与 Shadow Parts 都声明在modules[].declarations[]内的类声明对象上并以tagName标识对应自定义元素。在 preview 中注册清单四种完整写法注册动作发生在 Storybook 的预览配置文件.storybook/preview.js|ts中。核心 API 是从storybook/web-components-vite导入的setCustomElementsManifest将清单对象作为参数传入。下面完整继承原文档给出的四种写法。JavaScriptCSF 3import { setCustomElementsManifest } from storybook/web-components-vite; import customElements from ../custom-elements.json; setCustomElementsManifest(customElements); export default { parameters: { controls: { matchers: { color: /(background|color)$/i, date: /Date$/, }, }, }, };TypeScriptCSF 3import type { Preview } from storybook/web-components-vite; import { setCustomElementsManifest } from storybook/web-components-vite; import customElements from ../custom-elements.json; setCustomElementsManifest(customElements); const preview: Preview { parameters: { controls: { matchers: { color: /(background|color)$/i, date: /Date$/i, }, }, }, }; export default preview;TypeScriptCSF Next 实验性写法CSF Next 使用definePreview替代默认导出对象注册逻辑保持不变import { definePreview, setCustomElementsManifest } from storybook/web-components-vite; import customElements from ../custom-elements.json; setCustomElementsManifest(customElements); export default definePreview({ parameters: { controls: { matchers: { color: /(background|color)$/i, date: /Date$/i, }, }, }, });JavaScriptCSF Next import { definePreview, setCustomElementsManifest } from storybook/web-components-vite; import customElements from ../custom-elements.json; setCustomElementsManifest(customElements); export default definePreview({ parameters: { controls: { matchers: { color: /(background|color)$/i, date: /Date$/, }, }, }, });各写法要点说明导入路径统一为storybook/web-components-vite若使用 Webpack5 构建器则对应storybook/web-componentsTypeScript 写法可额外导入Preview类型获得配置提示。import customElements from ../custom-elements.json需要项目支持 JSON 模块导入Vite 默认支持若使用 Webpack 需确认配置路径以.storybook为基准指向仓库根目录的清单文件。setCustomElementsManifest(customElements)必须在导出preview配置之前调用确保运行时尽早注册。controls.matchers与清单解析相互独立color与date正则用于将 arg 名匹配到对应控件类型而清单负责提供 arg 的类型、默认值与描述。注册背后的实现global 单例与清单校验setCustomElementsManifest的实现位于 framework-api.ts逻辑非常简洁——将清单挂载到全局对象上export function setCustomElements(customElements: any) { global.__STORYBOOK_CUSTOM_ELEMENTS__ customElements; } export function setCustomElementsManifest(customElements: any) { global.__STORYBOOK_CUSTOM_ELEMENTS_MANIFEST__ customElements; } export function getCustomElements() { return global.__STORYBOOK_CUSTOM_ELEMENTS__ || global.__STORYBOOK_CUSTOM_ELEMENTS_MANIFEST__; }从中可以确认两点事实存在两套历史 API较早的setCustomElements旧版清单与当前的setCustomElementsManifestv1.0.0 清单读取时getCustomElements优先返回旧 API 写入的数据清单以全局单例形式存在web-components渲染器在提取 argTypes 时通过getCustomElements()统一读取见 custom-elements.ts。同时framework-api.ts 中的isValidMetaData负责在解析阶段做结构校验清单必须包含tags数组旧版格式或modules数组v1.0.0 格式否则抛出提示 You need to setup valid meta data in your config.js via setCustomElements()。因此注册时传入空对象或错误结构的 JSON 会直接导致解析失败。argTypes 提取原理两种 schema 的兼容解析注册后的清单在渲染时由 custom-elements.ts 消费核心流程是extractArgTypes(tagName)→getCustomElements()→getMetaData()→extractArgTypesFromElements()。getMetaData依据manifest.version experimental分支处理两种格式custom-elements.tsexperimental 格式直接在顶层tags数组中按tag.name匹配组件大小写不敏感找不到时输出Component not found in custom-elements.json: xxx警告v1.0.0 格式遍历modules[].declarations[]按declaration.tagName精确匹配组件。匹配成功后extractArgTypesFromElements将清单中各类声明映射为 argTypescustom-elements.tsreturn ( metaData { ...mapData(metaData.members ?? [], properties), ...mapData(metaData.properties ?? [], properties), ...mapData(metaData.attributes ?? [], attributes), ...mapData(metaData.events ?? [], events), ...mapData(metaData.slots ?? [], slots), ...mapData(metaData.cssProperties ?? [], css custom properties), ...mapData(metaData.cssParts ?? [], css shadow parts), } );映射规则同样可以从源码确认properties/attributes生成常规 InputType类型取自item.type.text默认值取item.default或item.defaultValue并写入table.category分组custom-elements.tsevents会被映射为两个 argType一个onXxx形式的 action 控件事件名经 kebab-case 转 camelCase 后再加on前缀且在表格中禁用另一个作为events分类的常规条目custom-elements.tsslots统一映射为string类型cssProperties与cssParts归入对应分类kind method的成员会被过滤不生成控件custom-elements.ts。组件描述Props 表格顶部的说明文字则由extractComponentDescription读取声明对象的description字段。与 story 文件的配合清单注册完成后需要在每个 story 文件中通过component指定标签名Storybook 才能据此查表export default { title: Demo Card, component: demo-wc-card, // 必须与 custom-elements.json 中的 tagName 一致 };在仓库自带的模板 story 中可以看到同样的组合preview.js 首先调用setCustomElementsManifest(customElementsManifest)注册清单随后 story 声明component: demo-wc-card与 custom-elements.json 中声明的tagName一一对应。若标签名在清单中不存在渲染时会输出Component not found in custom-elements.json警告且无法生成对应 argTypes。常见问题与排查建议Controls 面板空白或属性缺失优先检查custom-elements.json结构是否符合所选 schematags顶层数组 vsmodules[].declarations[]并确认setCustomElementsManifest已调用且传入了完整对象Component not found in custom-elements.json警告story 中的component标签名与清单tagName不一致注意大小写与连字符写法类型提示丢失确认清单中members/properties/attributes携带type.text字段分析器未输出类型时 Storybook 无法推断控件事件控件未出现事件需要声明在events字段中并确保事件名符合 kebab-case 转 camelCase 的映射规则。延伸阅读Controls 文档本片段被引用的上下文argTypes 参考Web Components 框架文档framework-api.ts 实现custom-elements.ts argTypes 提取实现manifest 真实示例【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表