Skip to content

Checkbox 复选框 ​

用于多选或开关式勾选,适合权限配置、批量选择、偏好设置等场景。

何时使用 ​

  • 需要在一组互不排斥的选项中选择多个值。
  • 需要展示全选、半选、最多可选等状态。
  • 需要以单个布尔值表达是否启用某项配置。

基础用法 ​

未同意
vue
<template>
  <x-checkbox v-model="checked">同意协议</x-checkbox>
</template>

<script setup lang="ts">
import { ref } from 'vue';

const checked = ref(false);
</script>

尺寸 ​

vue
<template>
  <x-checkbox v-model="checked" size="mini">mini</x-checkbox>
  <x-checkbox v-model="checked" size="small">small</x-checkbox>
  <x-checkbox v-model="checked" size="medium">medium</x-checkbox>
  <x-checkbox v-model="checked" size="large">large</x-checkbox>

  <x-checkbox-group v-model="values" :options="options" size="mini" />
  <x-checkbox-group v-model="values" :options="options" size="large" />
</template>

<script setup lang="ts">
import { ref } from 'vue';

const checked = ref(true);
const values = ref(['read']);
const options = [
  { label: '读取', value: 'read' },
  { label: '写入', value: 'write' },
];
</script>

禁用状态 ​

vue
<template>
  <x-checkbox disabled>禁用未选</x-checkbox>
  <x-checkbox v-model="checked" disabled>禁用已选</x-checkbox>
</template>

<script setup lang="ts">
import { ref } from 'vue';

const checked = ref(true);
</script>

半选状态 ​

vue
<template>
  <x-checkbox v-model="checkAll" :indeterminate="isIndeterminate">全选权限</x-checkbox>
  <x-checkbox-group v-model="values" :options="options" />
</template>

<script setup lang="ts">
import { computed, ref } from 'vue';

const values = ref(['read']);
const permissions = ['read', 'write', 'publish'];
const options = [
  { label: '读取', value: 'read' },
  { label: '写入', value: 'write' },
  { label: '发布', value: 'publish' },
];
const checkAll = computed({
  get: () => permissions.every((value) => values.value.includes(value)),
  set: (checked: boolean) => {
    values.value = checked ? [...permissions] : [];
  },
});
const isIndeterminate = computed(
  () => values.value.length > 0 && values.value.length < permissions.length,
);
</script>

复选框组 ​

vue
<template>
  <x-checkbox-group v-model="values" :options="options" />
</template>

<script setup lang="ts">
import { ref } from 'vue';

const values = ref(['read']);
const options = [
  { label: '读取', value: 'read' },
  { label: '写入', value: 'write' },
  { label: '发布', value: 'publish' },
];
</script>

纵向排列 ​

vue
<template>
  <x-checkbox-group v-model="values" direction="vertical" :options="options" />
</template>

<script setup lang="ts">
import { ref } from 'vue';

const values = ref(['email']);
const options = [
  { label: '邮件', value: 'email' },
  { label: '短信', value: 'sms', disabled: true },
  { label: '站内信', value: 'notice' },
];
</script>

最多可选 ​

vue
<template>
  <x-checkbox-group v-model="values" :options="options" :max="2" />
</template>

<script setup lang="ts">
import { ref } from 'vue';

const values = ref(['read']);
const options = [
  { label: '读取', value: 'read' },
  { label: '写入', value: 'write' },
  { label: '发布', value: 'publish' },
  { label: '删除', value: 'delete' },
];
</script>

自定义文案 ​

vue
<template>
  <x-checkbox-group v-model="values" :options="options">
    <template #label="{ data }">
      <span>{{ data.label }}模块</span>
    </template>
  </x-checkbox-group>
</template>

<script setup lang="ts">
import { ref } from 'vue';
const values = ref(['vue']);
const options = [{ label: 'Vue', value: 'vue' }, { label: 'TypeScript', value: 'ts' }];
</script>

自定义复选框图形 ​

vue
<template>
  <x-checkbox-group v-model="values" :options="options">
    <template #checkbox="{ checked, disabled }">
      <span :class="{ 'is-checked': checked, 'is-disabled': disabled }">
        {{ checked ? '✓' : '' }}
      </span>
    </template>
  </x-checkbox-group>
</template>

<script setup lang="ts">
import { ref } from 'vue';
const values = ref(['vue']);
const options = [{ label: 'Vue', value: 'vue' }, { label: 'TypeScript', value: 'ts' }];
</script>

布尔值选项 ​

vue
<template>
  <x-checkbox-group v-model="values" :options="options" />
</template>

<script setup lang="ts">
import { ref } from 'vue';

const values = ref([true]);
const options = [
  { label: '启用', value: true },
  { label: '停用', value: false },
];
</script>

事件 ​

vue
<template>
  <x-checkbox-group v-model="values" :options="options" @change="handleChange" />
</template>

<script setup lang="ts">
import { ref } from 'vue';

const values = ref(['read']);
const handleChange = (value: Array<string | number | boolean>) => {
  console.log(value);
};
</script>

在 Form 中校验 ​

组件放进 x-form-item 后会自动继承 Form 的尺寸与禁用状态,并按 FormItem 的校验规则展示错误。默认 validateTrigger 为 change,即值变化时触发校验。

vue
<template>
  <x-form ref="formRef" :model="formState" :rules="formRules">
    <x-form-item field="features" label="功能">
      <x-checkbox-group v-model="formState.features">
      <x-checkbox value="report">报表</x-checkbox>
      <x-checkbox value="alert">告警</x-checkbox>
    </x-checkbox-group>
    </x-form-item>
    <x-form-item>
      <x-space>
        <x-button type="primary" @click="handleValidate">校验</x-button>
        <x-button @click="handleReset">重置</x-button>
      </x-space>
    </x-form-item>
  </x-form>
  <p role="status">{{ validateResult }}</p>
</template>

<script setup lang="ts">
import { reactive, ref } from 'vue';
import type { FormInstance, FieldRule } from 'x-next';

const formState = reactive({ features: [] as string[] });
const formRules: Record<string, FieldRule[]> = {
  features: [{ type: 'array', required: true, message: '至少选择一项功能' }],
};
const formRef = ref<FormInstance>();
const validateResult = ref('');

const handleValidate = async () => {
  const errors = await formRef.value!.validate();
  validateResult.value = errors
    ? `校验失败:${Object.values(errors).map((error) => error.message).join(';')}`
    : '校验通过';
};
const handleReset = () => {
  formRef.value!.resetFields();
  validateResult.value = '已重置';
};
</script>

原生表单属性 ​

id、name、required、form、tabindex、autofocus、autocomplete 和 aria-* 传给内部原生 checkbox input。class、style、data-* 等容器属性保留在外层 label;组件自行管理 checked、disabled 和 aria-checked。组件本身就是 label,不要再嵌套外层 label。

下面的 Checkbox 位于表单外,通过 form 关联原生表单。未勾选时浏览器阻止提交;勾选后 FormData 能取得 name 对应的值。单纯传 required 不会创建 x-form 的校验规则。

先勾选,再提交
vue
<script setup lang="ts">
import { ref } from 'vue';
import { Button, Checkbox } from 'x-next';
import 'x-next/dist/style.css';

const agreement = ref(false);
const result = ref('');
function submit(event: Event) {
  result.value = String(new FormData(event.currentTarget as HTMLFormElement).get('agreement'));
}
</script>

<template>
  <form id="agreement-form" @submit.prevent="submit">
    <Button html-type="submit">提交</Button>
  </form>
  <Checkbox v-model="agreement" name="agreement" value="accepted" form="agreement-form" required>同意协议</Checkbox>
  <p role="status">{{ result }}</p>
</template>

按需导入 ​

ts
import { Checkbox, CheckboxGroup } from 'x-next';

样式按需引入(base.css 为共享基础层,多个组件只需引入一次):

ts
import 'x-next/style/base.css';
import 'x-next/style/form-checkbox.css';

Checkbox Props ​

参数说明类型默认值
modelValue绑定值boolean | CheckboxValue[]undefined
defaultChecked默认是否选中,非受控模式booleanfalse
value选项值,在 CheckboxGroup 中使用CheckboxValuetrue
disabled是否禁用booleanfalse
indeterminate是否为半选状态booleanfalse
size组件尺寸'mini' | 'small' | 'medium' | 'large'跟随全局配置

Checkbox Events ​

事件名说明回调参数
update:modelValue值更新时触发value: boolean | CheckboxValue[]
change值变化时触发value: boolean | CheckboxValue[], event: Event

Checkbox Slots ​

插槽名说明参数
default复选框文案-
checkbox自定义复选框图形{ checked, disabled }

CheckboxGroup Props ​

参数说明类型默认值
modelValue绑定值CheckboxValue[]undefined
defaultValue默认值,非受控模式CheckboxValue[][]
max最多可选数量number-
options选项数据Array<CheckboxValue | CheckboxOption>-
direction排列方向'horizontal' | 'vertical''horizontal'
disabled是否禁用booleanfalse
size组件尺寸'mini' | 'small' | 'medium' | 'large'跟随全局配置

CheckboxGroup Events ​

事件名说明回调参数
update:modelValue值更新时触发value: CheckboxValue[]
change值变化时触发value: CheckboxValue[], event: Event

CheckboxGroup Slots ​

插槽名说明参数
default自定义复选框列表-
label自定义 options 文案{ data }
checkbox自定义复选框图形{ checked, disabled }

类型 ​

ts
type CheckboxValue = string | number | boolean;

interface CheckboxOption {
  label?: string | (() => VNode);
  value: CheckboxValue;
  disabled?: boolean;
  indeterminate?: boolean;
}