深度解析 Vue.use() 的执行时机
在开发 Vue 2 项目时,大家肯定都写过 Vue.use(VueRouter) 或 Vue.use(Vuex)。但你有没有注意过,这个“插件安装”的语句,有人写在 main.js 里,有人写在 router/index.js 里。即便在 main.js 中先 import router 后执行 Vue.use,程序居然也能正常运行。难道 new VueRouter() 不需要插件先安装吗?为什么
前言
在开发 Vue 2 项目时,大家肯定都写过 Vue.use(VueRouter) 或 Vue.use(Vuex)。但你有没有注意过,这个“插件安装”的语句,有人写在 main.js 里,有人写在 router/index.js 里。
最诡异的是:即便在 main.js 中先 import router 后执行 Vue.use,程序居然也能正常运行。
难道 new VueRouter() 不需要插件先安装吗?为什么 Vuex 却严格要求顺序?今天我们就由浅入深,拆解这背后的 ES6 模块机制与 Vue 插件底层逻辑。
一、 两种写法之争
写法 A:高度封装型(Vue CLI 官方推荐)
在这种写法中,我们将插件的“安装”和“配置”全封装在 index.js 内部。
codeJavaScript
// router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
// 1. 先安装插件
Vue.use(VueRouter)
// 2. 后创建实例并暴露
export default new VueRouter({
routes: [ /* ... */ ]
})
写法 B:集中管理型
在这种写法中,开发者习惯在入口文件 main.js 中统一安装所有插件。
codeJavaScript
// main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router' // 此时会触发 router/index.js 执行
// 插件安装写在引入之后
Vue.use(VueRouter)
new Vue({
router,
render: h => h(App)
}).$mount('#app')
二、 深度质疑:执行顺序真的对吗?
我们知道,ES6 的 import 具有提升(Hoisting)特性。在写法 B 中,实际的执行逻辑是这样的:
-
浏览器解析 main.js,发现 import router,立即“闪现”到 router/index.js。
-
在 index.js 中,new VueRouter() 被执行。
-
index.js 执行完毕,回到 main.js。
-
此时才开始执行 Vue.use(VueRouter)。
结论: 在写法 B 中,“创建路由器实例”其实早于“安装路由器插件”。
那么问题来了:既然插件还没安装,为什么 new VueRouter() 不报错?
三、 破案:VueRouter 的“宽容”与 Vuex 的“严谨”
1. VueRouter 的设计哲学
VueRouter 在执行 new VueRouter() 时,其内部主要是在做一件工作:解析路由映射表。这是一个纯 JavaScript 的逻辑计算过程,它在此时并不强依赖 Vue 的核心功能。
VueRouter 真正的“绑定”动作,是发生在 new Vue({ router }) 这一步。只要在根实例启动前完成了 Vue.use(),它就能通过混入(Mixin)机制把 $router 注入到所有组件中。所以,它允许“先上车,后买票”。
2. Vuex 的严格限制
如果你尝试对 Vuex 使用写法 B,你会直接得到一个红色的 Error:
[vuex] must call Vue.use(Vuex) before creating a store instance.
为什么 Vuex 这么“事儿”?
因为 Vuex 的核心是响应式状态管理。当你执行 new Vuex.Store() 时,Vuex 为了让 state 变成响应式的,它会立即在内部 new 一个隐藏的 Vue 实例。
如果此时 Vue.use(Vuex) 没执行,Vuex 就拿不到 Vue 的引用,响应式系统就无法建立。所以 Vuex 强制要求:必须先安装插件,才能创建实例。
四、 核心差异对比表
| 维度 | 写法 A (在 router 内部 use) | 写法 B (在 main.js 内部 use) |
| 执行顺序 | 严格遵循:先安装 -> 后实例化 | 潜在风险:先实例化 -> 后安装 |
| 模块化程度 | 高(路由逻辑自闭环) | 中(依赖外部环境安装) |
| Vuex 兼容性 | 完美支持 | 直接报错 |
| 复用性 | 拷贝文件到新项目即可运行 | 需手动在主文件补写 Vue.use |
| 推荐指数 | ⭐⭐⭐⭐⭐ | ⭐⭐ |
五、 最终建议:如何写出高质量代码?
为了代码的健壮性和一致性,建议大家养成以下习惯:
-
坚持“谁使用,谁负责”:
既然是 router/index.js 用到了 VueRouter,就应该在它内部 Vue.use(VueRouter)。这样保证了无论在什么情况下,插件一定是在实例创建前安装好的。 -
保持 main.js 的纯粹:
main.js 作为大管家,只负责引入成品(router 实例、store 实例)并挂载,不应该操心这些插件内部的安装细节。 -
避坑口诀:
Vue 插件要记牢,先 use 后 new 才算好。
Router 虽然管得松,Vuex 报错跑不了!
更多推荐


所有评论(0)