开发预览 更新于 2026-05-10

Radio 单选框

单选框 —— Radio + RadioGroup 组合,单选互斥、键盘可达。

基础用法

RadioGroup 通过 provide / Contextvaluenamesizedisabled 注入到子项。任一子项被选中时回调 update:modelValue / onChange

背景

已选:pro

<script setup lang="ts">
import { ref } from 'vue';
import { CfRadio, CfRadioGroup } from '@chufix-design/vue';

const plan = ref<'free' | 'pro' | 'team'>('pro');
</script>

<template>
  <div class="demo-stack">
    <CfRadioGroup v-model="plan" name="plan">
      <CfRadio value="free">Free</CfRadio>
      <CfRadio value="pro">Pro</CfRadio>
      <CfRadio value="team">Team</CfRadio>
    </CfRadioGroup>
    <p class="demo-hint">已选:<code>{{ plan }}</code></p>
  </div>
</template>
<script setup>
import { ref } from 'vue';
import { CfRadio, CfRadioGroup } from '@chufix-design/vue';

const plan = ref<'free' | 'pro' | 'team'>('pro');
</script>

<template>
  <div class="demo-stack">
    <CfRadioGroup v-model="plan" name="plan">
      <CfRadio value="free">Free</CfRadio>
      <CfRadio value="pro">Pro</CfRadio>
      <CfRadio value="team">Team</CfRadio>
    </CfRadioGroup>
    <p class="demo-hint">已选:<code>{{ plan }}</code></p>
  </div>
</template>
import { useState } from 'react';
import { CfRadio, CfRadioGroup } from '@chufix-design/react';

export default function Demo() {
const [plan, setPlan] = useState<'free' | 'pro' | 'team'>('pro');
return (
  <CfRadioGroup value={plan} name="plan" onChange={(v) => setPlan(v as any)}>
    <CfRadio value="free">Free</CfRadio>
    <CfRadio value="pro">Pro</CfRadio>
    <CfRadio value="team">Team</CfRadio>
  </CfRadioGroup>
);
}
import { useState } from 'react';
import { CfRadio, CfRadioGroup } from '@chufix-design/react';

export default function Demo() {
const [plan, setPlan] = useState<'free' | 'pro' | 'team'>('pro');
return (
  <CfRadioGroup value={plan} name="plan" onChange={(v) => setPlan(v)}>
    <CfRadio value="free">Free</CfRadio>
    <CfRadio value="pro">Pro</CfRadio>
    <CfRadio value="team">Team</CfRadio>
  </CfRadioGroup>
);
}

排列方向

direction="column" 把选项垂直排开。在选项较多或文案较长时使用。

背景
<script setup lang="ts">
import { ref } from 'vue';
import { CfRadio, CfRadioGroup } from '@chufix-design/vue';

const flavor = ref('vanilla');
</script>

<template>
  <CfRadioGroup v-model="flavor" direction="column">
    <CfRadio value="vanilla">香草</CfRadio>
    <CfRadio value="chocolate">巧克力</CfRadio>
    <CfRadio value="strawberry" disabled>草莓(缺货)</CfRadio>
    <CfRadio value="matcha">抹茶</CfRadio>
  </CfRadioGroup>
</template>
<script setup>
import { ref } from 'vue';
import { CfRadio, CfRadioGroup } from '@chufix-design/vue';

const flavor = ref('vanilla');
</script>

<template>
  <CfRadioGroup v-model="flavor" direction="column">
    <CfRadio value="vanilla">香草</CfRadio>
    <CfRadio value="chocolate">巧克力</CfRadio>
    <CfRadio value="strawberry" disabled>草莓(缺货)</CfRadio>
    <CfRadio value="matcha">抹茶</CfRadio>
  </CfRadioGroup>
</template>
<CfRadioGroup value={flavor} direction="column" onChange={setFlavor}>
<CfRadio value="vanilla">香草</CfRadio>
<CfRadio value="chocolate">巧克力</CfRadio>
<CfRadio value="strawberry" disabled>草莓(缺货)</CfRadio>
<CfRadio value="matcha">抹茶</CfRadio>
</CfRadioGroup>
<CfRadioGroup value={flavor} direction="column" onChange={setFlavor}>
<CfRadio value="vanilla">香草</CfRadio>
<CfRadio value="chocolate">巧克力</CfRadio>
<CfRadio value="strawberry" disabled>草莓(缺货)</CfRadio>
<CfRadio value="matcha">抹茶</CfRadio>
</CfRadioGroup>

尺寸

size 设在 RadioGroup 上,注入给所有子项。

背景
<script setup lang="ts">
import { ref } from 'vue';
import { CfRadio, CfRadioGroup } from '@chufix-design/vue';

const a = ref('s');
const b = ref('m');
const c = ref('l');
</script>

<template>
  <div class="demo-stack">
    <CfRadioGroup v-model="a" size="sm">
      <CfRadio value="s">Small</CfRadio>
      <CfRadio value="t">Tiny</CfRadio>
    </CfRadioGroup>
    <CfRadioGroup v-model="b" size="md">
      <CfRadio value="m">Medium</CfRadio>
      <CfRadio value="r">Regular</CfRadio>
    </CfRadioGroup>
    <CfRadioGroup v-model="c" size="lg">
      <CfRadio value="l">Large</CfRadio>
      <CfRadio value="x">Extra Large</CfRadio>
    </CfRadioGroup>
  </div>
</template>
<script setup>
import { ref } from 'vue';
import { CfRadio, CfRadioGroup } from '@chufix-design/vue';

const a = ref('s');
const b = ref('m');
const c = ref('l');
</script>

<template>
  <div class="demo-stack">
    <CfRadioGroup v-model="a" size="sm">
      <CfRadio value="s">Small</CfRadio>
      <CfRadio value="t">Tiny</CfRadio>
    </CfRadioGroup>
    <CfRadioGroup v-model="b" size="md">
      <CfRadio value="m">Medium</CfRadio>
      <CfRadio value="r">Regular</CfRadio>
    </CfRadioGroup>
    <CfRadioGroup v-model="c" size="lg">
      <CfRadio value="l">Large</CfRadio>
      <CfRadio value="x">Extra Large</CfRadio>
    </CfRadioGroup>
  </div>
</template>
<CfRadioGroup size="sm" value={a} onChange={setA}>
<CfRadio value="s">Small</CfRadio>
<CfRadio value="t">Tiny</CfRadio>
</CfRadioGroup>
<CfRadioGroup size="sm" value={a} onChange={setA}>
<CfRadio value="s">Small</CfRadio>
<CfRadio value="t">Tiny</CfRadio>
</CfRadioGroup>

事件与表单

change 会返回选中的值,同时透出 namechecked 与原生事件,适合表单联动、埋点、权限策略切换等场景。事件从 RadioGroup 发出时,meta 来自实际触发的子项。

背景
cn
切换区域后会显示 value、name 与 checked。
<script setup lang="ts">
import { ref } from 'vue';
import { CfBadge, CfRadio, CfRadioGroup, type RadioChangeMeta } from '@chufix-design/vue';

const region = ref<'cn' | 'eu' | 'us'>('cn');
const logs = ref(['切换区域后会显示 value、name 与 checked。']);

function record(value: string | number | boolean | null, meta: RadioChangeMeta) {
  logs.value = [
    `change: value=${value ?? '-'} / name=${meta.name ?? '-'} / checked=${meta.checked}`,
    ...logs.value,
  ].slice(0, 5);
}
</script>

<template>
  <div class="radio-events">
    <CfRadioGroup v-model="region" name="deploy-region" direction="column" @change="record">
      <CfRadio value="cn">华东节点 · 低延迟</CfRadio>
      <CfRadio value="eu">欧洲节点 · 合规隔离</CfRadio>
      <CfRadio value="us">美西节点 · 灰度发布</CfRadio>
    </CfRadioGroup>
    <div class="radio-events__status">
      <CfBadge tone="info" :content="region" />
      <div class="radio-events__log" aria-live="polite">
        <code v-for="entry in logs" :key="entry">{{ entry }}</code>
      </div>
    </div>
  </div>
</template>

<style scoped>
.radio-events {
  display: grid;
  gap: 12px;
  width: min(100%, 560px);
}

.radio-events__status {
  display: flex;
  align-items: flex-start;
  gap: 10px;
}

.radio-events__log {
  display: grid;
  gap: 4px;
  min-width: 0;
}

.radio-events__log code {
  white-space: normal;
}
</style>
<script setup>
import { ref } from 'vue';
import { CfBadge, CfRadio, CfRadioGroup } from '@chufix-design/vue';

const region = ref<'cn' | 'eu' | 'us'>('cn');
const logs = ref(['切换区域后会显示 value、name 与 checked。']);

function record(value, meta) {
  logs.value = [
    `change: value=${value ?? '-'} / name=${meta.name ?? '-'} / checked=${meta.checked}`,
    ...logs.value,
  ].slice(0, 5);
}
</script>

<template>
  <div class="radio-events">
    <CfRadioGroup v-model="region" name="deploy-region" direction="column" @change="record">
      <CfRadio value="cn">华东节点 · 低延迟</CfRadio>
      <CfRadio value="eu">欧洲节点 · 合规隔离</CfRadio>
      <CfRadio value="us">美西节点 · 灰度发布</CfRadio>
    </CfRadioGroup>
    <div class="radio-events__status">
      <CfBadge tone="info" :content="region" />
      <div class="radio-events__log" aria-live="polite">
        <code v-for="entry in logs" :key="entry">{{ entry }}</code>
      </div>
    </div>
  </div>
</template>

<style scoped>
.radio-events {
  display: grid;
  gap: 12px;
  width: min(100%, 560px);
}

.radio-events__status {
  display: flex;
  align-items: flex-start;
  gap: 10px;
}

.radio-events__log {
  display: grid;
  gap: 4px;
  min-width: 0;
}

.radio-events__log code {
  white-space: normal;
}
</style>
<CfRadioGroup
value={region}
name="deploy-region"
onChange={(value, meta) => {
  setRegion(value as string);
  console.log(meta.name, meta.checked);
}}
>
<CfRadio value="cn">华东节点</CfRadio>
<CfRadio value="eu">欧洲节点</CfRadio>
<CfRadio value="us">美西节点</CfRadio>
</CfRadioGroup>
<CfRadioGroup
value={region}
name="deploy-region"
onChange={(value, meta) => {
  setRegion(value);
  console.log(meta.name, meta.checked);
}}
>
<CfRadio value="cn">华东节点</CfRadio>
<CfRadio value="eu">欧洲节点</CfRadio>
<CfRadio value="us">美西节点</CfRadio>
</CfRadioGroup>

API

RadioGroup

Prop类型默认值说明
valuestring | number | boolean | nullnull当前选中值
namestring透传给底层 input 用于表单提交
size'sm' | 'md' | 'lg''md'整组尺寸
disabledbooleanfalse整组禁用
direction'row' | 'column''row'排列方向

Radio

Prop类型默认值说明
valuestring | number | boolean | null单项的值
disabledbooleanfalse单独禁用此项(叠加 RadioGroup.disabled)

Events

事件载荷说明
change / onChange(value, meta)选中值变化;meta 包含 eventvaluenamechecked
focus / onFocus(event)单个 Radio 获得焦点
blur / onBlur(event)单个 Radio 失去焦点

Radio 也可以脱离 RadioGroup 独立使用,自行管理 v-model / checked + onChange

反馈与讨论

Radio 单选框 的讨论

0
0 / 600
一键发送
正在加载评论...