useToggle 🔄
介绍
想要轻松管理布尔状态的切换吗?useToggle 就像一个智能开关,让你在 true 和 false 之间自由切换!🎛️
无论是控制模态框的显示隐藏、切换主题模式,还是管理组件的展开收起状态,这个 Hook 都能让你的状态管理变得简单而优雅!
代码演示
基础用法 🚀
让我们从最简单的开关控制开始:
html
<template>
<div class="toggle-demo">
<div class="status-display">
<span class="status-text">
当前状态: {{ isOn ? '开启 🟢' : '关闭 🔴' }}
</span>
</div>
<div class="control-buttons">
<button @click="toggle()" class="toggle-btn">
{{ isOn ? '关闭' : '开启' }}
</button>
<button @click="toggle(true)" class="force-btn">
强制开启
</button>
<button @click="toggle(false)" class="force-btn">
强制关闭
</button>
</div>
</div>
</template>js
import { useToggle } from '@vant/use';
export default {
setup() {
// 创建一个开关状态,默认为关闭
const [isOn, toggle] = useToggle();
// 无参数调用:自动切换状态
const handleAutoToggle = () => {
toggle();
console.log('状态已切换:', isOn.value ? '开启' : '关闭');
};
// 有参数调用:设置特定状态
const handleForceOn = () => {
toggle(true);
console.log('强制开启!');
};
const handleForceOff = () => {
toggle(false);
console.log('强制关闭!');
};
return {
isOn,
toggle,
handleAutoToggle,
handleForceOn,
handleForceOff
};
},
};模态框控制 📱
使用 useToggle 优雅地管理模态框状态:
html
<template>
<div class="modal-demo">
<!-- 触发按钮 -->
<button @click="openModal" class="open-btn">
打开设置 ⚙️
</button>
<!-- 模态框 -->
<div v-if="isModalVisible" class="modal-overlay" @click="closeModal">
<div class="modal-content" @click.stop>
<div class="modal-header">
<h3>设置面板</h3>
<button @click="closeModal" class="close-btn">✕</button>
</div>
<div class="modal-body">
<div class="setting-item">
<label>
<input
type="checkbox"
:checked="isDarkMode"
@change="toggleDarkMode"
/>
深色模式 🌙
</label>
</div>
<div class="setting-item">
<label>
<input
type="checkbox"
:checked="isNotificationEnabled"
@change="toggleNotification"
/>
推送通知 🔔
</label>
</div>
</div>
<div class="modal-footer">
<button @click="resetSettings" class="reset-btn">
重置设置
</button>
<button @click="closeModal" class="confirm-btn">
确认
</button>
</div>
</div>
</div>
</div>
</template>js
import { useToggle } from '@vant/use';
import { watch } from 'vue';
export default {
setup() {
// 模态框显示状态
const [isModalVisible, toggleModal] = useToggle(false);
// 设置项状态
const [isDarkMode, toggleDarkMode] = useToggle(false);
const [isNotificationEnabled, toggleNotification] = useToggle(true);
// 打开模态框
const openModal = () => {
toggleModal(true);
document.body.style.overflow = 'hidden'; // 禁止背景滚动
};
// 关闭模态框
const closeModal = () => {
toggleModal(false);
document.body.style.overflow = ''; // 恢复滚动
};
// 重置所有设置
const resetSettings = () => {
toggleDarkMode(false);
toggleNotification(true);
console.log('设置已重置!');
};
// 监听深色模式变化
watch(isDarkMode, (newValue) => {
document.documentElement.classList.toggle('dark-theme', newValue);
console.log('深色模式:', newValue ? '已开启' : '已关闭');
});
// 监听通知设置变化
watch(isNotificationEnabled, (newValue) => {
if (newValue) {
console.log('通知已开启 🔔');
} else {
console.log('通知已关闭 🔕');
}
});
return {
isModalVisible,
isDarkMode,
isNotificationEnabled,
openModal,
closeModal,
toggleDarkMode,
toggleNotification,
resetSettings
};
}
};折叠面板组件 📋
创建一个可展开收起的信息面板:
html
<template>
<div class="accordion-demo">
<div class="accordion-item" v-for="item in accordionItems" :key="item.id">
<div
class="accordion-header"
@click="item.toggle()"
:class="{ active: item.isExpanded }"
>
<h4>{{ item.title }}</h4>
<span class="accordion-icon">
{{ item.isExpanded ? '▼' : '▶' }}
</span>
</div>
<transition name="accordion">
<div v-if="item.isExpanded" class="accordion-content">
<p>{{ item.content }}</p>
</div>
</transition>
</div>
</div>
</template>js
import { useToggle } from '@vant/use';
import { reactive } from 'vue';
export default {
setup() {
// 创建多个折叠面板项
const accordionItems = reactive([
{
id: 1,
title: '什么是 Vue 3?',
content: 'Vue 3 是一个渐进式 JavaScript 框架,用于构建用户界面。它具有更好的性能、更小的包体积和更强的 TypeScript 支持。',
...useToggle(false)
},
{
id: 2,
title: 'Composition API 的优势',
content: 'Composition API 提供了更好的逻辑复用、更清晰的代码组织和更强的类型推导能力,让大型项目的维护变得更加容易。',
...useToggle(false)
},
{
id: 3,
title: '如何开始学习?',
content: '建议从官方文档开始,然后通过实际项目练习。可以先学习基础概念,再逐步深入到高级特性和生态系统。',
...useToggle(false)
}
]);
// 展开所有面板
const expandAll = () => {
accordionItems.forEach(item => item.toggle(true));
};
// 收起所有面板
const collapseAll = () => {
accordionItems.forEach(item => item.toggle(false));
};
return {
accordionItems,
expandAll,
collapseAll
};
}
};功能开关管理 🎛️
实现一个功能开关面板,管理应用的各种特性:
html
<template>
<div class="feature-toggle-panel">
<h3>功能开关面板 🎛️</h3>
<div class="feature-grid">
<div
v-for="feature in features"
:key="feature.key"
class="feature-card"
:class="{ enabled: feature.isEnabled }"
>
<div class="feature-header">
<span class="feature-icon">{{ feature.icon }}</span>
<h4>{{ feature.name }}</h4>
</div>
<p class="feature-description">{{ feature.description }}</p>
<div class="feature-controls">
<label class="toggle-switch">
<input
type="checkbox"
:checked="feature.isEnabled"
@change="feature.toggle()"
/>
<span class="slider"></span>
</label>
<span class="status-text">
{{ feature.isEnabled ? '已启用' : '已禁用' }}
</span>
</div>
</div>
</div>
<div class="panel-actions">
<button @click="enableAllFeatures" class="action-btn primary">
启用全部功能
</button>
<button @click="disableAllFeatures" class="action-btn secondary">
禁用全部功能
</button>
<button @click="resetToDefaults" class="action-btn">
恢复默认设置
</button>
</div>
</div>
</template>js
import { useToggle } from '@vant/use';
import { reactive, watch } from 'vue';
export default {
setup() {
// 定义功能开关列表
const features = reactive([
{
key: 'notifications',
name: '推送通知',
icon: '🔔',
description: '接收应用内消息和提醒',
defaultValue: true,
...useToggle(true)
},
{
key: 'darkMode',
name: '深色模式',
icon: '🌙',
description: '切换到深色主题界面',
defaultValue: false,
...useToggle(false)
},
{
key: 'autoSave',
name: '自动保存',
icon: '💾',
description: '自动保存用户输入的内容',
defaultValue: true,
...useToggle(true)
},
{
key: 'analytics',
name: '数据分析',
icon: '📊',
description: '收集使用数据以改善体验',
defaultValue: false,
...useToggle(false)
},
{
key: 'betaFeatures',
name: '测试功能',
icon: '🧪',
description: '启用实验性的新功能',
defaultValue: false,
...useToggle(false)
},
{
key: 'offlineMode',
name: '离线模式',
icon: '📱',
description: '在无网络时继续使用应用',
defaultValue: true,
...useToggle(true)
}
]);
// 启用所有功能
const enableAllFeatures = () => {
features.forEach(feature => feature.toggle(true));
console.log('所有功能已启用!');
};
// 禁用所有功能
const disableAllFeatures = () => {
features.forEach(feature => feature.toggle(false));
console.log('所有功能已禁用!');
};
// 恢复默认设置
const resetToDefaults = () => {
features.forEach(feature => {
feature.toggle(feature.defaultValue);
});
console.log('已恢复默认设置!');
};
// 监听功能状态变化
features.forEach(feature => {
watch(() => feature.isEnabled, (newValue) => {
console.log(`${feature.name} ${newValue ? '已启用' : '已禁用'}`);
// 根据功能类型执行相应操作
switch (feature.key) {
case 'darkMode':
document.documentElement.classList.toggle('dark', newValue);
break;
case 'notifications':
if (newValue && 'Notification' in window) {
Notification.requestPermission();
}
break;
case 'analytics':
// 启用/禁用分析代码
break;
}
});
});
return {
features,
enableAllFeatures,
disableAllFeatures,
resetToDefaults
};
}
};游戏状态控制 🎮
使用 useToggle 管理游戏的各种状态:
html
<template>
<div class="game-control-panel">
<h3>游戏控制面板 🎮</h3>
<div class="game-status">
<div class="status-item">
<span class="label">游戏状态:</span>
<span class="value" :class="{ active: isGameRunning }">
{{ isGameRunning ? '运行中 ▶️' : '已暂停 ⏸️' }}
</span>
</div>
<div class="status-item">
<span class="label">音效:</span>
<span class="value" :class="{ active: isSoundEnabled }">
{{ isSoundEnabled ? '开启 🔊' : '关闭 🔇' }}
</span>
</div>
<div class="status-item">
<span class="label">调试模式:</span>
<span class="value" :class="{ active: isDebugMode }">
{{ isDebugMode ? '开启 🐛' : '关闭' }}
</span>
</div>
</div>
<div class="game-controls">
<button
@click="toggleGame"
class="control-btn"
:class="{ primary: !isGameRunning, danger: isGameRunning }"
>
{{ isGameRunning ? '暂停游戏' : '开始游戏' }}
</button>
<button @click="toggleSound" class="control-btn">
{{ isSoundEnabled ? '关闭音效' : '开启音效' }}
</button>
<button @click="toggleDebug" class="control-btn">
{{ isDebugMode ? '关闭调试' : '开启调试' }}
</button>
<button @click="resetGame" class="control-btn secondary">
重置游戏
</button>
</div>
<div v-if="isDebugMode" class="debug-panel">
<h4>调试信息 🔍</h4>
<pre>{{ debugInfo }}</pre>
</div>
</div>
</template>js
import { useToggle } from '@vant/use';
import { computed, watch } from 'vue';
export default {
setup() {
// 游戏状态管理
const [isGameRunning, toggleGame] = useToggle(false);
const [isSoundEnabled, toggleSound] = useToggle(true);
const [isDebugMode, toggleDebug] = useToggle(false);
// 调试信息
const debugInfo = computed(() => ({
gameRunning: isGameRunning.value,
soundEnabled: isSoundEnabled.value,
debugMode: isDebugMode.value,
timestamp: new Date().toLocaleTimeString()
}));
// 重置游戏
const resetGame = () => {
toggleGame(false);
toggleSound(true);
toggleDebug(false);
console.log('游戏已重置!');
};
// 监听游戏状态变化
watch(isGameRunning, (running) => {
if (running) {
console.log('游戏开始!🎮');
// 启动游戏循环
startGameLoop();
} else {
console.log('游戏暂停!⏸️');
// 停止游戏循环
stopGameLoop();
}
});
// 监听音效状态变化
watch(isSoundEnabled, (enabled) => {
if (enabled) {
console.log('音效已开启!🔊');
// 启用音效系统
} else {
console.log('音效已关闭!🔇');
// 禁用音效系统
}
});
// 监听调试模式变化
watch(isDebugMode, (debug) => {
if (debug) {
console.log('调试模式已开启!🐛');
// 显示调试信息
} else {
console.log('调试模式已关闭!');
// 隐藏调试信息
}
});
// 游戏循环控制
let gameLoopId = null;
const startGameLoop = () => {
if (gameLoopId) return;
gameLoopId = setInterval(() => {
// 游戏逻辑更新
if (isDebugMode.value) {
console.log('游戏循环更新...');
}
}, 16); // 60 FPS
};
const stopGameLoop = () => {
if (gameLoopId) {
clearInterval(gameLoopId);
gameLoopId = null;
}
};
return {
isGameRunning,
isSoundEnabled,
isDebugMode,
debugInfo,
toggleGame,
toggleSound,
toggleDebug,
resetGame
};
}
};API 参考 📚
类型定义
ts
function useToggle(
defaultValue?: boolean,
): [Ref<boolean>, (newValue?: boolean) => void];参数
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| defaultValue | 初始状态值 | boolean | false |
返回值
| 参数 | 说明 | 类型 |
|---|---|---|
| state | 当前的布尔状态值 | Ref<boolean> |
| toggle | 切换状态的函数,可传入具体值或不传参自动切换 | (newValue?: boolean) => void |
实际应用场景 🎯
1. 界面控制
- 模态框管理: 控制弹窗、抽屉、对话框的显示隐藏
- 折叠面板: 管理手风琴组件的展开收起状态
- 侧边栏: 控制导航栏的显示隐藏
2. 功能开关
- 主题切换: 深色模式与浅色模式的切换
- 功能启用: 控制应用功能的开启关闭
- 设置管理: 用户偏好设置的状态管理
3. 游戏开发
- 游戏状态: 暂停/继续、音效开关、调试模式
- 玩家状态: 生命值、技能状态、装备状态
- 关卡控制: 关卡解锁、完成状态
4. 表单交互
- 复选框: 单个选项的选中状态
- 开关按钮: 设置项的启用禁用
- 条件显示: 根据选择显示不同内容
最佳实践 💡
1. 语义化命名
js
// ✅ 推荐:使用有意义的变量名
const [isModalVisible, toggleModal] = useToggle(false);
const [isDarkMode, toggleDarkMode] = useToggle(false);
// ❌ 避免:使用无意义的变量名
const [flag, setFlag] = useToggle(false);2. 合理设置默认值
js
// ✅ 推荐:根据业务需求设置合理的默认值
const [isNotificationEnabled, toggleNotification] = useToggle(true); // 通知默认开启
const [isDebugMode, toggleDebug] = useToggle(false); // 调试模式默认关闭3. 状态变化监听
js
// ✅ 推荐:监听状态变化执行副作用
watch(isDarkMode, (newValue) => {
document.documentElement.classList.toggle('dark', newValue);
localStorage.setItem('darkMode', String(newValue));
});4. 组合使用
js
// ✅ 推荐:多个相关状态的组合管理
const [isLoading, toggleLoading] = useToggle(false);
const [isError, toggleError] = useToggle(false);
const [isSuccess, toggleSuccess] = useToggle(false);
const resetStatus = () => {
toggleLoading(false);
toggleError(false);
toggleSuccess(false);
};调试技巧 🔧
1. 状态变化日志
js
// 添加状态变化日志
const [isVisible, toggleVisible] = useToggle(false);
watch(isVisible, (newValue, oldValue) => {
console.log(`状态变化: ${oldValue} -> ${newValue}`);
}, { immediate: true });2. 开发工具集成
js
// 在开发环境中添加调试信息
if (process.env.NODE_ENV === 'development') {
window.debugToggles = {
isModalVisible,
isDarkMode,
isDebugMode
};
}3. 状态持久化
js
// 将状态保存到 localStorage
const [isDarkMode, toggleDarkMode] = useToggle(
JSON.parse(localStorage.getItem('darkMode') || 'false')
);
watch(isDarkMode, (newValue) => {
localStorage.setItem('darkMode', JSON.stringify(newValue));
});性能优化 ⚡
1. 避免不必要的重新渲染
js
// ✅ 推荐:使用 computed 计算衍生状态
const statusText = computed(() =>
isLoading.value ? '加载中...' : '加载完成'
);2. 批量状态更新
js
// ✅ 推荐:使用 nextTick 批量更新
import { nextTick } from 'vue';
const resetAllStates = async () => {
toggleLoading(false);
toggleError(false);
toggleSuccess(false);
await nextTick();
console.log('所有状态已重置');
};浏览器兼容性 🌐
useToggle 基于 Vue 3 的响应式系统,支持所有 Vue 3 兼容的环境:
- Chrome 60+
- Firefox 60+
- Safari 12+
- Edge 79+
相关文档 📖
核心概念
- Vue 3 响应式系统 - 了解响应式原理
- Ref API - 响应式引用
- Watch API - 监听器
相关 Hooks
- useBoolean - VueUse 中的布尔值管理
- useLocalStorage - 本地存储状态
- useDark - 深色模式管理
实际应用
- Element Plus Switch - 开关组件
- Ant Design Vue Switch - 开关组件
- Vant Switch - 移动端开关