Skip to content

Components 迁移指南

这页专门说明 @qxs-bns/components 从旧的 Vue 组件接入方式,切到当前跨框架 Web Components 方案后,业务页面需要重点检查什么。

先看结论

  • 组件现在以 Custom Element 方式提供,不再以 Vue 组件注册名为中心
  • 宿主负责业务状态、列表编排、分页和提交数据,组件负责局部渲染、编辑、校验和导出
  • Vue 里传对象、数组、函数、布尔值时,优先使用 .prop
  • 事件统一按 CustomEvent 处理,数据从 event.detail 读取
  • 样式覆盖优先使用属性、CSS 变量和 ::part(...)

升级前先检查

  • 页面里是否还在依赖旧的 Vue 全局注册组件名
  • 组件入参里是否有对象、数组、函数、布尔值
  • 业务层是否把列表、分页、标签、结果项弹窗这类状态塞给组件内部处理
  • 业务代码里是否直接读取 Vue 事件参数,而不是 CustomEvent.detail
  • 样式是否依赖深入组件内部 DOM 结构

最常见的迁移差异

0. components-v2AnswerContainer 已经有迁移入口

如果你的页面原来依赖的是:

ts
import { AnswerContainer } from '@qxs-bns/components-v2'

现在优先迁到:

ts
import '@qxs-bns/components/answer-container'
html
<qxs-answer-container></qxs-answer-container>

qxs-answer-container 的目标不是复刻旧 Vue 2 DOM,而是先保住旧答题页最依赖的运行时合同:

  • 继续接收旧 list 数据
  • 继续按 examTypeEnum 分发题型
  • 继续支持 themeName
  • 继续支持 disabledisShowCorrectbeforeChange
  • 继续暴露 onSubmit()reset()addTitleNumber()

对应文档见 AnswerContainer。 如果你只是想快速替换旧页面,直接看 AnswerContainer 迁移速查

1. 组件注册方式变了

旧思路通常是:

ts
import { QxsDataChart } from '@qxs-bns/components'

app.component('QxsDataChart', QxsDataChart)

现在推荐直接引入组件入口,然后使用 Custom Element 标签:

ts
import '@qxs-bns/components/data-chart'
html
<qxs-data-chart></qxs-data-chart>

2. Vue 里复杂值优先用 .prop

字符串属性可以直接写;对象、数组、函数、布尔值建议显式走实例属性。

vue
<qxs-data-chart :data.prop="chartData" />
<qxs-image-upload :limit.prop="3" :file-list.prop="files" />
<qxs-blocksuite-editor :upload-image.prop="uploadImage" :readonly.prop="true" />

如果你写成 readonly="false" 这类字符串属性,Web Component 仍然可能把它识别成真值属性。

3. 事件要从 detail 里取值

vue
<script setup lang="ts">
function handleChange(event: CustomEvent) {
  console.log(event.detail)
}
</script>

<template>
  <qxs-file-upload @upload-success="handleChange" />
</template>

如果你的旧页面习惯直接拿 Vue 组件回调参数,需要统一改成读取 CustomEvent.detail

4. 样式覆盖方式要收口

优先级建议是:

  1. 组件属性
  2. CSS 变量
  3. ::part(...)

不要再假设可以稳定依赖组件内部 DOM 结构或类名层级。

组件维度的迁移重点

组件迁移时重点关注
AnswerContainer原来的 components-v2 答题容器优先迁到 qxs-answer-container,保留旧 list / onSubmit / reset 心智
AnswerContainer 迁移速查一页看完 list.prop / beforeChange.prop / event.detail / ref.onSubmit() 这些最常见迁移点
题目组件宿主自己维护题目数组和提交态数据,不再依赖内建列表容器
富文本编辑器事件按 CustomEvent 取值;图片上传、自定义转换函数建议走 .prop
QxsIcon统一走字符串型图标来源,不再按 Vue 图标组件心智接入
FixedActionBar以插槽承载按钮内容,样式覆盖优先看 ::part(actionbar)
FileUpload上传结果从 upload-success / event.detail 读取
ImageUploadfile-list、限制项和回填数据建议走实例属性
PhotoCropToolFile、裁剪结果、回调函数一律按实例属性透传
DataChart图表数据、配置对象和地图地址建议走 .prop

推荐迁移顺序

  1. 先把页面入口改成直接引入 @qxs-bns/components 或子入口
  2. 如果是旧答题页,优先先把 components-v2/AnswerContainer 切到 qxs-answer-container
  3. 再把页面上的标签替换成 Custom Element 名称
  4. 然后逐个把复杂 props 改成 .prop
  5. 最后统一收口事件读取和样式覆盖方式

一页里如何渐进迁移

  • 先选一个边界清晰的组件替换,例如 qxs-iconqxs-fixed-action-bar
  • 再迁上传、图表、编辑器这类有复杂 props / events 的组件
  • 如果是旧答题页,不必一步拆成单题组件;先落 qxs-answer-container,再慢慢下沉到单题组件

components-v2/AnswerContainer 迁移清单

旧写法

vue
<script setup>
import { AnswerContainer } from '@qxs-bns/components-v2'

const answerRef = ref(null)
</script>

<template>
  <AnswerContainer
    ref="answerRef"
    :list="list"
    :is-show-correct="isShowCorrect"
    :theme-name="themeName"
    :before-change="beforeChange"
  />
</template>

新写法

vue
<script setup lang="ts">
import { ref } from 'vue'
import '@qxs-bns/components/answer-container'

const answerRef = ref<any>(null)
</script>

<template>
  <qxs-answer-container
    ref="answerRef"
    :list.prop="list"
    :is-show-correct.prop="isShowCorrect"
    :theme-name="themeName"
    :before-change.prop="beforeChange"
  />
</template>

迁移时优先保留什么

  • 保留原来的 list
  • 保留 themeName
  • 保留 disabled
  • 保留 isShowCorrect
  • 保留 beforeChange
  • 保留 ref.onSubmit() / ref.reset()

迁移后先不要假设这些还完全一样

  • 不保证旧 Vue 2 slot 结构还能原样使用
  • 不保证旧 DOM 层级和类名还能被深度样式覆盖
  • 不保证和旧页面逐像素一致

更稳的迁移策略是:

  1. 先替换成 qxs-answer-container
  2. 先确认 onSubmit()reset() 和旧 list 都能跑
  3. 再补主题细节和宿主样式
  4. 最后如果需要,再继续往单题组件拆

相关文档

Components 迁移指南 has loaded