# Switch 开关

在两个互斥状态之间即时切换，常用于「开 / 关」型设置项。底层是原生 `checkbox`，因此保留了表单提交、键盘操作与屏幕阅读器语义；默认带居中涟漪反馈。

## 代码演示

### 基础用法

`v-model` 绑定布尔值，默认插槽渲染轨道右侧的标签文本。

**演示说明：** 不传默认插槽时不渲染标签容器，只有一枚开关。

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

const notify = ref(false)
const weekly = ref(true)
</script>

<template>
  <div class="m-row-demo--col">
    <MSwitch v-model="notify">启用通知</MSwitch>
    <MSwitch v-model="weekly">接收周报</MSwitch>
    <span>通知状态：{{ notify ? '开启' : '关闭' }}</span>
  </div>
</template>
```

### 尺寸

`small` / `default` / `large` 三档，轨道与拇指同步缩放。

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

const small = ref(true)
const normal = ref(true)
const large = ref(true)
</script>

<template>
  <div class="m-row-demo">
    <MSwitch v-model="small" size="small">小</MSwitch>
    <MSwitch v-model="normal" size="default">默认</MSwitch>
    <MSwitch v-model="large" size="large">大</MSwitch>
  </div>
</template>
```

### 语义色

六种语义色对应选中态的轨道颜色，与全局 `--m-*` 令牌联动。

```vue
<script setup lang="ts">
import { reactive } from 'vue'

const colors = ['primary', 'secondary', 'success', 'warning', 'error', 'info'] as const

const on = reactive({
  primary: true,
  secondary: true,
  success: true,
  warning: true,
  error: true,
  info: true,
})
</script>

<template>
  <div class="m-row-demo">
    <MSwitch v-for="color in colors" :key="color" v-model="on[color]" :color="color">
      {{ color }}
    </MSwitch>
  </div>
</template>
```

### 禁用与加载

`disabled` 与 `loading` 都不可交互；`loading` 会在拇指内显示旋转指示器，适合状态尚未落库的过渡。

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

const disabledOn = ref(true)
const disabledOff = ref(false)
const loadingOn = ref(true)
const loadingOff = ref(false)
</script>

<template>
  <div class="m-row-demo">
    <MSwitch v-model="disabledOn" disabled>禁用 · 开</MSwitch>
    <MSwitch v-model="disabledOff" disabled>禁用 · 关</MSwitch>
    <MSwitch v-model="loadingOn" loading>加载 · 开</MSwitch>
    <MSwitch v-model="loadingOff" loading>加载 · 关</MSwitch>
  </div>
</template>
```

## API

### Props

| 属性 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `modelValue` | `boolean` | `undefined`（内部按 `!!` 处理） | 开关状态（v-model） |
| `color` | `'primary' \| 'secondary' \| 'success' \| 'warning' \| 'error' \| 'info'` | `'primary'` | 选中态轨道颜色 |
| `size` | `'small' \| 'default' \| 'large'` | `'default'` | 尺寸 |
| `disabled` | `boolean` | `false` | 是否禁用 |
| `loading` | `boolean` | `false` | 加载态：不可交互，拇指内显示旋转指示器 |
| `name` | `string` | `undefined` | 原生 input name（表单提交） |

### Events

| 事件 | 参数 | 说明 |
| --- | --- | --- |
| `update:modelValue` | `value: boolean` | 开关状态变化 |
| `change` | `value: boolean` | 开关状态变化 |

### Slots

| 插槽 | 参数 | 说明 |
| --- | --- | --- |
| `default` | 无 | 开关右侧标签文本（存在时才渲染 label 容器） |

## 使用建议

::: tip 提交表单时补上 name
组件底层是原生 `checkbox`，传入 `name` 后即可随 `<form>` 一起提交。未选中时原生 `checkbox` 不会带上该字段，取值时需要按「缺省即 false」处理。
:::

::: tip 即时生效 vs 确认后生效
开关默认「拨动即生效」。若切换背后是异步请求，建议在请求期间把 `loading` 置为 `true`，避免用户重复拨动造成状态错乱。
:::

::: warning loading 会连带禁用原生 input
`loading` 为真时内部 `input` 处于 `disabled`（即 `disabled || loading`），点击不会切换状态，同时涟漪反馈也被关闭。
:::

::: warning modelValue 会被强制布尔化
传入 `0`、`''`、`undefined` 都会被当作 `false`。不要用开关去承载三态（如 `null`）语义。
:::

## 相关组件

- [Checkbox 复选框](/components/checkbox)：需要勾选样式、或需要一次选中多项时使用。
- [Radio 单选框](/components/radio)：多于两个互斥状态时应改用单选组。
