@melt-js/demo-vue2-ele
v2026.11.9-1
Published
Vue 2 + Element UI 的 hel 宿主(消费方)示例:`preFetchLib` 从 unpkg 加载 [`@melt-js/comps-vue2-ele`](../comps-vue2-ele),页面里同时直接复用 `tpl-vue2-admin-ele` 的本地源码,并用 `preFetchLib` 演示 [`@melt-js/libs-utils`](../libs-utils) / [`@melt-js/libs-lodash`](../libs-lodash) 两个远程库的方法。
Readme
@melt-js/demo-vue2-ele
Vue 2 + Element UI 的 hel 宿主(消费方)示例:preFetchLib 从 unpkg 加载 @melt-js/comps-vue2-ele,页面里同时直接复用 tpl-vue2-admin-ele 的本地源码,并用 preFetchLib 演示 @melt-js/libs-utils / @melt-js/libs-lodash 两个远程库的方法。
页面使用 vue-router(hash 模式) 把示例拆成十九个可切换的页面,顶部导航栏同时显示当前示例的简介,示例区右上角有全屏按钮(只放大当前示例的组件预览区,基于 vue-fullscreen 的 pageOnly + teleport 模式)。每页保留原有的多个示例,并在末尾追加一个 LevaPlayground 属性面板块(左侧组件 + 右侧属性面板);rocket-render 的几个表单 / 表格示例来自第三方全局插件,没有 workspace schema,保持原样。
| 项 | 值 |
| --- | --- |
| npm 包名 | @melt-js/demo-vue2-ele |
| unpkg 入口 | https://unpkg.com/@melt-js/demo-vue2-ele/dist/index.html |
| 端口 | 30010 |
| 消费的远程组件 | comps-vue2-ele(https://unpkg.com/@melt-js/comps-vue2-ele/hel_dist/hel-meta.json) |
| 消费的远程库 | libs-utils、libs-lodash(线上同样指向 unpkg 的 hel-meta.json) |
| 路由 | [email protected],hash 模式 |
| 全屏 | [email protected](legacy),pageOnly + teleport(不调用浏览器原生全屏) |
示例路由
| 路由 | 导航文案 | 内容 |
| --- | --- | --- |
| #/ | 简介 | demo 概览:远程依赖、端口、远端地址与示例入口 |
| #/remote-comp | 远程组件 | comps-vue2-ele 的 App(内部再依赖 HelloWorld),红色边框区域内渲染 |
| #/ranking | 排行榜 | comps-vue2-ele 的 TierRanking 排行榜:拖拽排序、上传图片、评级编辑、IndexedDB 持久化、导出图片 |
| #/tc-clamp | TcClamp | comps-vue2-ele 的 TcClamp:多行截断、悬停看全文、展开 / 收起、容器自适应 |
| #/tc-block | TcBlock | 面板:title / rightTool 插槽、三种 shadow、最小化与 window / document 全屏 |
| #/tc-more | TcMore | 折叠容器:基础 / 默认展开 / expanded.sync 受控 / title、tool 插槽 |
| #/tc-icon | TcIcon | 图标:glyph 尺寸 / 颜色 / spin,name 类名用法 |
| #/tc-button | TcButton | 按钮:type / size / plain / round / circle / loading / disabled / 点击事件与按钮组 |
| #/tc-select | TcSelect | 下拉:providers、placeholder、禁用、自定义 option 插槽 |
| #/tc-radio | TcRadio | 单选三件套:providers 分段按钮、TcRadio 圆点、单项 / 整组禁用 |
| #/tc-dialog | TcDialog | 弹窗:基础 / 尺寸 / loading / 标题栏拖拽(可关闭)/ beforeClose 防误关 / 遮罩与 Esc / forceEnabled |
| #/tc-loading | TcLoading | 19 个纯 CSS loading、尺寸颜色与自定义文案 |
| #/tc-letter-avatar | TcLetterAvatar | 字母头像:自动缩写、initials、配色、rounded / inline、图片模式 |
| #/rocket-search-form | SearchForm | rocket-render 查询表单:flex / inline 布局、查询 / 重置、change 联动与表单值回显 |
| #/rocket-form | RocketForm | rocket-render 动态表单:栅格、inline 组合、条件显隐 / 字段联动、校验、提交 / 重置 |
| #/rocket-table | RocketTable | rocket-render JSON 表格:标题 / 操作按钮 / 工具条 / 分页 / 可点击列 / 链接 / formatter / 操作列 / 多级表头 |
| #/rocket-desc | RocketDesc | rocket-render 详情描述:带边框 / 垂直布局 / 链式取值 / 插槽 / 一键编辑模式 |
| #/libs | 远程 libs | libs-utils / libs-lodash 的调用结果 |
| #/tpl-comp | tpl 源码 | 通过 workspace 链接直接复用 tpl-vue2-admin-ele 的 Hamburger |
约定:
- hash 模式:demo 的构建产物会通过 unpkg 上的
dist/index.html打开,history 模式在那种静态文件路径下会 404。 - 路由清单在
src/router/index.js,每条路由的meta.title/meta.description同时驱动导航栏 tab 与下方那行简介;新增示例只要加一条路由。 - 全屏按钮只把当前示例标记为
data-demo-preview的组件预览区送进全屏,页面标题、简介、说明与页脚都留在屏幕外;全屏借用vue-fullscreen4.x legacy 的pageOnly + teleport模式:预览区临时挂到 body、用 fixed 铺满视口,退出时还原到页面原位置,不调用浏览器原生 Fullscreen API(iframe 内也可用)。预览区右下角提供「退出全屏」浮层按钮,Esc 也可退出;切换路由时会自动退出并还原。 - 需要全屏的示例在组件预览区外包一层
<demo-preview>;简介页没有预览区,在路由meta里标记fullscreen: false,工具栏不显示全屏按钮。
文件结构
demo-vue2-ele/src
├── App.vue # demo 外壳:导航栏 + 示例舞台(含全屏按钮)+ router-view
├── components/
│ ├── DemoNavbar.vue # 顶部导航栏:示例 tab + 当前示例简介
│ ├── DemoPreview.vue # 组件预览区:全屏目标 + 「退出全屏」浮层按钮
│ └── ScreenfullButton.vue # 示例区全屏按钮(无 element-ui 依赖)
├── configs/app.js # demo 展示信息(名称 / 端口 / 远端地址 / 仓库链接)
├── router/index.js # 示例路由(hash 模式)
├── styles/ # base.css(变量与重置)+ demo-shell.css(外壳样式)+ rocket-demo.css(rocket 示例共用)
├── views/ # Overview / RemoteComp / Ranking / TcClamp … TcLetterAvatar / RocketSearchForm / RocketForm / RocketTable / RocketDesc / Libs / TplComp
├── tc/components.js # 从远端 comps-vue2-ele 解构 Tc* 组件 + missingTc 检查
└── libs/remoteLibs.js # 两个远程 libs 的预加载(Promise 复用)关键流程
src/main.js:bindVueRuntime({ Vue })把宿主 vue 挂到window.Vue,远程组件 external 的vue会复用这一份。src/main.js:preFetchLib('comps-vue2-ele', { custom: { host } })预加载远程组件;hel 组名(comps-vue2-ele)与 scoped npm 包名(@melt-js/comps-vue2-ele)解耦,因此用custom.host指向 unpkg 上的hel_dist/hel-meta.json。host按process.env.NODE_ENV分支:生产走 unpkg,开发走http://localhost:20010。src/main.js+src/libs/remoteLibs.js:入口处和远程组件一起并行预加载两个远程库(loadRemoteLibs()内部是Promise.all+preFetchLib,重复调用复用同一个 Promise)。页面里直接调用它们的方法展示结果:libs-utils:num.canBeNum/num.random、regs.en/regs.enSnake、myMod.sayHelloToHellibs-lodash:chunk/uniq/camelCase/orderBy、myUtils.regs.enOrNum、VERSION
两个库都不在宿主的
package.json依赖里(lodash 也没有安装),全部来自远程产物。host 同样按环境切换:生产指向 unpkg 的hel-meta.json,开发指向各自 dev server(http://localhost:10010/http://localhost:10020),并用skipFetchHelMeta跳过 dev server 上不存在的hel-meta.json、直接解析index.html里的入口脚本。src/router/index.js:#/libs路由的组件工厂先await loadRemoteLibs()(复用入口预加载的同一个 Promise,通常已 resolve),再动态import示例组件,组件内直接读getRemoteLibs()的已加载结果;其余示例同样按路由懒加载。src/App.vue:导航栏 + 示例舞台;示例舞台持有router-view与全屏按钮,ScreenfullButton的目标是当前页面DemoPreview渲染的[data-demo-preview]。src/views/RemoteCompView.vue/RankingView.vue/Tc*View.vue:渲染远程组件comps.App/comps.TierRanking/ 各Tc*组件(组件从src/tc/components.js解构;静态导入只拿到 hel-lib-proxy 的空壳代理,真正的组件代码由入口的preFetchLib载入)。
排行榜远程组件(TierRanking)
- 组件源码在
comps-vue2-ele/src/components/TierRanking,由src/components/index.js与libProperties一起导出,宿主只需preFetchLib后挂载,不打包它的代码与样式。 - 组件能力:拖拽排序 / 跨评级拖动 / 拖到删除区删除、上传图片(自动压缩)、评级改名 / 改色 / 增删、显示图片名、固定评级高度、导出图片(按需加载 html2canvas)、IndexedDB 持久化(
persist/storageKey可关可换)。 - 本地联调:
pnpm comps:dev(20010)的产物直接可用,打开 http://localhost:30010/#/ranking。 - 线上:远端
hel-meta.json会同时下发排行榜所在的 chunk(webpack 把组件拆成了独立 chunk),因此生产构建(远端走 unpkg)同样能渲染#/ranking;只有远端版本早于排行榜组件时,页面才会显示「远端产物没有导出 TierRanking」的提示。 - 排行榜状态存在 IndexedDB(库名
tier-ranking-db,storageKey=demo-vue2-ele-ranking),用组件自带的「重置排行榜」即可恢复默认评级。
文本截断远程组件(TcClamp)
- 组件源码在
comps-vue2-ele/src/components/TcClamp,提取自 think-vuele 的packages/clamp(其核心同 Justineo/vue-clamp),由src/components/index.js与libProperties一起导出。 - 能力:
max-lines/max-height截断、autoresize容器自适应、ellipsis自定义省略号、use-mode="expand"展开 / 收起、auto-tip悬停看全文、expanded.sync受控展开,以及before/after作用域插槽。 - 适配说明:
comps-vue2-ele不依赖 element-ui,因此原实现的el-tooltip换成内置 tooltip(深色气泡 + 箭头,placement/tip-width可配),tc-button换成原生button,resize-detector 换成ResizeObserver(不再支持 IE11)。 - 本地联调:
pnpm comps:dev(20010)的产物直接可用,打开 http://localhost:30010/#/tc-clamp;远端版本较旧没导出TcClamp时,页面会显示提示而不是报错。
Tc 组件库(每个组件一个 tab)
- 组件源码在
comps-vue2-ele/src/components,统一用Tc前缀导出(TcBlock、TcButton…),模板里写<tc-block>、<tc-button>。 - 全部沿用
TcClamp的思路:不引入 element-ui。原来的el-button/el-select/el-radio-group/el-dialog/el-collapse等换成原生实现;el-icon-*换成内置字符或任意图标类名(TcIcon)。 - 导航栏按组件拆成 10 个 tab,每个 tab 都是该组件的完整演示:
#/tc-clamp:截断行数 / 高度、悬停、展开收起、容器自适应#/tc-block:插槽、shadow、最小化、window / document 全屏#/tc-more:基础、默认展开、expanded.sync、插槽#/tc-icon:尺寸、颜色、spin、name 类名#/tc-button:全部 type / size / 状态 / 点击事件 / 按钮组#/tc-select:providers、placeholder、禁用、自定义 option#/tc-radio:providers 分段按钮、TcRadio、TcRadioButton、禁用#/tc-dialog:基础、尺寸、loading、标题栏拖拽(draggable可关)、beforeClose、遮罩 / Esc、forceEnabled#/tc-loading:19 个动画、尺寸颜色、自定义文案#/tc-letter-avatar:自动缩写、initials、配色、rounded / inline、图片
- 各组件的能力与差异见
comps-vue2-ele/README.md的「导出组件」表,源码头部也记录了与上游 think-vuele 的行为差异。
rocket-render 低代码组件(每个组件一个 tab)
- 依赖:
[email protected]与它依赖的[email protected]都装在本包里(dependencies),不是远程产物;src/main.js先Vue.use(ElementUI, { size: 'small' }),再Vue.use(RocketRender, { size, inline, align, border, stripe, pageSize, emptyText })全局注册,页面里直接写<search-form>/<rocket-form>/<rocket-table>/<rocket-desc>。 - 四个组件各占一个导航 tab:
#/rocket-search-form:SearchForm 的flex/inline两种布局,json数组生成查询项,@handleQuery/@handleReset与change(val, values, model)联动,并把回传的表单值直接打印出来。#/rocket-form:RocketForm 的json.formList,包含span栅格、inline子表单、show: { model, val }条件显隐、change联动、rules校验、input-number/date/checkbox/textarea等控件,以及通过ref调用组件暴露的validate()/handleReset()。#/rocket-table:RocketTable 的json,包含标题、actionList、工具条、复选 / 序号 / 可点击列 / 链接列 / formatter / 操作列(含permission)、分页与多级表头;@handleChange换页、各类事件回显在页面日志里。#/rocket-desc:RocketDesc 的带边框 / 垂直布局、prop: 'user.dept.name'链式取值、formatter、title/extra/ label / value 插槽,以及把json.type设为'edit'的编辑模式(update:values同步)。
- 所有示例都用页面内的本地 mock 数据,不请求接口;
src/styles/rocket-demo.css提供四个页面共用的排版、结果面板与事件日志样式。 - Element UI 的样式与组件在本 demo 内全局可用,因此 rocket 示例之外的页面也可以按需使用
el-button/el-tag等组件。
本地开发
# 终端 1:起远程组件(20010)
pnpm comps:dev
# 终端 2、3:起两个远程库(10010 / 10020,页面上的 libs 演示区需要)
pnpm libs-utils:dev
pnpm libs-lodash:dev
# 终端 4:起宿主(30010)
pnpm demo:dev打开 http://localhost:30010 。libs 的预加载在入口处 Promise.all 里,和远程组件一起完成,所以三个 dev server 都要先起好;缺任意一个都会在控制台打印 loadApp err,页面不会挂载。
构建 / 发布
pnpm demo:build # 产出 dist/
pnpm --filter @melt-js/demo-vue2-ele run publish:stage # build → npm stage 暂存,等待 2FA 审批vue.config.js在生产构建时使用相对publicPath,发布后 unpkg 上的dist/index.html可直接加载同目录资源;hash 路由同样可用。process.env.NODE_ENV由 vue-cli 静态注入,生产包里只会保留 unpkg 的地址;线上从 unpkg 加载 libs 的前提是@melt-js/libs-utils/@melt-js/libs-lodash已发布。files白名单只发布dist/与 README。
下载示例
示例区工具栏(全屏按钮左侧)的「下载示例」会按当前页面下载一份单文件「HTML + CDN」示例:
Vue 与 hel-micro 走 CDN,组件由 preFetchLib 在运行时从 unpkg 拉取,双击即可打开,用于演示 / 推广 hel 的接法。
- 模板:
src/configs/downloadExampleTemplate.js - 拼装:
src/configs/downloadPage.js(替换组件名 / 参数 / 背景,生成hel-micro-<组件名>.html) - 数据:
src/configs/downloadExamples.js(路由 →comps-vue2-ele的组件与参数,新增示例页在这里补一条) - 没有远程组件的页面(简介 / libs / 模板源码等)下载
FALLBACK_EXAMPLE
