Appearance
Components 迁移指南
这页专门说明 @qxs-bns/components 从旧的 Vue 组件接入方式,切到当前跨框架 Web Components 方案后,业务页面需要重点检查什么。
先看结论
- 组件现在以 Custom Element 方式提供,不再以 Vue 组件注册名为中心
- 宿主负责业务状态、列表编排、分页和提交数据,组件负责局部渲染、编辑、校验和导出
- Vue 里传对象、数组、函数、布尔值时,优先使用
.prop - 事件统一按
CustomEvent处理,数据从event.detail读取 - 样式覆盖优先使用属性、CSS 变量和
::part(...)
升级前先检查
- 页面里是否还在依赖旧的 Vue 全局注册组件名
- 组件入参里是否有对象、数组、函数、布尔值
- 业务层是否把列表、分页、标签、结果项弹窗这类状态塞给组件内部处理
- 业务代码里是否直接读取 Vue 事件参数,而不是
CustomEvent.detail - 样式是否依赖深入组件内部 DOM 结构
最常见的迁移差异
0. components-v2 的 AnswerContainer 已经有迁移入口
如果你的页面原来依赖的是:
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 - 继续支持
disabled、isShowCorrect、beforeChange - 继续暴露
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. 样式覆盖方式要收口
优先级建议是:
- 组件属性
- CSS 变量
::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 读取 |
| ImageUpload | file-list、限制项和回填数据建议走实例属性 |
| PhotoCropTool | File、裁剪结果、回调函数一律按实例属性透传 |
| DataChart | 图表数据、配置对象和地图地址建议走 .prop |
推荐迁移顺序
- 先把页面入口改成直接引入
@qxs-bns/components或子入口 - 如果是旧答题页,优先先把
components-v2/AnswerContainer切到qxs-answer-container - 再把页面上的标签替换成 Custom Element 名称
- 然后逐个把复杂 props 改成
.prop - 最后统一收口事件读取和样式覆盖方式
一页里如何渐进迁移
- 先选一个边界清晰的组件替换,例如
qxs-icon、qxs-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 层级和类名还能被深度样式覆盖
- 不保证和旧页面逐像素一致
更稳的迁移策略是:
- 先替换成
qxs-answer-container - 先确认
onSubmit()、reset()和旧list都能跑 - 再补主题细节和宿主样式
- 最后如果需要,再继续往单题组件拆