蓝戒博客

  • 首页
  • 研发说
  • 架构论
  • 效能录
  • AI谈
  • 随笔集
智构苍穹
融合 AI、架构与工程实践,沉淀方法论,构建可持续的技术价值。
  1. 首页
  2. 效能录
  3. 正文

基于 Monaco Editor 的 Web Component 智能提示实践

2026年2月8日 8点热度 0人点赞 0条评论

——通过 custom-elements.json 实现 yp-* 组件的跨框架自动补全

背景

在构建 Web Component 组件库(如 yp-button、yp-input 等)时,组件具备天然的跨框架能力,但**开发体验(DX)**往往成为落地的最大障碍:

  • HTML 中没有组件与属性补全
  • Vue / React 模板里无法识别自定义标签
  • Markdown 中示例代码没有任何智能提示
  • IDE 插件维护成本高,难以定制

而 Monaco Editor(VS Code 内核)为 Web 编辑器场景提供了一个理想的解决方案:

通过插件机制,在运行时注入组件元信息,实现“类 IDE”级别的智能提示。

本文将完整拆解一个实战方案:

基于 custom-elements.json,在 Monaco Editor 中实现 yp- Web Component 的:*

  • 标签自动补全
  • 属性 / 类型 / 描述提示
  • 事件提示
  • 支持 HTML / Vue / React / Markdown

一、整体方案设计

目标能力

能力说明
固定前缀识别仅对 yp- 开头组件生效
标签补全<yp-button>
属性补全type、size、disabled
属性说明description / default / type
事件提示@click / onClick
多语言支持HTML / Vue / React / Markdown
无侵入不依赖 VS Code 插件

核心技术选型

技术作用
monaco-editor编辑器内核
custom-elements.jsonWeb Component 元数据标准
CompletionItemProviderMonaco 插件扩展点
HTML / TS Language Service多语言能力复用

二、custom-elements.json 作为唯一数据源

1️⃣ custom-elements.json 是什么

这是由 Web Components 社区推动的组件元信息标准,典型结构如下:

JSON
{
  "schemaVersion": "1.0.0",
  "tags": [
    {
      "name": "yp-button",
      "description": "按钮组件",
      "attributes": [
        {
          "name": "type",
          "type": "primary | success | warning",
          "description": "按钮类型",
          "default": "default"
        }
      ],
      "events": [
        {
          "name": "click",
          "description": "点击事件"
        }
      ]
    }
  ]
}

2️⃣ 为什么选择它

  • 与 Lit / Stencil / FAST / Vue Custom Element 生态兼容
  • 可自动生成
  • 一次定义,多处消费
  • 非 Monaco / VS Code 强绑定

三、解析 custom-elements.json

1️⃣ 数据结构归一化

TypeScript
interface ComponentMeta {
  tag: string
  description?: string
  attributes: AttributeMeta[]
  events: EventMeta[]
}
TypeScript
function parseCustomElements(json: any): ComponentMeta[] {
  return json.tags
    .filter((tag: any) => tag.name.startsWith('yp-'))
    .map((tag: any) => ({
      tag: tag.name,
      description: tag.description,
      attributes: tag.attributes ?? [],
      events: tag.events ?? []
    }))
}

四、Monaco 插件机制实现

1️⃣ 注册 HTML 补全提供器

TypeScript
monaco.languages.registerCompletionItemProvider('html', {
  triggerCharacters: ['<', ' ', ':', '@'],
  provideCompletionItems(model, position) {
    return getCompletions(model, position)
  }
})

2️⃣ 标签自动补全(yp-*)

TypeScript
function getTagCompletions(components: ComponentMeta[]) {
  return components.map(comp => ({
    label: comp.tag,
    kind: monaco.languages.CompletionItemKind.Class,
    insertText: comp.tag,
    documentation: comp.description
  }))
}

效果:

<yp-│(提示所有组件)

3️⃣ 属性补全(HTML / Vue)

TypeScript
function getAttributeCompletions(component: ComponentMeta) {
  return component.attributes.map(attr => ({
    label: attr.name,
    kind: monaco.languages.CompletionItemKind.Property,
    insertText: `${attr.name}="$1"`,
    documentation: `
${attr.description}
类型:${attr.type}
默认值:${attr.default ?? '-'}
`
  }))
}

4️⃣ Vue 指令 / 事件补全

TypeScript
function getVueEventCompletions(component: ComponentMeta) {
  return component.events.map(evt => ({
    label: `@${evt.name}`,
    kind: monaco.languages.CompletionItemKind.Event,
    insertText: `@${evt.name}="$1"`,
    documentation: evt.description
  }))
}

5️⃣ React JSX 事件支持

TypeScript
function toReactEvent(name: string) {
  return 'on' + name.charAt(0).toUpperCase() + name.slice(1)
}
TypeScript
label: toReactEvent(evt.name)
insertText: `${toReactEvent(evt.name)}={$1}`

五、多语言支持策略

HTML

  • 原生支持
  • 直接注册 html provider

Vue(template)

TypeScript
monaco.languages.registerCompletionItemProvider('vue', {
  provideCompletionItems: htmlProvider
})

复用 HTML 规则即可。


React(JSX / TSX)

TypeScript
monaco.languages.registerCompletionItemProvider('typescript', {
  provideCompletionItems: jsxProvider
})

识别 <yp- 上下文即可。


Markdown

TypeScript
monaco.languages.registerCompletionItemProvider('markdown', {
  provideCompletionItems(model, position) {
    // 仅在 ```html / ```vue 区块内生效
  }
})

六、插件化设计

1️⃣ 插件接口定义

TypeScript
interface MonacoWebComponentPlugin {
  name: string
  setup(monaco: typeof import('monaco-editor')): void
}

2️⃣ 插件注册

TypeScript
const ypWebComponentPlugin: MonacoWebComponentPlugin = {
  name: 'yp-webcomponent',
  setup(monaco) {
    registerHtmlProvider(monaco)
    registerVueProvider(monaco)
    registerJsxProvider(monaco)
    registerMarkdownProvider(monaco)
  }
}

七、最终效果

✅ 输入 <yp- 自动提示组件
✅ 输入属性立即补全
✅ hover 查看属性说明
✅ Vue / React 语法差异自动适配
✅ Markdown 示例代码也有智能提示


八、最佳实践总结

关键经验

  1. custom-elements.json 是 DX 的核心资产
  2. Monaco 插件应尽量无状态、可组合
  3. 固定前缀能显著降低补全干扰
  4. Vue / React 差异应在补全层解决
  5. Markdown 支持极大提升文档体验

九、适用场景

  • Web Component 组件库官网
  • 在线 Playground / Demo
  • 低代码 / 页面搭建器
  • 跨框架组件文档系统

结语

通过 Monaco Editor + custom-elements.json + 插件机制,
可以在 浏览器中复刻 IDE 级别的 Web Component 开发体验,并且:

  • 不依赖 VS Code
  • 不绑定单一框架
  • 可持续演进

这是一条非常适合 Web Component 组件库、Design System 的工程化路径。

如果你正在做组件库、低代码或在线编辑器,这套方案值得长期投入。

标签: custom-elements.json Monaco Editor Web Component 智能提示 自动补全
最后更新:2026年2月8日

cywcd

我始终相信,技术不仅是解决问题的工具,更是推动思维进化和创造价值的方式。从研发到架构,追求极致效能;在随笔中沉淀思考,于 AI 中对话未来。

打赏 点赞
< 上一篇

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

cywcd

我始终相信,技术不仅是解决问题的工具,更是推动思维进化和创造价值的方式。从研发到架构,追求极致效能;在随笔中沉淀思考,于 AI 中对话未来。

最新 热点 随机
最新 热点 随机
基于 Monaco Editor 的 Web Component 智能提示实践 AI 智能体框架选型:主流方案对比与建议 Vue AI Skill:vue-skills —— 教 AI 正确写 Vue OpenCode:一个真正「为程序员而生」的开源 AI 编程 Agent Vue 全家桶 Skills:让 AI 真正“懂 Vue”的一次工程化升级 TypeScript 工具类型分享:从常用到进阶,实现可维护的类型体系
WebAssembly(WASM)技术全景解析:从浏览器加速到云原生基石用 Yjs 打造下一代协同编辑应用Docker 进阶(七):容器化体系设计总结与生产落地经验复盘Unplugin:统一前端构建插件体系的工程化解法吃透大文件分片上传:原理、方案与最佳实践前端 Worker + WebAssembly + 主线程协作:一次讲清高性能计算模型
vue中使用v-for循环,动态绑定失效解决方法,循环列表显示/隐藏单独控制实例 js判断浏览器类型并区分IE不同版本 Vue 3.6「无虚拟 DOM」时代开启:深入解读 Vapor Mode 的革命性变革 SlipJs高效实现移动web页面整屏滑动 javascript开源物理引擎verlet.js js事件流:冒泡事件和捕获事件详解
最近评论
渔夫 发布于 3 个月前(11月05日) 学到了,感谢博主分享
沙拉小王子 发布于 8 年前(11月30日) 适合vue入门者学习,赞一个
沙拉小王子 发布于 8 年前(11月30日) 适合vue入门者学习,赞一个
cywcd 发布于 9 年前(04月27日) 请参考一下这篇文章http://www.jianshu.com/p/fa4460e75cd8
cywcd 发布于 9 年前(04月27日) 请参考一下这篇文章http://www.jianshu.com/p/fa4460e75cd8

COPYRIGHT © 2025 蓝戒博客_智构苍穹-专注于大前端领域技术生态. ALL RIGHTS RESERVED.

京ICP备12026697号-2