在 中变量默认自动暴露,关键在于控制暴露范围而非禁止暴露;应通过作用域隔离、清晰命名、defineexpose 精确控制及 typescript 类型约束来管理。

在 <script setup></script> 中,变量默认会自动暴露到模板和父组件作用域,命名冲突和全局污染不是“会不会发生”的问题,而是“什么时候暴露、暴露给谁”的问题。关键不在于禁止暴露,而在于控制暴露范围和命名意图。
用作用域隔离私有变量
以下划线开头(如 _internalData)只是约定,并不能阻止暴露——Vue 不做任何拦截。真正私有的方式是让变量脱离顶层作用域:
- 在立即执行函数(IIFE)或普通函数内声明:例如
(() => { const _cache = new Map(); })(),这样_cache完全不可被模板访问 - 在事件处理函数、
onMounted回调等生命周期钩子中定义临时状态,避免提升到顶层 - 把逻辑抽离成独立的组合式函数(composable),内部变量天然封闭,只通过返回值可控暴露
命名要带上下文,不靠前缀猜用途
别写 data、res、list 这类泛化名,也别依赖 _userList 暗示“私有”。清晰的命名本身就是一种文档:
- 接口响应数据用
userListResponse或fetchedUsers,区分于本地计算的filteredUserList - 分页参数明确写成
currentPage、itemsPerPage,而不是page、size - 方法名动词前置,体现行为意图:
fetchUserList、resetFilters、validateForm
用 defineExpose 精确控制对外接口
如果组件需要被父组件调用方法或读取状态,不要让所有顶层变量都“被动暴露”。只显式暴露真正需要的部分:
- 写
defineExpose({ refresh: fetchUserList, isLoading }),父组件只能访问这两个成员 - 避免暴露原始
ref对象(如userList),改用计算属性或只读包装:defineExpose({ userList: readonly(userList) }) - 不暴露的变量,即使名字再“公共”,也不会出现在父组件的
$refs上
借助 TypeScript 强化边界意识
TypeScript 本身不解决暴露问题,但能帮你提前发现误用:
- 为
defineProps和defineEmits写完整类型,让 IDE 提示哪些 props 是合法输入、哪些事件可被监听 - 对内部工具函数加
private注释(虽无运行时效果),配合团队 Code Review 形成习惯 - 在组合式函数中使用
const+ 明确返回类型,避免意外修改闭包外的状态
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










