ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Quasar Framework Tabs 组件实战指南:QTabs / QTab / QRouteTab 全解析

Quasar Framework Tabs 组件实战指南:QTabs / QTab / QRouteTab 全解析 前端UI组件跨平台【免费下载链接】quasarQuasar Framework - Build high-performance VueJS user interfaces in record time项目地址https://gitcode.com/gh_mirrors/qu/quasar点击查看免费下载导读Tabs选项卡是 Web 界面中一种经典的省空间交互模式在有限的窗口区域内通过一排可切换的页签在多个视图之间导航避免一次性堆叠过多信息。本指南以 Quasar Framework 官方文档 docs/src/pages/vue-components/tabs.md 为骨架完整讲解 QTabs、QTab、QRouteTab 三个组件的核心 API、布局与样式定制、无障碍与键盘导航、滚动箭头机制以及如何通过 QRouteTab 与 Vue Router 深度集成。读完本文你将掌握从基础用法、指示器动画、动态增删页签到路由联动匹配、拦截导航等完整实战能力。一、认识三个组件QTabs / QTab / QRouteTabTabs 系列由三个分工明确、层级清晰的组件组成组件职责QTabs页签容器Tab list负责管理选中状态v-model、滚动、箭头、对齐方式、指示器样式并向子级注入共享状态QTab单个页签Tab负责渲染图标/标签/角标/指示器点击后通过 QTabs 更新选中值QRouteTab继承 QTab 全部能力额外绑定 Vue Router 的router-link行为根据当前路由自动激活点击时触发路由跳转三者最常见的组合场景是放入 Layout 的 header / footer 中作为全局导航参见 Layouts 文档 与 Header Footer 文档 中的 Tabs 示例。同时QTabPanels负责承载面板内容本身的组件是 QTabs 的天然搭档——但注意QTabPanels 可以独立使用并不依赖 QTabs 的存在。在源码层面三者位于 ui/src/components/tabs/ 目录QTabs.js 负责容器逻辑QTab.js 是一个极薄的封装仅将公共逻辑 use-tab.js 的渲染结果输出为div而 QRouteTab.js 则通过组合useRouterLink与useTab两个 composable 实现路由与页签的融合。所有 QTab/QRouteTab 通过 Vue 的provide/inject机制tabsKey注册到最近的 QTabs 实例中use-tab.js中甚至有这样的保护逻辑当 QTab 找不到父级 QTabs 时会在控制台输出QTab/QRouteTab component needs to be child of QTabs错误。二、基础用法一个最基础的 QTabs QTab 组合如下参见示例 docs/src/examples/QTabs/Basic.vuetemplate q-tabs v-modeltab classtext-teal q-tab namemails iconmail labelMails / q-tab namealarms iconalarm labelAlarms / q-tab namemovies iconmovie labelMovies / /q-tabs /template script setup import { ref } from vue const tab ref(mails) /script要点说明name是页签的唯一标识类型为Number | String。源码 use-tab.js 中它的默认值是自动生成的t_${id}形式但实践中强烈建议显式指定以便与 v-model 值对应。v-model的值与 QTab 的name一一对应类型同为Number | String见 QTabs.js 的modelValueprop。icon与label可同时使用默认图标在上、文字在下形成满宽布局也可只用一个搭配inline-label时图标与文字会横向排成一行。默认情况下标签文本会被转成大写Material Design 风格no-caps可以禁用这一行为。常用样式变体官方示例还展示了多种便捷变体全部依赖 QTabs 暴露的 props纯图标模式q-tab namemails iconmail /inline-label图文同行q-tabs v-modeltab inline-label ...no-caps保留原始大小写q-tabs v-modeltab no-caps ...背景与文字着色直接复用 Quasar 的辅助类如bg-purple text-white shadow-2。三、滚动箭头机制outside / inside / mobile-arrowsQTabs 的容器宽度不足时页签会自动变为可横向滚动TIPS来自官方文档QTabs 在内容宽度超过容器宽度时可以水平滚动调整浏览器窗口大小即可看到效果桌面端两侧会出现可点击的箭头chevron同时页签支持沿其轴向的滚动手势例如水平触控板滑动或鼠标滚轮倾斜移动端可以直接用手指平移页签如果想在移动端强制显示箭头使用mobile-arrowsprop。对应到实现QTabs.js 中的updateContainer通过 QResizeObserver 监听容器尺寸并逐个子元素求和计算内容总宽而非依赖scrollWidth来判断是否溢出——注释中解释了这样做是为了规避不同浏览器引擎Blink/Gecko vs WebKit对溢出区域报告的差异以及 justify 模式下亚像素四舍五入带来的幽灵箭头问题。updateArrowsQTabs.js负责根据当前滚动位置切换左右箭头的显隐与淡出态还正确处理了 RTL 模式。按住箭头时animScrollTo以 5ms 间隔持续向目标方向滚动。ArrowsModifiers 示例docs/src/examples/QTabs/ArrowsModifiers.vue演示了三种箭头形态默认箭头覆盖在内容区内侧边缘outside-arrows箭头外置在容器两侧mobile-arrows在移动端也始终显示箭头默认移动端隐藏。四、布局与视觉定制4.1 垂直方向Verticalverticalprop 让 QTabs 变为垂直布局指示器移动到左侧RTL 下为右侧箭头逻辑也切换为上下方向源码getIndicatorClass中vertical ? [left, right] : [top, bottom]QTabs.js。官方示例 docs/src/examples/QTabs/Vertical.vue 将垂直 QTabs 与 QSplitter 结合左侧竖排页签、右侧内容区。4.2 紧凑模式Densedense用于需要节省纵向空间的工具栏等场景渲染更紧凑的页签见 docs/src/examples/QTabs/Dense.vue。4.3 单个页签着色Individual colors可以通过active-color激活态文字色、active-bg-color激活态背景色让激活页签区别于其他页签active-class则可以挂载自定义 CSS 类。官方示例 docs/src/examples/QTabs/IndividualColor.vue 展示了组合用法。从 use-tab.js 的getClasses可以看到激活态会依次拼接q-tab--active、active-class、text-${activeColor}、bg-${activeBgColor}。4.4 水波纹Ripple页签默认带水波纹反馈ripple默认值为trueuse-tab.js。docs/src/examples/QTabs/Ripples.vue 演示了两种定制ripplefalse完全关闭水波纹ripple{ color: xxx }自定义波纹颜色源码中 ripple 还支持keyCodes、early等底层选项空格/回车键也会触发波纹。4.5 自定义指示器Custom indicator底部滑动指示条是 Tabs 的核心视觉元素QTabs 提供了一组 prop 精细控制它见 docs/src/examples/QTabs/CustomIndicator.vueindicator-color指示器颜色narrow-indicator指示器收窄为文字/图标宽度而非整行宽度switch-indicator指示器移到顶部垂直布局下移到左侧indicator-colortransparent配合active-color实现无指示器的纯文字高亮效果。指示器切换时带有一个平滑的滑动动画源码animate函数QTabs.js会读取旧/新页签指示器的位置用translateX/translateY scaleX/scaleY先把新指示器伪装成旧位置再通过transition: transform .25s cubic-bezier(.4, 0, .2, 1)动画过渡到最终位置。4.6 页签通知角标Tab notifications官方文档指出有三种展示通知的方式对应 docs/src/examples/QTabs/Notifying.vueQBadge将 QBadge 放入 QTab 默认插槽中自由定制数字/颜色alert属性红点alert为true时渲染一个小红点也可以传颜色字符串如alertred改变颜色alert-icon属性图标指定图标名alert传颜色值时图标按该颜色着色。对应渲染逻辑见 use-tab.js。4.7 对齐方式Alignment与下拉折叠Dropdownalignprop 决定页签在容器内的分布方式可选值在源码 QTabs.js 中定义为[left, center, right, justify]默认centerjustify页签平均铺满整行left/center/right分别靠左/居中/靠右排列。注意文档中的关键说明QTabs 是响应式的align仅在容器宽度注意不是窗口宽度大于配置的 breakpoint 时才生效当宽度小于 breakpoint 时所有页签会被强制拉伸铺满justify以便在窄屏下充分利用空间。源码中justify.value size Number.parseInt(props.breakpoint, 10)QTabs.js正是这一逻辑breakpoint默认值为600QTabs.js。官方示例 docs/src/examples/QTabs/Alignment.vue 中为了演示效果特意将 breakpoint 关闭。另一个实用技巧来自官方示例 docs/src/examples/QTabs/Dropdown.vue当窗口宽度低于 1024px 时Movies 和 Photos 两个页签会被收进一个 More... 下拉菜单QMenu中实现窄屏下的渐进增强。五、在 QToolbar 中嵌入将 QTabs 放入 QToolbar例如页面顶部工具条时必须指定shrinkprop。文档明确解释了原因默认情况下 QTabs 会尝试撑满所有可用横向空间而作为 QToolbar 的子元素时我们通常不希望它抢占整行。源码中shrink对应col-shrink类QTabs.js即 Flex 布局中的flex-shrink行为。官方示例 docs/src/examples/QTabs/TabsInToolbar.vue 展示了q-tabs v-modeltab inline-label shrink stretch的组合shrink让页签只占所需宽度stretch让页签在垂直方向撑满工具栏高度。六、动态增删页签Tabs 是响应式组件页签可以完全由数据驱动动态渲染。官方示例 docs/src/examples/QTabs/DynamicTabs.vue 展示了核心模式q-tabs v-modeltab inline-label shrink stretch q-tab v-fortab in tabs :keytab.name v-bindtab / /q-tabsconst tabs ref(tabsDefinition.slice(0, 1)) function setTabSelected(tabItem, status) { if (status) { tabs.value.push(tabItem) } else { const index tabs.value.indexOf(tabItem) if (index ! -1) tabs.value.splice(index, 1) } }示例中通过一组复选框控制每个页签的显隐。从源码角度每个 QTab 在onMounted时调用$tabs.registerTab(tabData)、在onBeforeUnmount时调用unregisterTabuse-tab.jsQTabs 维护内部的tabDataList数组并触发recalculateScroll()重算滚动状态QTabs.js因此增删页签后箭头、对齐和滚动位置都会自动修正。七、与 QTabPanels 搭配QTabs 负责选哪个页签QTabPanels 负责展示对应内容两者通过相同的name值联动官方示例 docs/src/examples/QTabs/TabsWithTabpanels.vueq-tabs v-modeltab classtext-teal q-tab namemails iconmail labelMails / q-tab namealarms iconalarm labelAlarms / /q-tabs q-tab-panels v-modeltab animated q-tab-panel namemails邮件内容.../q-tab-panel q-tab-panel namealarms闹钟内容.../q-tab-panel /q-tab-panels再次强调文档中的提示QTabPanels 完全可以独立使用不依赖 QTabs它可以放置在页面任意位置而不必紧挨着 QTabs。更详细的联动说明包括 ARIA 属性如何将页签与面板关联请参见 QTabPanels 的无障碍章节。八、无障碍与键盘导航v2.25自 v2.25 起QTabs 对 WAI-ARIA tabs 模式提供了完善支持且采用的是manual activation手动激活风格ARIA 语义QTabs 根节点渲染roletablist其aria-orientation跟随水平/垂直布局每个 QTab/QRouteTab 渲染roletabaria-selected反映当前选中态禁用时附带aria-disabled见 QTabs.js 与 use-tab.js。键盘导航水平页签用Arrow Left/Arrow Right垂直页签用Arrow Up/Arrow Down两端循环Home/End跳到第一个/最后一个页签Space/Enter激活当前聚焦的页签。单一 Tab 停靠点roving tabindex整个页签列表只有一个 Tab 停靠点——Tab键进入页签列表时焦点落在当前激活页签无激活页签时落在第一个可用页签随后移出列表不会逐个遍历每个页签。方向键移动焦点不会改变选中项。这一逻辑对应源码中的tabStopName计算QTabs.js它遍历已注册页签返回激活页签名或第一个可用页签名tabIndex仅在页签名等于该停靠点时才返回0否则为-1use-tab.js。方向键、Home/End 的处理集中在onKbdNavigateQTabs.js并适配了 RTL 方向反转。可覆写性开发者可以通过阻止页签自身的keydown事件接管按键行为例如keydown.enter.prevent可阻止Enter激活页签——但文档提醒一旦接管方向键就必须自行重新实现其导航逻辑否则页签列表将不再符合上述 ARIA 模式。这是因为 use-tab.js 的onKeydown会先 emit 给外部外部可以preventDefault取消内部处理再执行内置的方向键导航。九、与 Vue Router 集成QRouteTab9.1 基本用法QRouteTab 继承了 QTab 的全部能力同时绑定了router-link的属性和行为既能监听当前应用路由来决定激活态也能在点击时触发路由跳转q-tabs q-route-tab iconmail to/mails exact / q-route-tab iconalarm to/alarms exact / /q-tabs9.2 关于 v-model 的重要警告WARNING官方文档原文要点当 QTabs 与 QRouteTab 混用时不建议再同时使用 v-model虽然技术上仍然可以因为此时激活页签的真值来源是当前路由而非 v-model。每个 QRouteTab 的激活状态由应用路由决定而不是由 v-model 决定因此 v-model 的初始值或直接修改 v-model 都不会改变应用的路由。从源码看QRouteTab.js 通过useRouterLink获取linkIsActive/linkIsExactActive、resolvedLink等路由状态并传入useTab而 QTabs 内部updateActiveRouteQTabs.js在路由变化watch(() proxy.$route.fullPath, ...)QTabs.js时重新计算激活页签。只有当路由匹配到某个 QRouteTab 时才会更新内部currentModel。9.3 QRouteTab 匹配当前路由的规则官方文档给出了完整、精确的匹配规则现完整整理如下。当设置了exact精确匹配时它指向的路由必须被 Vue Router 判定为 exact-active路由完全匹配忽略 hash 与 query若 Vue Router 处于 history 模式必须匹配配置的 hash如有必须匹配配置的 query如有——当前路由 query 中任何多余的参数都会导致该页签不激活若希望容忍多余参数就不要使用exact。当未设置exact宽松匹配时它指向的路由必须被 Vue Router 判定为 active宽松匹配忽略 hash 与 query若 Vue Router 处于 history 模式且配置了 hash则必须完全一致若配置了 query则配置的 query 必须包含于当前路由的 query 中若仍有多个 QRouteTab 同时匹配当前路由例如当前路由为/cars/brands/tesla而存在指向非精确/cars、非精确/cars/brands、非精确/cars/brands/tesla的三个 QRouteTab则最具体匹配路由最多的页签胜出此例中为/cars/brands/tesla若仍有多者匹配则其 query 与当前路由 query最接近配置的 query 存在且当前路由 query 多余参数最少的页签胜出若仍有多者匹配则其解析出的href 更长的页签胜出。另外配置了exact的 QRouteTab 永远优先于宽松匹配非 exact的 QRouteTab。这套规则在源码updateActiveRouteQTabs.js中有逐条对应的实现exact分支要求 hash 相等、query 完全一致queryLen ! currentQueryLen || !hasQueryIncluded(...)即精确相等宽松分支用得分制bestScore { matchedLen, queryDiff, hrefLen }依次比较路由匹配深度、query 差异数、href 长度与文档规则一一对应。9.4 自定义导航拦截点击事件QRouteTab 的click事件处理器会收到两个参数原生事件e和导航函数go。调用e.preventDefault()可以取消默认导航之后再在任意时机调用go()完成跳转——这为实现延迟跳转、条件拦截、重定向等自定义导航场景提供了抓手文档提示更完整的click说明见页面顶部的 QRouteTab API 卡片。官方文档给出的完整示例可直接复制运行template q-tabs no-caps classbg-orange text-white shadow-2 q-route-tab :to{ query: { tab: 1 } } exact replace labelActivate in 2s clicknavDelay / q-route-tab :to{ query: { tab: 2 } } exact replace labelDo nothing clicknavCancel / q-route-tab :to{ query: { tab: 3 } } exact replace labelNavigate to the second tab clicknavRedirect / q-route-tab :to{ query: { tab: 4 } } exact replace labelNavigate immediately clicknavPass / /q-tabs /template script setup function navDelay(e, go) { e.preventDefault() // 取消默认导航 setTimeout(() { go() // 2 秒后再执行导航 }, 2000) } function navCancel(e) { e.preventDefault() // 完全取消导航 } function navRedirect(e, go) { e.preventDefault() // 取消默认导航 // 在任意方便的时刻调用 go({ to: { query: { tab: 2, noScroll: true } } // replace: boolean; 默认取页签自身配置 // returnRouterError: boolean; 默认 false }) .then(vueRouterResult { /* 导航成功后的处理 */ }) .catch(vueRouterError { /* 除非 returnRouterError true否则不会走到这里 */ }) } function navPass() {} /scriptgo()支持的选项选项含义默认值to重定向的目标路由可传对象或字符串页签自身配置的toreplace是否使用replace导航不产生历史记录页签自身配置returnRouterError是否将导航错误以 Promise reject 形式返回给调用方false对应源码 use-tab.js 中的go实现它内部调用routeData.navigateToRouterLink并通过avoidRouteWatcher一个临时 uid让 QTabs 的路由监听器忽略这次由页签自己触发的跳转避免与内部状态互相干扰只有当导航无硬错误hard error、且软错误只是 Avoided redundant navigation重复导航到同一路由时才会把该页签标记为激活。9.5 UMD 版本的注意事项WARNING官方文档原文要点如果你使用 UMD 版本且没有同时安装 Vue RouterQRouteTab 将无法工作。这是因为 QRouteTab 依赖useRouterLink及proxy.$route提供路由能力源码 QRouteTab.js 与 QTabs.js 中均有对$route的判空/依赖逻辑。十、关键 Props 速查表综合官方文档、QTabs.js 与 use-tab.js 的源码定义整理核心 props 如下QTabs容器Prop类型默认值说明modelValueNumber/String-当前激活页签的 namealignStringcenterleft/center/right/justify容器宽度 breakpoint 时生效breakpointNumber/String600低于该宽度时页签强制铺满verticalBooleanfalse垂直布局shrinkBooleanfalse不撑满可用宽度如放入 QToolbar 时stretchBooleanfalse垂直方向撑满父容器高度active-class/active-color/active-bg-colorString-激活页签的类/文字色/背景色indicator-colorString-指示器颜色left-icon/right-iconString图标集默认值自定义左右箭头图标outside-arrowsBooleanfalse箭头外置mobile-arrowsBooleanfalse移动端也显示箭头switch-indicatorBooleanfalse指示器移到顶部垂直布局移到左侧narrow-indicatorBooleanfalse指示器收窄inline-labelBooleanfalse图标与文字同行no-capsBooleanfalse保留标签原始大小写denseBooleanfalse紧凑模式content-classString-附加到内容区的类QTab / QRouteTab页签定义于 use-tab.jsProp类型默认值说明nameNumber/String自动生成t_${id}页签唯一标识iconString-图标名labelNumber/String-标签文本alertBoolean/String-通知红点传颜色字符串可着色alert-iconString-通知图标no-capsBooleanfalse单页签禁用大写转换disableBooleanfalse禁用页签tabindexString/Number0自定义 Tab 顺序content-classString-附加到页签内容的类rippleBoolean/Objecttrue水波纹开关/配置QRouteTab 独有继承自 router-linkto、exact、replace、active-class、active-href等全部 Vue Router 链接属性由 use-router-link 提供。十一、延伸阅读QTabPanels 组件文档与 Tabs 配套的内容面板组件QButtonToggle 组件文档另一种互斥选项形态的组件QIcon 组件文档 与 QBadge 组件文档页签中图标与角标的底层组件组件实现源码QTabs.js、QTab.js、QRouteTab.js、use-tab.js样式定义QTabs.sass完整可运行示例全部位于 docs/src/examples/QTabs/ 目录包括 Basic、Vertical、Dense、CustomIndicator、Notifying、Alignment、Dropdown、DynamicTabs、TabsWithTabpanels 等 13 个示例文件组件测试用例QTabs.test.js、QTab.test.js、QRouteTab.test.js 与 use-tab.test.js 验证了上述大部分交互行为含无障碍键盘导航与路由匹配逻辑。赞分享前端UI组件跨平台【免费下载链接】quasarQuasar Framework - Build high-performance VueJS user interfaces in record time项目地址https://gitcode.com/gh_mirrors/qu/quasar点击查看免费下载相关推荐Quasar Framework QCheckbox 组件完全指南状态模型、Toggle 顺序与无障碍实现Quasar Framework QCheckbox 组件完全指南状态模型、Toggle 顺序与无障碍实现 QCheckbox 是 Quasar Framew前端UI组件跨平台Quasar Framework QBreadcrumbs 面包屑组件完全指南导航、路由与无障碍Quasar Framework QBreadcrumbs 面包屑组件完全指南导航、路由与无障碍 QBreadcrumbs 是 Quasar Framewor前端UI组件跨平台Quasar Framework 的 Vite 插件quasar/vite-plugin完全指南安装、配置与源码级原理解析Quasar Framework 的 Vite 插件quasar/vite plugin完全指南安装、配置与源码级原理解析 本文以仓库 vite plu前端UI组件跨平台创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表