101 lines
4.9 KiB
JSON
101 lines
4.9 KiB
JSON
{
|
||
"slug": "select",
|
||
"end": "vue3",
|
||
"curated": true,
|
||
"summary": "Vue 3 端下拉选择:单选、多选、分组与内部关键字过滤,modelValue 存选中值。",
|
||
"usage": [
|
||
"defineProps 收 modelValue / options / groups / multiple / searchable / disabled / placeholder 七个(第 53-61 行),modelValue 类型是 [String, Number, Array]。",
|
||
"多选要求 modelValue 是数组:selectedArr 只在 Array.isArray(modelValue) 成立时才取到值(第 69 行),单选传值、多选传数组。",
|
||
"单选选中后自动收起面板(第 114 行),多选不收起(第 109-110 行);多选标签上的 ✕ 也会派发去掉该项后的新数组(第 117-121 行)。",
|
||
"搜索框绑的是内部 keyword ref(第 17、66 行)而不是 prop,且每次展开面板都会把它清空(第 89 行的 watch),外部预设不了搜索词。",
|
||
"分组与平铺二选一:groups 有内容就渲染 .kole-select-group-label 分组头(第 20-32 行),否则铺 options(第 34-43 行)。"
|
||
],
|
||
"bestPractices": [
|
||
"groups 模式下列表只从 groups 取(labelOf 第 99-100 行做了兜底),options 与 groups 同传时以 groups 为准渲染。",
|
||
"点外部关闭依赖挂在 document 上的 click 监听(第 122-126 行),面板里的搜索框写了 @click.stop(第 17 行)避免点到就关。",
|
||
"空态「无匹配选项」由 isEmpty 控制(第 45、85-87 行),groups 模式下它只看分组过滤后的条数,不看 options。"
|
||
],
|
||
"a11y": [
|
||
"触发器是没有 role 的 div,靠 tabindex=\"0\" 进焦点序列,但只绑了 @click(第 3 行),Enter 与空格都打不开面板。",
|
||
"选中态用 .kole-select-option.is-selected 类表达(第 26 行),没有 aria-selected 或 listbox 语义,读屏器分不清选中项。",
|
||
"禁用态只有 .kole-select.is-disabled 类与样式(第 2 行),触发器上没有 aria-disabled,键盘仍会停在它上面。"
|
||
],
|
||
"apiCarrier": {
|
||
"kind": "props",
|
||
"note": "本端载体是七个 props 与 update:modelValue、change 两个 emit;没有插槽,选项与分组由 options / groups 数据驱动(表内 keyword 一行实为内部搜索词 ref)。",
|
||
"table": [
|
||
{
|
||
"name": "disabled",
|
||
"type": "Boolean",
|
||
"desc": "是否禁用(frameworks/Select.vue3.vue:2)"
|
||
},
|
||
{
|
||
"name": "groups",
|
||
"type": "属性",
|
||
"desc": "有内容时改走分组模板,渲染 .kole-select-group-label 分组头而非平铺 options(frameworks/Select.vue3.vue:20-32)"
|
||
},
|
||
{
|
||
"name": "keyword",
|
||
"type": "属性",
|
||
"desc": "内部 keyword ref(非 prop):搜索框 v-model 绑它,每次展开面板都会被 watch 清空(frameworks/Select.vue3.vue:17,31,66,89)"
|
||
},
|
||
{
|
||
"name": "modelValue",
|
||
"type": "String | Number | Array",
|
||
"desc": "双向绑定值(frameworks/Select.vue3.vue:54)"
|
||
},
|
||
{
|
||
"name": "multiple",
|
||
"type": "属性",
|
||
"desc": "为真时 modelValue 需为数组,选中不收起面板并渲染带 ✕ 的已选标签(frameworks/Select.vue3.vue:4,69,109-121)"
|
||
},
|
||
{
|
||
"name": "options",
|
||
"type": "Array",
|
||
"desc": "选项数据(frameworks/Select.vue3.vue:24)"
|
||
},
|
||
{
|
||
"name": "placeholder",
|
||
"type": "String",
|
||
"desc": "占位提示文本(frameworks/Select.vue3.vue:5)"
|
||
},
|
||
{
|
||
"name": "searchable",
|
||
"type": "Boolean",
|
||
"desc": "是否可搜索(契约:支持单选、多选、搜索、分组、级联)(frameworks/Select.vue3.vue:16)"
|
||
},
|
||
{
|
||
"name": "change",
|
||
"type": "(val: any) => void",
|
||
"desc": "值变化时触发(frameworks/Select.vue3.vue:63)"
|
||
}
|
||
]
|
||
},
|
||
"resources": [
|
||
{
|
||
"file": "frameworks/Select.vue3.vue",
|
||
"kind": "Vue 3",
|
||
"desc": "该端实现(本页 API 与用法的唯一权威来源)。"
|
||
},
|
||
{
|
||
"file": "frameworks/Select.css",
|
||
"kind": "样式",
|
||
"desc": "该组件的样式文件,类名口径以它为准。"
|
||
}
|
||
],
|
||
"exampleIds": [
|
||
"select-ex-1",
|
||
"select-ex-2",
|
||
"select-ex-3",
|
||
"select-ex-4",
|
||
"select-ex-5"
|
||
],
|
||
"notes": [
|
||
"props 与 emit 声明见 frameworks/Select.vue3.vue:53-63;modelValue 类型为 [String, Number, Array],默认 null。",
|
||
"多选数组判断见 frameworks/Select.vue3.vue:69;单选自动收起见第 114 行,多选不收起见 109-110 行。",
|
||
"搜索词是内部 ref 并在展开时重置(frameworks/Select.vue3.vue:31,66,89),因此 keyword 不是对外 prop。",
|
||
"分组与平铺两条分支见 frameworks/Select.vue3.vue:20-32 与 34-43;空态见第 45 行与 85-87 行。",
|
||
"点外部关闭的监听见 frameworks/Select.vue3.vue:122-126;搜索框写了 @click.stop(第 17 行)避免误关。"
|
||
]
|
||
}
|