Appearance
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 | 默认是否选中,非受控模式 | boolean | false |
value | 选项值,在 CheckboxGroup 中使用 | CheckboxValue | true |
disabled | 是否禁用 | boolean | false |
indeterminate | 是否为半选状态 | boolean | false |
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 | 是否禁用 | boolean | false |
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;
}