Skip to content

Checkbox 复选框

在一组选项里多选。支持半选态,用于表达「部分选中」。

基础用法

vue
<script setup>
import { ref } from 'vue'
const agreed = ref(false)
</script>

<template>
  <SrCheckbox v-model="agreed">同意服务条款</SrCheckbox>
</template>

半选态

indeterminate 用于「父项部分勾选」的场景——比如「全选」框在三项里选了一项。

vue
<SrCheckbox v-model="value" indeterminate>半选状态</SrCheckbox>

indeterminatemodelValue 是两回事

半选不改变值。它只是一个视觉状态,表示「下面有一部分选了」。 点击半选状态的框,先变为全选(而不是直接取消)——这是通行的交互约定, 因为用户此时最可能想表达的是「全都要」。

全选组合

vue
<script setup>
import { computed, ref } from 'vue'

const all = ['Vue', 'Nuxt', 'TypeScript']
const checked = ref([])

const isAll = computed(() => checked.value.length === all.length)
const isPartial = computed(() => checked.value.length > 0 && checked.value.length < all.length)
</script>

<template>
  <SrCheckbox
    :model-value="isAll"
    :indeterminate="isPartial"
    @update:model-value="(v) => (checked = v ? [...all] : [])"
  >
    全选
  </SrCheckbox>

  <SrCheckbox
    v-for="item in all"
    :key="item"
    :model-value="checked.includes(item)"
    @update:model-value="(v) => (v ? checked.push(item) : checked.splice(checked.indexOf(item), 1))"
  >
    {{ item }}
  </SrCheckbox>
</template>

组件不接管数组增删。 它只知道自己被勾没被勾,不知道自己在哪个数组里—— 「往哪个数组加、加完要不要去重」是业务逻辑,硬塞进组件会让它无法应对 「选项来自服务端、选中项存在另一处」这类常见情况。

尺寸与禁用

vue
<SrCheckbox size="sm">小</SrCheckbox>
<SrCheckbox size="md">中</SrCheckbox>
<SrCheckbox disabled>禁用</SrCheckbox>

Props

名称类型默认值说明
modelValuebooleanfalse是否选中
size'sm' | 'md''md'尺寸
disabledbooleanfalse是否禁用
indeterminatebooleanfalse是否半选(不影响值

插槽

名称说明
default标签文本

事件

事件参数说明
update:modelValueboolean勾选状态变化
changeboolean同上(语义化事件)

无障碍

  • <label> 包裹原生 <input type="checkbox">,点击文字即可切换—— 自己拼 div 时几乎一定会漏掉这一点
  • 半选通过 aria-checked="mixed" 暴露,读屏软件能播报「部分选中」
  • 禁用态用原生 disabled 属性而非仅靠 pointer-events: none—— 后者仍能被键盘聚焦,用户会以为它可操作

自用组件库 · 源码分发 · 不发布 npm