普通视图

发现新文章,点击刷新页面。
昨天 — 2025年7月2日首页

OpenTiny训练营实操体验|轻松解锁TinyVue智能组件开发Web应用

2025年7月1日 09:27

1.背景描述

TinyVue 是一套企业级的 Vue 框架下的组件库,它具有跨端、跨框架的特性,同时支持 Vue2 和 Vue3,支持 PC 端和移动端浏览器。

本次实验是通过改造一个使用 TinyVue 组件的常规 Web 应用,秒变为一个能够对接大语言模型的智能应用。这个应用可以让用户通过自然语言与网页进行对话,直接“精准”操作网页上的组件。

2.实验简介

首先,我们提供了一个用  Vue3  搭建的商品列表管理的单页面应用,它使用 TinyVue 组件库中的  Select、Grid  等组件。该商品管理应用默认会显示商品管理的表格,并且已经实现了条件查询商品,添加、删除商品和保存商品等功能。但此应用目前不支持 AI 大模型的操作,比如打开智能助手,发送的信息不会正确执行。

对接 TinyVue Next 智能框架的相关包,给 Select、Grid  等组件添加业务描述后,让智能助手等功能可以遥控操作网页。

3.基本要求

  • 熟练使用 VSCode 或其他代码编辑器
  • 具有 Chrome、Edge 等浏览器的调试能力
  • 熟悉 Vue 开发,以及具有 TinyVue 或其它组件库的开发经验

4.代码实战

4.1 启动电商平台 demo 页面,熟悉功能

解压桌面上的工程压缩文件 agent-app-demo (可能位置与名称有调整,有疑问可咨询)

解压完成后用 VSCode 软件打开指定的工程目录,打开终端,执行以下命令安装依赖:

npm install

安装完成后执行以下命令,启动电商平台 demo 页面。

npm run dev

启动成功后,查看商品列表并简单的进行增删改查的操作。

但此时测试 AI 智能助手,则是无响应的。下一步就来对应用进行简单改造。

4.2 引用 vue-next 等智能包进行应用改造

将上面的普通应用,秒变为智能应用,需要以下 4 步, 需要按顺序完成。

4.2.1 引入智能包

在终端中执行以下命令,安装相关智能包。

npm install @opentiny/tiny-vue-mcp @opentiny/next-vue -S

4.2.2 全局注册 TinyVue MCP 的工具

main.ts 文件中,引入@opentiny/tiny-vue-mcp,注册 TinyVue MCP 的工具。

import { createMcpTools, getTinyVueMcpConfig } from "@opentiny/tiny-vue-mcp";

import { registerMcpConfig } from "@opentiny/vue-common";

// 1、 将 TinyVue MCP的工具注入到 vue-common 层中,之后应用可以TinyVue MCP的功能

registerMcpConfig(getTinyVueMcpConfig(), createMcpTools);

4.2.3  创建 MCP Client 的远端会话

App.vue文件中,引入@opentiny/next-vue, 创建 MCP Client 的远端会话。

注意:代码中连接需要自行提供
目前 agent 代理服务器代码未开源,如想进一步了解可以在 github 中提 issue 单
提交 issue 连接:github.com/opentiny/ti…

import { useNextClient } from"@opentiny/next-vue";
import { globalConversation } from"./composable/utils";

// 2、创建 sessionId , 一个 ref<string> 的值, 并保存起来,智能助手会访问该变量进行通讯

const { sessionId } = useNextClient({
clientInfo: { name"my-project"version"1.0.0" },
// url为工具调用方,token为对应的凭证
proxyOptions: { url"https://xxx/sse"token"" },
});

globalConversation.sessionId = sessionId;

4.2.4 在应用页面,创建 MCP Server, 并给组件声明“业务属性”

views/productManager/index.vue中,创建 MCP Server

import { useNextServer } from "@opentiny/next-vue";
// 3、创建web应用所需的 McpServer 变量, 用于注册页面中的组件到系统中。
const { server } = useNextServer({
  serverInfo: { name"company-list"version"1.0.0" },
});
// 4、 模板中,在AI智能助手要操作的组件上,去绑定 server 和 组件的 “业务描述”。  这样 AI就能关联mcp,并识别每个组件的业务定义了。

views/productManager/index.vue文件中, 可以改造 TinyVue 的组件,它们支持属性 tiny_mcp_config, 传入 server 和组件的业务描述,例如:

<tiny-base-select
  v-model="statusFilter"
  :options="statusOptions"
  placeholder="商品状态"
  clearable
  :tiny_mcp_config="{
    server,
    business: {
      id: 'category-status',
      description: '商品状态的下拉框',
    },
  }"
>
</tiny-base-select>

其中 business.id 是组件在页面上的唯一 id。 business.description 是描述组件的业务含义, 这样与大模型对话时,大模型可以“精准”的知道页面上有什么可以操纵。

接下来,给商品状态的 Select, 商品列表的表格,按钮等等,都可以添加上 :tiny_mcp_config 属性了。

给分类下拉框添加 tiny_mcp_config

<tiny-base-select
  v-model="categoryFilter"
  :options="categoryOptions"
  placeholder="商品分类"
  clearable
  :tiny_mcp_config="{
    server,
    business: {
      id: 'category-select',
      description: '商品分类的下拉框',
    },
  }"
>
</tiny-base-select>

给商品列表表格添加

<tiny-grid
  auto-resize
  ref="gridRef"
  :data="displayProducts"
  :height="520"
  :edit-config="{ trigger: 'click', mode: 'cell', showStatus: true }"
  :tiny_mcp_config="{
    server,
    business: {
      id: 'category-list',
      description: '商品列表',
    },
  }"
>
  <!--省略部分代码-->
</tiny-grid>

4.3 通过页面的 AI 智能助手进行网页的智能操作

经过 4.2 节, 我们已经将普通的应用秒变为智能应用。此时就可以通过“AI 智能体”工具跟网页对话了

对下拉框,你可以尝试提问:   在商品分类下拉框中,弹出下拉面板选中手机分类。

对于表格, 你可以问:帮我在商品列表中删除最贵的且分类为手机的商品。

这里就可以发挥想像力,对网页进行各种提问,看看大模型能否正确判断行为,并调用正确的 MCP 方法。

如果“AI 智能体”工具不能执行成功,可以打开浏览器控制台,参考以下内容进行排查:

控制台有无报错

打开“网络” 面板,查看 chat-messages 接口是否异常

图片

查看控制台打印的: SSE data: xxxx  信息。可以跟踪大模型的执行过程,查看调用 MCP 工具的中间过程等。

图片

4.4 页面添加可识别二维码,通过手机远程操作

通过文字去操作页面有点麻烦,如果能通过语音就是远程遥控网页是不是就好了。

在“App.vue”的顶部增加 的二维码组件:

<div class="qr-code">
  <span>
    页面识别二维码, 请用手机扫码后,在浏览器中打开。
    微信的浏览器可能没有语音功能,需要使用手机内置的浏览器访问。
  </span>
  <tiny-qr-code :value="sessionUrl" :size="100" color="#1677ff"></tiny-qr-code>
   
</div>

二维码的 value= sessionUrl ,它是通过 sessionId 计算出来的一个 url。在App.vue添加以下 js 代码:

注意:代码中连接需要自行实现并部署远程操控服务
如对此有疑问或者有兴趣交流,欢迎提交 issue: github.com/opentiny/ti…

import CryptoJSfrom"crypto-js";
import { computed } from"vue";

const sessionUrl = computed(() => {
// 未创建session时

if (!sessionId.valuereturn"no session"// 创建好 sessionId后,加密后拼接成 sessionUrl ,  这样手机扫码后会连接这个Url页面

const encryptedId = CryptoJS.AES.encrypt(
    sessionId.value,
    "secret-session-id"
  ).toString();

return"https://xxx?id=" + encodeURIComponent(encryptedId);
});

这样,我们的应用顶部会有一个二维码,用手机扫描后,使用手机上的浏览器打开,就可以选择“语音控制器”,跟它对话了,通过手机远程指挥网页。

因为上述流程中 proxyOptions.url 与 语音远程操控页面需要自行部署服务,因此提供了临时的线上体验连接:opentiny.design/tiny-vue/zh…

5.实验总结

通过本次实验,我们不仅掌握了将普通 Web 应用转化为智能 Web 应用的关键技能,还学会了利用智能助手或远程手机对网页进行精准操控。

该实验引导用户深入思考网页未来可能呈现的形态与无限可能,让每一位用户都能深切体验到人工智能为 Web 开发领域所带来的震撼,感受技术进步如何重塑我们的网页世界。

关于 OpenTiny

欢迎加入 OpenTiny 开源社区。添加微信小助手:opentiny-official 一起参与交流前端技术~

OpenTiny 官网:opentiny.design
OpenTiny 代码仓库:github.com/opentiny
TinyVue 源码:github.com/opentiny/ti…
TinyEngine 源码: github.com/opentiny/ti…
欢迎进入代码仓库 Star🌟TinyEngine、TinyVue、TinyNG、TinyCLI、TinyEditor~
如果你也想要共建,可以进入代码仓库,找到 good first issue 标签,一起参与开源贡献~

AI助力快速引入外部组件到TinyEngine低代码引擎

2025年7月2日 16:36

本文由羽毛笔记作者观默原创。

背景:低代码时代的开发挑战

TinyEngine作为一款优秀的低代码平台,以其强大的功能和快速迭代能力赢得了众多开发者的青睐。它让开发者能够通过可视化界面快速构建应用,大大提升了开发效率。

然而,就像一座美丽的花园需要更多花卉品种来装点一样,TinyEngine也面临着组件生态的挑战:官方提供的组件虽然精心设计,但数量有限,难以满足企业级项目的多样化需求。更具挑战性的是,要将私有组件库接入TinyEngine,必须先为每个组件生成对应的schema文件——这就像为每朵花制作专属的标签卡片。

从痛点到机遇:AI时代的解决方案

最近,我们公司面临着将私有组件库接入TinyEngine的需求。如果采用传统的人工方式为每个组件编写schema文件,不仅耗时费力,更重要的是缺乏那种让人兴奋的技术创新感。想象一下,如果有几十个组件需要处理,那将是一个令人望而却步的重复性工作。

这让我开始思考:在AI技术日新月异的今天,是否有更优雅的解决方案?

传统方案 VS AI方案

在AI时代之前,我可能会选择**Babel + AST(抽象语法树)**的技术路线:

  • 解析Vue组件源码
  • 遍历AST节点
  • 提取props、events、slots信息
  • 手工编写转换逻辑

这种方法虽然可行,但就像用显微镜逐个检查细胞一样繁琐。而现在,我们有了更强大的工具——AI大语言模型

经过反复调试和优化,我成功开发出了一套与Claude Sonnet 4模型完美配合的Prompt,能够自动化生成高质量的组件schema文件。这就像拥有了一位经验丰富的架构师助手,能够理解组件的每一个细节并生成标准化的配置文件。

schema 生成 Prompt:

注意:group/category/npm 这三个字段请根据实际情况调整,不要照抄!

# 任务:Vue 组件 Schema 生成器

你是一位精通 Vue 3 Composition API、TypeScript 及低代码平台组件集成的资深架构师。你的任务是接收一个 Vue 组件的源代码及相关项目文件,然后生成一个完全符合指定规则、高度精确且信息丰富的 JSON Schema 文件,用于驱动低代码平台。

你的输出必须是一个**完整的、格式正确的 JSON 对象**,不包含任何额外的解释性文字。

---

### 前置检查:验证输入信息

在开始生成 Schema 之前,你必须首先验证是否已收到所有必需的信息。

**以下项目是必需的:**

1.  **`组件源代码`**: 目标 `.vue` 文件的完整内容。
2.  **`package.json`**: 项目的 `package.json` 文件完整内容。

**可选的组件元数据***   `中文名称 (zh_CN)`: 如果未提供,从组件的 `defineComponent({ name: '...' })` 中提取 `name` 值。
*   `图标 (icon)`: 如果未提供,从组件的 `defineComponent({ name: '...' })` 中提取 `name` 值。
*   `描述 (description)`
*   `标签 (tags)`
*   `关键词 (keywords)`
*   `文档链接 (doc_url)`

**如果必需信息缺失,请不要继续。** 你的回应应该是一个清晰的请求,明确指出用户需要提供哪些缺失的具体内容。

只有在确认所有必需输入都已提供后,才能继续执行下面的生成步骤。

---

### 第一步:分析输入 (假设已通过前置检查)

你将收到以下输入:

1.  **`组件源代码`**: 一个完整的 Vue 组件 (`.vue`) 的文本内容。
2.  **`package.json`**: 项目的 `package.json` 文件内容。
3.  **`组件元数据` (可选)**:
    *   `中文名称 (zh_CN)`
    *   `图标 (icon)`
    *   `描述 (description)`
    *   `标签 (tags)`
    *   `关键词 (keywords)`
    *   `文档链接 (doc_url)`

---

### 第二步:执行生成规则

请严格按照以下规则,一步步构建最终的 JSON 对象:

#### 1. **顶层字段填充**

*   `component`: 从组件的 `defineComponent({ name: '...' })` 中提取 `name` 值。
*   **`name.zh_CN`**: 
    - 如果 `组件元数据` 中提供了 `中文名称`,则使用该值
    - 否则根据 `component` 名称进行智能推断和翻译:
      - `Button` -> `"按钮"`
      - `LoginInfo` -> `"登录信息"`
      - `SixAxisRobot` -> `"六轴机械臂"`
      - `Chamber` -> `"腔体"`
      - `Aligner` -> `"对中器"`
      - `MainMenuButton` -> `"主菜单按钮"`
      - `CdsState` -> `"CDS状态"`
      - 其他名称按语义进行合理的中文翻译
*   **`icon`**: 
    - 如果 `组件元数据` 中提供了 `图标`,则使用该值
    - 否则默认使用 `component` 名称(如 `"SixAxisRobot"` -> `"SixAxisRobot"`)
*   **`group`**: 固定为 `"DCP"`
*   **`category`**: 固定为 `"DCP"`
*   `description`: 如果 `组件元数据` 中提供了 `description`,则使用该值;否则默认为 `""`。
*   `tags`: 如果 `组件元数据` 中提供了 `tags`,则使用该值;否则默认为 `""`。
*   `keywords`: 如果 `组件元数据` 中提供了 `keywords`,则使用该值;否则默认为 `""`。
*   `doc_url`: 如果 `组件元数据` 中提供了 `doc_url`,则使用该值;否则默认为 `""`。
*   `devMode`: 固定为 `"proCode"`。

#### 2. **`npm` 对象构建**

根据 `package.json` 的内容,动态构建 `npm` 对象:

*   `package`: 从 `package.json` 中读取 `name` 字段。
*   `exportName`: **必须**与顶层 `component` 字段的值保持一致。
*   `version`: 从 `package.json` 中读取 `version` 字段。
*   `script`: 基于 `package.json` 的信息,拼接成固定格式:`"http://192.168.0.212:4874/{package}@{version}/js/web-component.mjs"`。
*   `destructuring`: 固定为 `true`。
*   `npmrc`:
    1.  从 `package.json` 的 `name` 字段提取 scope (例如 `@dcp/component-library` -> `@dcp`)。
    2.  从 `package.json` 的 `publishConfig.registry` 字段提取 registry URL (并移除末尾的 `/`)。
    3.  拼接成 `"{scope}:registry={registry_url}"` 的格式。

#### 3. **`configure` 对象构建**

生成完整的 `configure` 对象,包含以下所有字段:

**基础行为控制***   `loop`: 固定为 `true`(支持循环渲染)
*   `condition`: 固定为 `true`(支持条件渲染)
*   `styles`: 固定为 `true`(支持样式配置)

**组件类型标识***   `isContainer`: 根据组件分析决定:
    - 如果组件模板中包含 `<slot>` 标签,设置为 `true`
    - 如果组件名称暗示容器用途(如 Layout、Container、Wrapper),设置为 `true`
    - 否则设置为 `false`
*   `isModal`: 固定为 `false`(除非组件明确是模态框)
*   `isPopper`: 固定为 `false`(除非组件明确是弹出框)
*   `isNullNode`: 固定为 `false`
*   `isLayout`: 根据组件用途判断,Layout 类组件设置为 `true`,否则为 `false`

**嵌套规则***   `nestingRule`: 对象包含以下字段,通常设置为默认值:
    - `childWhitelist`: `""`(允许的子组件白名单,通常为空)
    - `parentWhitelist`: `""`(允许的父组件白名单,通常为空)
    - `descendantBlacklist`: `""`(禁止的后代组件黑名单,通常为空)
    - `ancestorWhitelist`: `""`(允许的祖先组件白名单,通常为空)

**编辑器配置***   `rootSelector`: 固定为 `""`
*   `shortcuts.properties`: 识别出组件最核心、最常用的 1-3 个 props,填入此数组
*   `contextMenu`: 对象包含:
    - `actions`: 默认为 `["copy", "remove", "insert", "updateAttr", "bindEevent"]`
    - `disable`: 默认为 `[]`

**交互行为** (可选字段,根据组件类型添加):
*   `clickCapture`: 对于按钮类、交互类组件设置为 `true`,其他组件可省略或设置为 `false`
*   `framework`: 如果是第三方组件库保持原值,自定义组件设置为 `"Vue"`

#### 4. **`schema.properties` (Props 分组映射)**

将 Vue 组件的所有 props 按逻辑功能分组,生成一个**分组数组****分组策略***   **基础属性**: 核心功能相关的 props(如 name、size、type 等)
*   **样式属性**: 外观、颜色、尺寸相关的 props(如 width、height、backgroundColor、color 等)
*   **行为属性**: 交互、事件、状态相关的 props(如 disabled、loading、onClick 等)
*   **高级属性**: 可选的、专业配置项(如复杂对象配置、高级选项等)

**每个分组对象必须包含***   `name`: 分组标识符,使用数字字符串(如 `"0"`, `"1"`, `"2"`*   `label.zh_CN`: 分组的中文显示名称(如 `"基础属性"`, `"样式属性"`*   `description.zh_CN`: 分组的中文描述
*   `content`: 该分组下的具体属性配置数组

**`content` 数组中的每个属性对象必须包含以下固定字段***   `property`: Prop 的名称
*   `label.text.zh_CN`: 中文标签
*   `description`: 中文描述
*   `required`: 根据 Vue Prop 中的 `required` 字段决定,默认为 `false`
*   `readOnly`: 固定为 `false`
*   `disabled`: **固定为 `false`**
*   `cols`: **固定为 `12`**
*   `labelPosition`: 固定为 `"left"`
*   `type`: Vue 类型转换为小写字符串
*   `defaultValue`: Vue Prop 的默认值
*   `widget`: 根据以下规则推断

**Widget 推断规则 (按优先级顺序)**1. **validator 函数解析 (最高优先级)**:
   - 如果 Prop 定义中存在 `validator` 函数,解析函数体中的选项数组
   - 设置 `widget.component``"SelectConfigurator"`
   - 设置 `widget.props.options` 为解析出的选项数组

2. **属性名称模式匹配**:
   - 名称包含 `color` 或默认值以 `#` 开头 -> `"ColorConfigurator"`,props: `{}`
   - 名称包含 `icon` -> `"InputConfigurator"`,props: `{ "placeholder": "请输入图标名称" }`

3. **Vue 类型 + 语义推断**:
   - `Boolean` 类型:
     - 开关语义 (show*, enable*, is*) -> `"SwitchConfigurator"`,props: `{}`
     - 选项语义 (disabled, loading, plain, round, circle) -> `"CheckBoxConfigurator"`,props: `{}`
   - `Number` 类型 -> `"NumberConfigurator"`,根据属性名称设置 props:
     - 尺寸类 (width, height, size): `{ "min": 50, "max": 2000, "step": 10 }`
     - 角度类 (rotate, angle): `{ "min": 0, "max": 360, "step": 1 }`
     - 比例类 (scale): `{ "min": 0.1, "max": 5, "step": 0.1 }`
     - 时间类 (duration, delay): `{ "min": 0, "max": 50, "step": 0.1 }`
     - 默认: `{ "step": 1 }`
   - `String` 类型 -> `"InputConfigurator"`,props: `{ "placeholder": "请输入..." }`
   - `Object`/`Array` 类型 -> `"CodeConfigurator"`,props: `{ "language": "json", "height": 150 }`

4. **智能类型分析**:
   - 如果 Prop 类型为 `Array as PropType<SomeInterface[]>`,在 `description` 中补充接口结构信息

#### 5. **`schema.events` (事件映射)**

*   在组件 `<script>` 中搜索所有 `emit('event-name', ...)` 的调用。
*   每一个 `event-name` (kebab-case) 都对应 `events` 对象中的一个键。
*   该键的命名规则为 **`'on' +` 将 `event-name` 转换为首字母大写的驼峰式 (CamelCase)**。例如,`emit('menu-item-click')` 映射为 `onMenuItemClick`*   分析 `emit` 的参数,为该事件生成 `functionInfo.params` 数组。

#### 6. **`schema.slots` (插槽分析)**

*   扫描组件的 `<template>` 部分,寻找所有 `<slot>` 标签。
*   对于每一个**具名插槽** (例如 `<slot name="menu-items">`),在 `schema.slots` 对象中为其添加一个条目。
*   该条目的键为插槽名 (`menu-items`),值为一个包含 `label.zh_CN``description.zh_CN` 的对象,用于描述该插槽的用途。

#### 7. **`snippets` (智能代码片段生成)**

*   生成一个只包含**单个默认 Snippet** 的数组 `[]`*   `name.zh_CN`, `icon`, `snippetName` 与顶层字段保持一致。
*   `schema.props`:
    *   **优先策略**: 在工作区中查找与组件同名的 `.stories.ts` 文件。如果找到,请使用其 `args` 对象作为 `props` 的数据来源。
    *   **备用策略**: 如果找不到 Storybook 文件,请不要简单地使用 `defaultValue`。应根据每个 Prop 的语境,创建一组有意义、更具代表性的示例值(例如,`username` 使用 `'Admin'` 而不是 `'User'`)。

---

### 第三步:输出最终 JSON

请整合以上所有分析结果,生成最终的 JSON 文件。

实战指南:从理论到实践

第一步:智能生成Schema

运用AI生成schema的过程就像与一位专业顾问的对话。让我们以Cursor编辑器为例,一步步地体验这个过程:

操作步骤:

  1. 打开组件项目:启动Cursor,进入你的Vue组件库项目
  2. 准备上下文材料:在聊天界面中添加以下关键文件:
    • 项目根目录的package.json
    • 目标组件的.vue源码文件
  3. 粘贴Prompt:将上文提供的完整Prompt复制到输入框
  4. 发起对话:按下回车键,等待AI的魔法发生

为什么选择Claude Sonnet 4?

经过测试对比,我发现Claude Sonnet 4在理解Vue组件结构和生成精准schema方面表现出色,像deepseek、qwen这些国内模型暂时无法:

  • 精准的类型推断:能够正确识别Props的TypeScript类型并转换为对应的widget配置
  • 智能的语义理解:根据属性名称自动推断合适的编辑器组件(颜色选择器、数字输入框等)
  • 结构化输出:生成的JSON格式规范、完整,直接可用

实际效果展示

设想我们有一个名为CustomButton的Vue组件:

<template>
  <button 
    :class="buttonClass" 
    :disabled="disabled"
    @click="handleClick"
  >
    <slot>{{ label }}</slot>
  </button>
</template>

<script setup lang="ts">
import { computed } from 'vue'

interface Props {
  label?: string
  type?: 'primary' | 'secondary' | 'danger'
  size?: 'small' | 'medium' | 'large'
  disabled?: boolean
  loading?: boolean
}

const props = withDefaults(defineProps<Props>(), {
  label: '按钮',
  type: 'primary',
  size: 'medium',
  disabled: false,
  loading: false
})

const emit = defineEmits<{
  click: [event: MouseEvent]
}>()

const handleClick = (event: MouseEvent) => {
  if (!props.disabled && !props.loading) {
    emit('click', event)
  }
}
</script>

通过AI处理后,会生成一个包含以下关键信息的schema:

  • Props分组:label、type、size被分类为“基础属性”,disabled、loading分类为“行为属性”
  • 组件类型:type属性自动配置为下拉选择器,并包含正确的选项
  • 事件映射:click事件被正确转换为onClick处理函数

第二步:添加物料

把上一步得到的json文件保存到TinyEngine项目根目录下的materials/components 文件夹下。

第三步:添加仓库

如果你没有添加过仓库配置,那么你需要在 项目根目录下的materials/packages.json 文件中添加你的仓库信息:

{
      "name": "DCP组件库",
      "package": "@dcp/component-library",
      "version": "0.0.60",
      "script": "http://192.168.0.212:4874/@dcp/component-library@0.0.60/js/web-component.mjs",
      "destructuring": true,
      "npmrc": "@dcp:registry=http://192.168.0.212:4873"
    }

第四步:构建物料

现在你可以直接在终端执行pnpm buildMaterials ,等终端不再有新的输出时,可以ctrl + c 退出脚本。

一切就绪,启动项目验收

至此,你可以pnpm serve:frontend 后访问项目来使用新增的组件了。

问题排查指南

在实际开发过程中,即使按照上述步骤操作,也可能遇到组件未正常显示的情况,这里为您提供了系统化的排查方法。

关键检查点一:组件获取机制

首先检查TinyEngine的组件获取机制是否正常工作。在以下位置添加调试信息:

文件位置: packages/canvas/render/src/material-function/material-getter.ts#L109

export const getComponent = (name) => {
  // 添加调试信息
  console.log(`正在获取组件: ${name}${getNative(name)}`)
  
  const result = Mapper[name] || getNative(name) || getBlock(name) || (isHTMLTag(name) ? name : getBlockComponent(name))
  
  console.log(`获取结果:`, result)
  return result
}

ℹ️ 排查要点:对于引入的组件,getNative(name)应该返回非空值。如果返回undefined,说明组件没有被正确注册。

关键检查点二:动态导入机制

如果上一步检查发现问题,接下来排查动态导入机制。在以下位置添加调试代码:

文件位置: packages/canvas/common/src/utils.ts#L100

const dynamicImportComponentLib = async ({ pkg, script }: DynamicImportParams): Promise<any> => {
  console.log(`开始导入组件库: ${pkg}`)
  
  if (window.TinyComponentLibs[pkg]) {
    console.log(`组件库已存在缓存中: ${pkg}`)
    return window.TinyComponentLibs[pkg]
  }

  if (!script) {
    console.warn(`组件库 ${pkg} 缺少 script 配置`)
    return {}
  }

  const href = window.parent.location.href || location.href
  const scriptUrl = script.startsWith('.') ? new URL(script, href).href : script
  
  console.log(`动态导入组件库脚本: ${scriptUrl}`)

  if (!window.TinyComponentLibs[pkg]) {
    try {
      const modules = await import(/* @vite-ignore */ scriptUrl)
      console.log(`组件库导入成功:`, modules)
      window.TinyComponentLibs[pkg] = modules
    } catch (error) {
      console.error(`组件库导入失败: ${pkg}`, error)
      return {}
    }
  }

  return window.TinyComponentLibs[pkg]
}

常见问题及解决方案

📌 最常见问题:组件未正确导出

在我的实际经验中,这个问题出现频率最高。很多时候我们在组件库中开发了新组件,但忘记在入口文件中导出它。

解决方案

  1. 检查组件库的index.tsindex.js文件
  2. 确认目标组件已经被正确导出:
    export { default as YourComponent } from './YourComponent.vue'
    

📌 脚本路径错误

检查packages.json中的script字段是否正确。常见错误包括:

  • 版本号不匹配
  • 域名或端口错误
  • 文件路径错误

通过以上系统化的排查步骤,绝大多数问题都能够得到快速解决。


如果您对AI开发感兴趣,欢迎关注我的公众号:观默视界

在这里,我会分享更多关于AI技术在实际开发中的实战经验和最新趋势。

关于OpenTiny

欢迎加入 OpenTiny 开源社区。添加微信小助手:opentiny-official 一起参与交流前端技术~

OpenTiny 官网opentiny.design
OpenTiny 代码仓库github.com/opentiny
TinyVue 源码github.com/opentiny/ti…
TinyEngine 源码: github.com/opentiny/ti…
欢迎进入代码仓库 Star🌟TinyEngine、TinyVue、TinyNG、TinyCLI、TinyEditor~
如果你也想要共建,可以进入代码仓库,找到 good first issue标签,一起参与开源贡献~

❌
❌