稳定性大幅升级!TinyVue 3.28 核心修复清单,一文看懂升不升!
本文由体验技术团队TinyVue项目组原创。 我们非常高兴地宣布,最近,TinyVue发布了 v3.28.0🎉, 详细的 Release Notes 请参考:https://github.com/opentiny/tiny-vue/releases/tag/v3.28.0 本次版本共有 11 位贡献者参与开发,其中 IKEYCY / neostfox 是新朋友,欢迎新朋友的加入👏,感谢新老朋友们对 TinyVue 的辛苦付出👏 同时,如果你在使用过程中遇到任何问题,或者有好的建议,欢迎: 你可以更新 @opentiny/vue@3.28.0 进行体验! 如果遇到问题,可以: 查看 Issue - 在 GitHub 上搜索相关问题 下面我们一起来看看都有哪些更新吧! Select 组件的现状和问题: 我们使用 Vite 创建一个空的 Vue 项目,对比下不同情况下构建产物体积情况: 不引入TinyVue组件/只引入Select组件/只引入Tree组件的产物体积对比: 只使用 Area 组件(依赖了Select组件)的产物体积: 可以看到: 本次重构主要达成以下目标: 为了达成以上目标,我们设计并实行了以下重构方案: 重构后组件关系如下图: 使用了 Select 组件的业务,如果想要优化性能,可以: 仅使用base-select与select组件打包对比包体积减少50%以上 为 TinyVue 提供 全局动效配置能力,基于 LESS 与 CSS 变量,实现以下目标: 在 开发者可在组件主题文件中覆盖这些变量: 也可通过在 所有动效存放在 /packages/theme/src/motion/ 目录下,按类型拆分: 1. 淡入淡出 (fade.less) 组件调用示例: 2. 滑动 (slide.less) 组件调用示例: 3. 蚂蚁线 (ants.less,可配置) 组件调用示例: 右键菜单在很多业务场景中都非常常见: 自定义宽度让你可以: 拖拽功能特别适合: ESC 键关闭是用户习惯的操作方式: Drawer 组件支持多种关闭方式: 这个功能特别适合: guide 这个优化让你可以: TinyVue v3.28.0 版本的发布,实现了多项重要升级:对选择器组件家族进行了彻底重构,解耦了 Tree / Grid 等重型功能,显著降低了单个组件的体积;新增了全局主题动画配置,让动画效果可通过 CSS 变量随意定制;引入了懒加载、右键菜单、宽度自定义、弹窗拖拽、ESC 关闭等实用功能,进一步提升了开发体验和用户交互;同时修复了 65+ 个 Bug,整体稳定性大幅提升。通过这些改进,TinyVue 不仅在性能上实现了突破,也为开发者提供了更灵活、可维护的组件库,期待在未来的项目中为你带来更高效、更优雅的开发体验,让我们一起,让前端开发变得更简单、更高效! 欢迎加入 OpenTiny 开源社区。添加微信小助手:opentiny-official 一起参与交流前端技术~ 欢迎进入代码仓库 Star🌟TinyVue、TinyEngine、TinyPro、TinyNG、TinyCLI、TinyEditor一、前言
这个版本带来了:二、升级指南
# 安装最新版本
npm install @opentiny/vue@3.28.0
# 或使用 yarn
yarn add @opentiny/vue@3.28.0
提交 Issue - 如果问题未解决,提交新的 Issue三、特性介绍
选择器组件"家族重组"
为什么需要重构?
产物体积(css+js, 单位kB) gzip之后的产物体积(单位kB) 不引入TinyVue组件 56 23 只引入Select组件 1777 424 只引入Tree组件 789 190 只引入Grid组件 1217 302 只引入Button 310 91 只引入Area组件(依赖Select) 1783 425 

重构目标
重构方案

业务性能优化
tiny-select 为 tiny-base-select 来实现性能优化tiny-select 为 tiny-tree-select 来实现性能优化tiny-select 为 tiny-grid-select 来实现性能优化场景示例

新增功能:懒加载支持
tree-select 现在支持懒加载,想象一下,一个包含 10,000 个节点的树形选择器,以前需要一次性加载所有数据,现在可以按需加载,性能提升不是一点点!懒加载的使用场景
主题动画:一键定制,随心所欲
全局动画配置
@keyframes。全局变量定义
/packages/theme/src/base/vars.less 中统一定义动效变量::root {
/* 蚂蚁线相关配置 */
--tv-motion-ants-shift: 8px;
--tv-motion-ants-speed: 0.8s;
/* 其他动效参数... */
}.copyed-borders {
--tv-motion-ants-shift: 12px;
--tv-motion-ants-speed: 1.2s;
}/packages/theme/src/base/ 下创建 motion-theme.less 来切换全局动效风格::root {
--tv-motion-ants-shift: 12px;
--tv-motion-ants-speed: 1.2s;
}动效分类与目录结构
motion/
├─ fade.less // 淡入淡出
├─ slide.less // 滑动
├─ zoom.less // 缩放
├─ rotate.less // 旋转
├─ bounce.less // 弹跳
├─ scroll.less // 滚动
├─ stroke.less // 描边
├─ shine.less // 闪烁
├─ ants.less // 蚂蚁线
├─ arrow.less // 箭头
├─ tab.less // Tab 切换
├─ progress.less // 进度条
└─ index.less // 统一引入动效示例
@keyframes fade-in {
0% { opacity: 0; }
100% { opacity: 1; }
}
@keyframes fade-out {
0% { opacity: 1; }
100% { opacity: 0; }
}.@{fade-prefix-cls} {
&-enter-active {
animation: var(--tv-motion-fade-speed) fade-in ease-out both;
}
&-leave-active {
animation: var(--tv-motion-fade-speed) fade-out ease-in both;
}
}
@keyframes slide-left-in {
0% { opacity: 0; transform: translateX(var(--tv-motion-slide-offset-left)); }
50% { opacity: var(--tv-motion-slide-opacity-mid); transform: translateX(var(--tv-motion-slide-offset-left-mid)); }
100% { opacity: 1; transform: translateX(0%); }
}
@keyframes slide-left-out {
0% { opacity: 1; transform: translateX(0%); }
50% { opacity: var(--tv-motion-slide-opacity-mid); transform: translateX(var(--tv-motion-slide-offset-left-mid)); }
100% { opacity: 0; transform: translateX(var(--tv-motion-slide-offset-left)); }
}.drawer-slide-left-enter-active {
animation: slide-left-in var(--tv-motion-slide-speed) linear;
}
.drawer-slide-left-leave-active {
animation: slide-left-out var(--tv-motion-slide-speed) linear;
}
@keyframes ants-x {
0% { background-position: 0 0; }
100% { background-position: var(--tv-motion-ants-shift, 8px) 0; }
}
@keyframes ants-x-rev {
0% { background-position: 0 0; }
100% { background-position: calc(-1 * var(--tv-motion-ants-shift, 8px)) 0; }
}.@{grid-prefix-cls}-copyed-borders {
--tv-motion-ants-shift: 13px;
.@{grid-prefix-cls}-border-top {
animation: ants-x var(--tv-motion-ants-speed) linear infinite;
}
.@{grid-prefix-cls}-border-right {
animation: ants-y var(--tv-motion-ants-speed) linear infinite;
}
.@{grid-prefix-cls}-border-bottom {
animation: ants-x-rev var(--tv-motion-ants-speed) linear infinite;
}
.@{grid-prefix-cls}-border-left {
animation: ants-y-rev var(--tv-motion-ants-speed) linear infinite;
}
}
组件集成方式
所有 @keyframes 在 transition.less 与 motion/* 中集中维护,统一加载。
组件可通过 className 或 animation 调用指定动效。
开发者可通过覆盖 :root 变量调整动效时长、速度等参数。四、其他重要更新
下拉菜单右键支持
dropdown 组件现在支持右键菜单触发了!这对于需要上下文菜单的场景非常有用。
使用场景
支持的触发方式
click - 点击触发(默认)hover - 悬停触发contextmenu - 右键触发(新功能)focus - 聚焦触发Switch 组件宽度自定义
switch 组件现在支持自定义宽度了!不再局限于固定的尺寸。
使用场景
Modal 头部拖拽
modal 组件现在支持设置 headerDragable 属性,让用户可以拖拽弹窗头部来移动弹窗位置。
使用场景
注意事项
Drawer 按 ESC 关闭
drawer 组件现在支持通过按 ESC 键关闭,用户体验更加友好。
使用场景
其他关闭方式
close() 方法Tree Menu 节点点击增强
tree-menu 组件现在支持在文档中点击添加节点,交互更加直观。使用场景
Guide 组件触发条件优化
组件现在支持showStep属性,只有在showStep为true` 时才会触发引导。
使用场景
五、结语
关于OpenTiny
OpenTiny 官网:https://opentiny.design
OpenTiny 代码仓库:https://github.com/opentiny
TinyVue源码:https://github.com/opentiny/tiny-vue
如果你也想要共建,可以进入代码仓库,找到 good first issue标签,一起参与开源贡献~