Quasar QColor 颜色选择器组件完全指南:从基础用法到无障碍访问
2026/9/20 17:33:57 网站建设 项目流程

Quasar QColor 颜色选择器组件完全指南:从基础用法到无障碍访问

【免费下载链接】quasarQuasar Framework - Build high-performance VueJS user interfaces in record time项目地址: https://gitcode.com/gh_mirrors/qu/quasar

导读:QColor<q-color>)是 Quasar 框架内置的颜色输入组件,用户可在 Spectrum(光谱)、Tune(调校)、Palette(调色板)三种视图间切换,以 HEX/RGB 等格式取色。本文基于 Quasar 官方文档 color-picker.md,结合组件源码 QColor.js、API 定义 QColor.json 及测试用例 QColor.test.js,系统讲解模型绑定、视图配置、自定义调色板、原生表单提交与无障碍访问,帮助你直接落地一个可用、可扩展且对键盘和屏幕阅读器友好的颜色选择器。

组件概述

QColor为 Vue 组件,提供一种输入颜色的方式。它支持四种输出格式:#FF00FF(HEX)、#FF00FFCC(HEXA,带 Alpha 通道)、rgb(0,0,0)rgba(255,0,255,0.8),模型值既可以是带#前缀的十六进制字符串,也可以是rgb()/rgba()函数字符串,使用v-model进行双向绑定。

[!TIP] 若需要在组件之外处理颜色字符串,Quasar 还提供了独立的 Quasar Color Utils,内含rgbToHexrgbToHsvhexToRgbtextToRgbhsvToRgb等转换函数,以及lightenluminositybrightnessblend等处理函数——QColor 内部正是复用了这些工具。

组件内部结构上,QColor 由三部分构成(见 QColor.js):

  • Header:顶部显示当前颜色值与 HEX/RGB(或 HEXA/RGBA)切换标签页,由no-header/no-header-tabs控制;
  • 三个视图 Tab:Spectrum(光谱面板 + 色相滑条)、Tune(数值输入 + 滑条)、Palette(色块矩阵),由default-view与底部视图切换器控制;
  • Footer:底部视图切换标签,由no-footer控制。

基础用法

最基本的用法是直接绑定v-model,QColor 会根据初始值自动识别当前格式(HEX 还是 RGB),并相应地输出同格式的值:

<template> <div class="q-pa-md row items-start q-gutter-md"> <q-color v-model="hex" class="my-picker" /> <q-color v-model="hexa" class="my-picker" /> <q-color v-model="rgb" class="my-picker" /> <q-color v-model="rgba" class="my-picker" /> </div> </template> <script setup> import { ref } from 'vue' const hex = ref('#FF00FF') const hexa = ref('#FF00FFCC') const rgb = ref('rgb(0,0,0)') const rgba = ref('rgba(255,0,255,0.8)') </script> <style lang="sass" scoped> .my-picker max-width: 250px </style>

完整示例见 Basic.vue。从源码看,组件在parseModel(QColor.js)中对模型值做了归一化:将字符串解析为{ h, s, v, r, g, b, a }的内部模型,同时缓存hexrgb两种字符串表达。输出时通过isOutputHex计算属性决定当前该用哪种格式:

const isOutputHex = computed(() => forceHex.value !== null ? forceHex.value : isHex.value )

其中isHex判断模型值是否为空或是否以#开头。这意味着:初始模型是 HEX 字符串,输出就是 HEX;初始是rgb()字符串,输出就是 RGB——格式会跟随初始值自动保持一致。

结合 QInput 使用与校验规则

颜色选择器最常见的落地场景之一,是配合输入框:用户既可以直接打字,也可以点击色滴图标弹出选择器。官方示例 Input.vue 展示了用QPopupProxy实现弹出式取色器:

<template> <div class="q-pa-md"> <div class="q-gutter-md row items-start"> <q-input filled v-model="color" class="my-input"> <template #append> <q-icon name="colorize" class="cursor-pointer"> <q-popup-proxy cover transition-show="scale" transition-hide="scale"> <q-color v-model="color" /> </q-popup-proxy> </q-icon> </template> </q-input> <q-input filled v-model="secondColor" :rules="['anyColor']" hint="With validation" class="my-input" > <template #append> <q-icon name="colorize" class="cursor-pointer"> <q-popup-proxy cover transition-show="scale" transition-hide="scale"> <q-color v-model="secondColor" /> </q-popup-proxy> </q-icon> </template> </q-input> </div> </div> </template> <script setup> import { ref } from 'vue' const color = ref('#FF00FF') const secondColor = ref('#027be3') </script>

QInputrules属性有现成的校验辅助规则,完整列表定义在 patterns.js,与颜色相关的包括:

规则名匹配内容底层正则(节选)
hexColor#RGB/#RRGGBB/^#[0-9a-fA-F]{3}([0-9a-fA-F]{3})?$/
hexaColor#RGBA/#RRGGBBAA/^#[0-9a-fA-F]{4}([0-9a-fA-F]{4})?$/
hexOrHexaColor上述两者/^#([0-9a-fA-F]{3}\|{4}\|{6}\|{8})$/
rgbColorrgb(r,g,b)0–255 的通道值
rgbaColorrgba(r,g,b,a)通道 0–255,alpha 0–1
rgbOrRgbaColor上述两者组合正则
hexOrRgbColorHEX 或 RGB组合正则
hexaOrRgbaColorHEXA 或 RGBA组合正则
anyColor任意一种颜色格式hexOrHexaRE \|\| rgbRE \|\| rgbaRE

用法上既可以直接传字符串规则名(如:rules="['anyColor']"),也可以根据你的自定义需求编写自己的校验函数,参见 QInput 内部校验。这些正则与 QColor 内部解析逻辑保持一致:在parseModel中,组件正是用testPattern.anyColor(...)判断模型值是否为合法颜色,非法值会退化为黑色。

隐藏头部与底部

你可以按需隐藏头部(no-header)、头部内的 HEX/RGB 切换标签(no-header-tabs)或底部视图切换器(no-footer),示例见 NoHeaderFooter.vue:

<q-color v-model="hex" no-header class="my-picker" /> <q-color v-model="hex" no-header-tabs class="my-picker" /> <q-color v-model="hex" no-footer class="my-picker" /> <q-color v-model="hex" no-header no-footer class="my-picker" />

API 定义中(QColor.json)对no-footer的说明是:当你只想用default-view固定某一种视图、不希望用户切换时非常有用。

自定义默认视图

default-view属性可以指定打开时的初始视图,取值'spectrum'(默认)、'tune''palette'三者之一,源码中的校验器为['spectrum', 'tune', 'palette'].includes(v)(QColor.js)。

以下示例固定使用palette视图,同时隐藏头部和底部,最终呈现一个纯色板,用户只需点选即可取色(CustomDefaultView.vue):

<q-badge color="grey-3" text-color="black" class="q-mb-sm">{{ hex }}</q-badge> <q-color v-model="hex" no-header no-footer default-view="palette" class="my-picker" />

自定义调色板

默认调色板是组件内置的一组硬编码颜色(约 120 个 RGB 字符串,从浅到深共 6 阶,定义在 QColor.js 的palette常量中)。通过palette属性可以完全替换 Palette 视图中的色块列表,示例见 CustomPalette.vue:

<q-color v-model="hex" default-view="palette" :palette="[ '#019A9D', '#D9B801', '#E8045A', '#B2028A', '#2A0449', '#019A9D' ]" class="my-picker" />

palette是字符串数组,元素可以是#hexrgb(r,g,b)等任意合法颜色字符串(API 示例:['#019A9D', '#D9B801', 'rgb(23,120,0)', '#B2028A'])。点选色块后,onPalettePick(QColor.js)会解析该颜色并同步更新模型——若被选中的颜色不含 Alpha 通道,则沿用当前模型的 Alpha 值。

Palette 插槽(v2.31+)

palette插槽用于完全替换 Palette 视图中的默认色块,同时保留 Spectrum、Tune 视图与视图切换器。它的作用域提供三个字段(QColor.json 的 slots 定义):

作用域字段类型说明
paletteArray当前调色板颜色列表(palette属性传入的数组;未设置时为内置列表)
select(color)Function将模型设为指定颜色;组件处于disablereadonly状态时调用无效
editableBoolean用户当前能否修改颜色(禁用/只读时为false

因此你可以完全自行决定色块的布局与标签。官方示例 PaletteSlot.vue 用品牌色 + 名称文本做了演示:

<q-color v-model="hex" default-view="palette" :palette="palleteOptions" class="my-picker" > <template #palette="{ palette, select, editable }"> <div class="row q-gutter-sm q-pa-md" role="group" aria-label="Brand colors" > <q-btn v-for="color in palette" :key="color" no-caps :outline="hex !== color" :unelevated="hex === color" :disable="!editable" :aria-pressed="hex === color" @click="select(color)" > <span class="swatch q-mr-sm" :style="{ backgroundColor: color }" /> {{ swatches[color] }} </q-btn> </div> </template> </q-color>

注意:默认色块本身是键盘和屏幕阅读器可访问的(详见下文无障碍章节),自定义插槽内容时,请尽量保持你的实现同样具备无障碍能力

强制暗色模式

dark属性强制 QColor 以暗色主题渲染(Dark.vue),即使应用当前处于亮色模式。它复用了 Quasar 的useDarkcomposable(源码中const isDark = useDark(props, $q),见 QColor.js):

<q-color v-model="hex" dark class="my-picker" /> <q-color v-model="hexa" dark class="my-picker" /> <q-color v-model="rgb" dark class="my-picker" /> <q-color v-model="rgba" dark class="my-picker" />

默认值

当模型尚未设置值时,可以用default-value属性显示一个默认颜色,示例见 DefaultValue.vue:

<q-color v-model="nullModel" default-value="#285de0" style="max-width: 250px" />

从源码看,default-valuemodel-value共同参与内部模型初始化:const model = ref(parseModel(props.modelValue || props.defaultValue))(QColor.js)。也就是说,模型为空(null/undefined/ 空字符串)时会回退到default-value的解析结果;一旦用户取色,update:modelValue事件会携带新值回写父组件。

懒更新(Lazy Model)

默认情况下,拖动光谱面板或滑条会实时触发update:model-value。若希望用户完成选择后才更新(例如用于表单提交、或避免高频渲染开销),可以用change事件代替v-model双向绑定,示例见 LazyModel.vue:

<q-color :model-value="hex" @change="val => { hex = val }" style="max-width: 250px" />

两个事件的语义在 API 定义中有明确区分(QColor.json):

  • update:model-value:模型值变化时实时发出;
  • change:用户完成一次取色操作(结束拖动、松开按键、点击色块等)后发出,是"懒模型"的入口。

源码中updateModel(rgb, change)(QColor.js)是统一出口:始终发出update:modelValue,仅当change为真时才追加change事件。Spectrum 面板的键盘操作也遵循这一约定:按键期间(keydown)只更新内部值与update:modelValue,松开按键(keyup)时才发出change,避免按键连发刷屏(QColor.js)。测试用例也验证了两类事件的独立行为(QColor.test.js)。

禁用与只读

disablereadonly属性控制交互性(DisableReadonly.vue):

<q-color v-model="color" disable class="my-picker" /> <q-color v-model="color" readonly class="my-picker" />
  • disable:完全禁用组件,视觉上变灰,aria-disabled="true"暴露在根元素上;
  • readonly:只读,不可修改颜色,但保留视觉样式;
  • 两者的共同底层是editable计算属性(!props.disable && !props.readonly,见 QColor.js),它同时控制 Palette 插槽作用域中的editable标志;
  • 无障碍层面:只读或禁用时,光谱面板与色块会从 Tab 键顺序中移除(与其滑条行为一致),但光谱面板仍会以aria-readonly/aria-disabled持续播报当前颜色(详见下文)。

原生表单提交

当组件处于一个带actionmethod原生表单中(例如 Quasar 配合 ASP.NET 控制器使用)时,必须给 QColor 指定name属性,否则formData将不会包含该字段。示例见 NativeForm.vue:

<q-form @submit="onSubmit" class="q-gutter-md"> <q-color name="accent_color" v-model="color" style="width: 200px; max-width: 100%" /> <div> <q-btn label="Submit" type="submit" color="primary" /> </div> </q-form>

提交后FormData中即可读取到accent_color = 当前颜色值。其实现机制是useFormInject:组件内部渲染一个type="hidden"的隐藏输入框,值取自model.value[isOutputHex.value ? 'hex' : 'rgb'](QColor.js)——即输出格式同样遵循"跟随初始值"的规则。

强制模型输出格式:format-model

除了跟随初始值自动推断,QColor 还提供format-model属性强制模型输出为指定格式:

效果
'auto'(默认)跟随初始值的格式
'hex'强制输出#RRGGBB
'rgb'强制输出rgb(r,g,b)
'hexa'强制输出#RRGGBBAA
'rgba'强制输出rgba(r,g,b,a)

源码中通过forceHexforceAlpha两个计算属性实现(QColor.js):formatModelhex则强制十六进制输出,含a则强制带 Alpha 通道(hasAlpha控制界面中是否显示 Alpha 滑条与 HEXA/RGBA 标签)。当强制输出带 Alpha 的格式而模型值本身没有 Alpha 时,解析时会自动补上a: 100(QColor.js)。

无障碍访问(v2.25+,Palette 增强 v2.31+)

QColor 的三种视图均支持键盘与屏幕阅读器操作,这是其区别于一般取色组件的重要特性,相关测试覆盖在 QColor.test.js 的无障碍章节。

Spectrum 光谱面板

  • 面板本身是一个role="slider"的滑条,名称来自本地化的colorPicker.spectrum标签;由于它同时驱动两个轴,其可访问值会同时播报饱和度与亮度,例如 "Saturation 40%, Brightness 70%"(本地化键colorPicker.saturation/colorPicker.brightness);
  • 面板是 Tab 键停靠点,键盘行为:
    • Left/Right:调整饱和度 ±1%(按住Shift为 ±10%);
    • Up/Down:调整亮度 ±1%(按住Shift为 ±10%);
    • Home/End:饱和度跳到 0 / 100;
    • PageUp/PageDown:亮度 ±10%;
    • 与旁边的滑条一致,松开按键时才发出change事件(防止长按连发)。

这些按键逻辑可在 QColor.js 的onSpectrumKeydown/onSpectrumKeyup中找到:左右键的方向还会跟随 RTL 语言方向反转,与 QSlider 行为保持一致;饱和度/亮度经过between(s, 0, 100)钳制在 0–100。

Palette 色块

  • 色块是带名称的按钮(aria-label即其颜色值),包裹在一个携带本地化colorPicker.palette标签的分组(role="group")中;
  • 与当前模型匹配的色块会暴露为aria-pressed="true"
  • Palette 只有一个 Tab 停靠点(优先是当前选中的色块,否则是第一个),采用 roving tabindex 模式(源码中focusedSwatch负责记录当前拥有 Tab 停靠点的色块,见 QColor.js);
  • 方向键在色块间移动:Up/Down按"一行"的视觉行距移动(通过父容器宽度除以色块宽度实时测量列数,即使自定义了色块宽度也能落在正上方/正下方的色块上),Home/End跳到第一个/最后一个色块,Enter/Space选中当前聚焦色块;
  • 通过palette插槽渲染的色块,其无障碍实现由你自行负责。

测试用例验证了上述行为,例如"色块是带名称的按钮、位于命名分组内"、"匹配模型的色块拥有 Tab 停靠点且aria-pressed为 true"(QColor.test.js)。

本地化与禁用语义

  • 所有对外暴露的内部控件(视图标签、头部颜色值输入框、色相/透明度滑条)都使用 Quasar Language Pack 中colorPicker.*键的本地化名称,这些名称消费者无法从外部覆盖;
  • 测试用例对此做了断言:视图标签依次命名为colorPicker.spectrum/colorPicker.tune/colorPicker.palette,头部输入框为colorPicker.value,滑条为colorPicker.hue/colorPicker.alpha(QColor.test.js);
  • disable的 QColor 会在根元素上暴露aria-disabled="true"
  • readonlydisable时,光谱面板与色块会退出 Tab 键顺序(与其滑条一致),但光谱面板仍持续以aria-readonly/aria-disabled播报当前颜色。

补充说明与样式

  • QColor 还支持square(直角)、flat(扁平无阴影)、bordered(边框)三个视觉属性,均继承自 Quasar 通用样式约定;
  • 组件的 SASS 样式位于 QColor.sass,内部类名以q-color-picker__为前缀(如q-color-picker__header-contentq-color-picker__palette-rows等),可通过深选择器或全局样式进行定制;
  • 头部文本颜色会自动适配:当颜色过亮或 Alpha 过低时,内部通过luminosity()计算亮度并切换--light/--dark修饰类(QColor.js);
  • 如果需要在文档/组件库场景中同时覆盖多种交互状态,可参考 QColor.hydration.test.js 的测试写法,了解组件在服务端渲染与客户端水合时的行为边界。

至此,从基础绑定、弹出式取色、自定义视图与调色板,到懒更新、原生表单、强制格式与无障碍键盘操作,<q-color>的完整能力已覆盖完毕。将上述配置组合使用(例如default-view="palette"+palette插槽 +format-model="hexa"),即可快速构建出贴合业务品牌色的专业取色器。

【免费下载链接】quasarQuasar Framework - Build high-performance VueJS user interfaces in record time项目地址: https://gitcode.com/gh_mirrors/qu/quasar

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询