OpenTiny NEXT 从入门到精通·第 2 篇组件篇——TinyVue 核心组件库深度实战组件库是前端应用的“乐高积木”。TinyVue 作为 OpenTiny 生态的核心 UI 组件库拥有 130 企业级组件覆盖中后台开发的绝大部分场景。但会用组件只是第一步理解其Renderless 无渲染架构、掌握主题定制、学会封装自定义组件才是从普通使用者到进阶开发者的关键一跃。本篇将带你深度实战 TinyVue解锁它的真正威力。在日常开发中你是否遇到过这些问题同一个项目里既要支持 Vue 2又要支持 Vue 3组件库需要维护两套代码API 还不一致想封装一个业务组件但为了适配不同框架Vue / React要写好几套实现组件样式需要根据品牌色动态切换但传统 CSS 方案改起来非常痛苦TinyVue 的Renderless 架构正是为了解决这些问题而生的。它将组件的逻辑、模板和样式三者分离让核心逻辑与框架解耦一套代码可以同时运行在 Vue 2 / Vue 3 / React 等多个框架中。本篇文章将从以下几个方面展开TinyVue 组件库全景概览与特色组件介绍Renderless 无渲染架构深度解析主题定制与样式系统从零封装一个自定义组件含 Vue 2/3 适配一、TinyVue 组件库概览1.1 130 组件的全景介绍TinyVue 的组件按照功能可以分为以下几大类分类组件示例使用场景基础组件Button、Icon、Link、Typography页面基础元素布局组件Grid、Layout、Divider、Space页面结构搭建表单组件Input、Select、Checkbox、Radio、DatePicker、Upload、Form数据录入与校验数据展示Table、Tree、Pagination、Tag、Badge、Card、Carousel数据列表与详情展示反馈组件Modal、Message、Notification、Popconfirm、Progress用户交互反馈导航组件Menu、Tabs、Breadcrumb、Steps、Dropdown页面导航与路由高阶组件Split、IpAddress、CalendarView、Crop、RichText特殊业务场景每个组件都遵循 OpenTiny Design 设计规范保证视觉一致性和交互体验。1.2 高频组件特性速览Table 表格组件支持固定表头、固定列、多级表头内置虚拟滚动轻松处理 10 万 行数据行内编辑、行拖拽排序、列拖拽调整宽度树形表格、可展开行Tree 树形控件支持懒加载、拖拽节点、复选框自定义节点内容、节点过滤异步加载大数据量时自动启用虚拟滚动Select 选择器支持远程搜索、分组、创建新条目虚拟滚动支持上千条选项不卡顿多选、可清空、可禁用选项Form 表单支持表单校验内置多种校验规则可自定义动态表单项、表单联动支持布局模式inline、block1.3 OpenTiny 特色组件详解除了常规组件TinyVue 还提供了一些业界少见的特色组件这些组件来源于华为内部业务的实际需求经过大量生产验证。Split 面板分隔器可拖拽调整左右或上下两个面板大小的组件常用于后台管理系统的左右布局。template tiny-split v-modelsplitSize modehorizontal template #left左侧面板可拖拽调整/template template #right右侧面板/template /tiny-split /template script setup import { ref } from vue import { TinySplit } from opentiny/vue const splitSize ref(0.3) // 左侧占比 30% /scriptIpAddress IP 地址输入框专门用于 IPv4 地址输入的组件自动分隔四段支持键盘快速跳转。tiny-ip-address v-modelip /CalendarView 日历视图比常规的 DatePicker 更强大的日历组件支持月/周/日视图切换可自定义渲染内容如日程安排。tiny-calendar-view v-modelcurrentDate :eventscalendarEvents /Crop 图片裁切提供可视化裁剪框支持固定比例、自由裁剪输出 base64 或 Blob便于上传。tiny-crop :srcimageUrl :aspectRatio16/9 crophandleCrop /二、Renderless 无渲染架构深度解析2.1 组件与框架分离的设计理念传统组件库的代码组织方式通常是“框架 组件逻辑”强耦合的。以 Vue 组件为例模板template、逻辑script、样式style都写在同一个.vue文件中这种结构直接绑定了 Vue 框架。TinyVue 采用的Renderless 架构则将组件拆分为三个独立层┌─────────────────────────────────────┐ │ 框架适配层 │ │ (Vue2 适配器 / Vue3 适配器 / React适配器) │ ├─────────────────────────────────────┤ │ 无渲染逻辑层 (Renderless) │ │ (状态管理、事件处理、生命周期、API) │ ├─────────────────────────────────────┤ │ 样式层 (Theme) │ │ (CSS Variables / 主题变量) │ └─────────────────────────────────────┘逻辑层Renderless纯 TypeScript 实现包含组件的状态、计算属性、方法、生命周期等完全不依赖任何 UI 框架。这部分代码可以跨框架复用。模板层Template框架特定的模板代码负责将逻辑层的数据和事件绑定到 DOM 上。不同框架有不同的模板语法但调用的都是同一套逻辑层 API。样式层StyleCSS 样式使用 CSS Variables 实现主题变量与框架无关。2.2 一套代码同时支持 Vue 2 和 Vue 3——版本适配器如何抹平差异Vue 2 和 Vue 3 在响应式原理、生命周期、API 等方面存在差异。TinyVue 通过版本适配器Version Adapter来抹平这些差异。适配器核心思路将 Vue 2 的 Options API 和 Vue 3 的 Composition API 封装成统一调用接口。逻辑层代码只调用适配器提供的统一方法如useReactive、useMounted不直接依赖 Vue。适配器根据当前 Vue 版本动态选择底层实现。简化示例Button 组件// renderless/button.ts —— 纯逻辑层无框架依赖exportfunctionuseButton(props,{emit}){consthandleClick(event){if(!props.disabled){emit(click,event);}};return{handleClick};}!-- vue3/Button.vue —— Vue 3 模板层 -- template button :classclasses clickhandleClick slot / /button /template script setup import { useButton } from ../renderless/button const props defineProps([disabled]) const emit defineEmits([click]) const { handleClick } useButton(props, { emit }) /script!-- vue2/Button.vue —— Vue 2 模板层 -- template button :classclasses clickhandleClick slot / /button /template script import { useButton } from ../renderless/button export default { props: [disabled], setup(props, { emit }) { return useButton(props, { emit }) } } /script通过这种方式Button 的核心逻辑useButton只写一次Vue 2 和 Vue 3 的模板各自引用同一份逻辑保证了 API 和行为的完全一致。2.3 一套代码同时支持 PC 和移动端——多端同源的技术实现传统组件库往往分 PC 版和移动版如 Ant Design 和 Ant Design Mobile需要维护两套代码。TinyVue 通过响应式断点 适配器实现了多端同源。实现原理组件内部通过useBreakpoint检测当前屏幕宽度返回pc或mobile。模板层根据端类型渲染不同的 DOM 结构和交互模式如 PC 端是弹窗选择器移动端是底部抽屉。样式层通过媒体查询自动适配不同屏幕。示例DatePicker 组件的多端适配PC 端弹出浮层日历面板鼠标交互。移动端底部弹出滚动选择器触摸优化。开发者只需引入同一个组件无需关心端差异TinyVue 会自动适配。三、主题定制与样式系统3.1 基于 CSS Variables 的动态主题系统TinyVue 的主题系统基于CSS Variables自定义属性构建而不是传统的 SCSS 变量。CSS Variables 的一大优势是运行时动态切换无需重新编译。主题变量定义示例/* 亮色主题 */:root{--ti-button-primary-bg:#1890ff;--ti-button-primary-hover-bg:#40a9ff;--ti-button-primary-active-bg:#096dd9;--ti-button-border-radius:4px;}/* 暗色主题 */[data-themedark]{--ti-button-primary-bg:#1f3a5f;--ti-button-primary-hover-bg:#2a4b7a;--ti-button-primary-active-bg:#0f2a4a;}组件样式使用变量.tiny-button--primary{background-color:var(--ti-button-primary-bg);border-radius:var(--ti-button-border-radius);}.tiny-button--primary:hover{background-color:var(--ti-button-primary-hover-bg);}动态切换主题// 切换到暗色主题document.documentElement.setAttribute(data-theme,dark);// 切回亮色主题document.documentElement.removeAttribute(data-theme);3.2 主题生成器与自定义主题包导出TinyVue 提供了在线主题生成器开发者可以可视化调整颜色、圆角、间距等设计 token实时预览效果最后导出自定义主题 CSS 文件在项目中引入即可。自定义主题包导入importopentiny/vue/theme/index.css// 默认主题import./my-custom-theme.css// 自定义主题覆盖3.3 Shadow DOM 样式隔离机制——微前端场景下的天然优势TinyVue 组件可以选择性地启用Shadow DOM封装。启用后组件的样式会被隔离在 shadow root 内部不会影响外部页面也不会被外部样式污染。这对于微前端场景尤为重要主应用和子应用可能使用不同的 UI 库或主题传统 CSS 容易发生样式冲突。而 TinyVue 的 Shadow DOM 方案从根本上解决了这个问题。启用 Shadow DOMtemplate tiny-button shadow-dom隔离样式/tiny-button /template资深提示Shadow DOM 虽然解决了样式冲突但也会带来一些限制如全局弹窗需要挂载到 body。TinyVue 内部已做了处理Modal、Message 等浮层组件会自动挂载到外部保证功能正常。四、组件开发实战——从零封装一个自定义组件下面我们以一个评分组件Rate为例演示如何基于 TinyVue 的 Renderless 架构开发一个支持 Vue 2 和 Vue 3 的跨框架组件。4.1 理解组件 API 规范与设计模式首先定义组件的 Props 和 Events// types.tsexportinterfaceRateProps{value:number;// 当前评分值max?:number;// 最大分数默认5disabled?:boolean;// 是否禁用allowHalf?:boolean;// 是否允许半星}exportinterfaceRateEmits{(e:change,value:number):void;(e:update:value,value:number):void;}4.2 编写组件逻辑层Renderless 核心// renderless/rate.tsimport{ref,computed}from../adapter// 统一适配器exportfunctionuseRate(props:RateProps,{emit}){constcurrentValueref(props.value);constmaxcomputed(()props.max??5);conststarscomputed((){returnArray.from({length:max.value},(_,i)i1);});constgetStarClass(index:number){conststarValueindex1;constisFullcurrentValue.valuestarValue;constisHalfprops.allowHalfcurrentValue.valuestarValue-1currentValue.valuestarValue;return{full:isFull,half:isHalf,active:isFull||isHalf};};consthandleClick(index:number){if(props.disabled)return;constnewValueindex1;currentValue.valuenewValue;emit(update:value,newValue);emit(change,newValue);};consthandleMouseMove(event:MouseEvent,index:number){if(!props.allowHalf||props.disabled)return;constrect(event.targetasHTMLElement).getBoundingClientRect();consthalfevent.clientX-rect.leftrect.width/2;conststarValueindex(half?0.5:1);currentValue.valuestarValue;};return{stars,currentValue,getStarClass,handleClick,handleMouseMove};}4.3 适配 Vue 2 和 Vue 3 的版本适配层Vue 3 模板vue3/Rate.vuetemplate div classtiny-rate :class{ is-disabled: disabled } span v-for(star, index) in stars :keyindex classtiny-rate__star :classgetStarClass(index) clickhandleClick(index) mousemove(e) handleMouseMove(e, index) i classtiny-icon-star/i /span /div /template script setup langts import { useRate } from ../renderless/rate const props defineProps([value, max, disabled, allowHalf]) const emit defineEmits([change, update:value]) const { stars, getStarClass, handleClick, handleMouseMove } useRate(props, { emit }) /script style scoped /* 样式略使用 CSS Variables */ /styleVue 2 模板vue2/Rate.vuetemplate div classtiny-rate :class{ is-disabled: disabled } span v-for(star, index) in stars :keyindex classtiny-rate__star :classgetStarClass(index) clickhandleClick(index) mousemove(e) handleMouseMove(e, index) i classtiny-icon-star/i /span /div /template script import { useRate } from ../renderless/rate export default { props: [value, max, disabled, allowHalf], setup(props, { emit }) { return useRate(props, { emit }) } } /script4.4 组件文档与示例编写组件开发完成后需要编写使用文档和示例方便团队成员使用。TinyVue 的文档基于 Markdown Vue 组件演示示例代码可直接运行。文档示例# Rate 评分组件 用于快速评级操作。 ## 基础用法 vue tiny-rate v-modelscore /半星支持tiny-rate v-modelscore allow-half /禁用状态tiny-rate v-modelscore disabled /APIProps参数说明类型默认值value当前评分number0max最大分数number5disabled是否禁用booleanfalseallowHalf是否允许半星booleanfalse至此一个完整的跨框架自定义组件就开发完成了。整个过程中核心逻辑只编写了一次Vue 2 和 Vue 3 的适配成本极低。 ## 总结 本篇我们深入剖析了 TinyVue 组件库的核心能力 1. **组件全景**130 组件覆盖中后台全场景特色组件Split、IpAddress、CalendarView 等解决特定业务痛点。 2. **Renderless 架构**逻辑、模板、样式三层分离一套代码同时支持 Vue 2 / Vue 3甚至可扩展至 React。 3. **主题系统**基于 CSS Variables 的运行时主题切换支持 Shadow DOM 样式隔离微前端场景天然友好。 4. **组件开发实战**从 API 设计到逻辑层实现再到 Vue 2/3 适配完整演示了跨框架组件的开发流程。 掌握这些内容你不仅能够熟练使用 TinyVue 开发企业级应用还能根据业务需求扩展自定义组件甚至为 OpenTiny 社区贡献代码。 **下篇预告** 《数据篇——表格、表单与图表的高级应用》将聚焦企业级中后台最核心的数据处理场景带你深度掌握 TinyGrid、TinyForm、TinyChart 组件的高阶用法与性能优化技巧敬请期待 **如果觉得本文对你有帮助欢迎点赞、收藏、评论你的支持是我持续创作的动力**