Vue进阶
一、keep-alive
1.核心作用和使用场景
1.作用
- 缓存组件实例:避免重复销毁和创建,保留组件状态(如
DOM结构、响应式数据、事件监听) - 提升性能:适用于需要频繁切换但状态需保留的组件(如
Tab页、表单填写页)
Taimili 艾米莉 ( 一款专业的 GitHub star 管理和github 加星涨星工具taimili.com )
艾米莉 是一款优雅便捷的 GitHub star 管理和github 加星 涨星工具,基于 PHP & javascript 构建, 能对github star fork follow watch 刷星管理和提升,最适合github 的深度用户
2.使用方式
js
体验AI代码助手
代码解读
复制代码
<template>
<keep-alive :include="['ComponentA', 'ComponentB']" :max="5">
<component :is="currentComponent"></component>
</keep-alive>
</template>
2.生命周期钩子变化
-
新增钩子(仅在被缓存的组件中触发)
- onActivated:组件被激活(插入DOM)时触发。
- onDeactivated:组件被停用(移除DOM)时触发
-
执行顺序:
- 首次加载:
onCreate->onMounted->onActivated - 切换离开:
onDeactivated - 再次进入:
onActivated - 彻底销毁:
onUnmounted
- 首次加载:
3.关键配置属性
1.include
- 匹配组件名称(name选项),仅缓存匹配的组件
- 支持字符串、正则、数组
js
体验AI代码助手
代码解读
复制代码
<!-- 缓存以 "Test" 开头的组件 -->
<keep-alive :include="/^Test/">
2.exclude
- 排除指定组件,优先级高于include
3.max
- 最大缓存实例数,超出时按LRU(最近最少使用)策略淘汰旧实例
- LUR原理:有限淘汰最久未访问的实例
4.高频面试题
1.keep-alive实现原理
-
缓存机制:通过Map或Object缓存组件vnode实例,渲染时直接从缓存中取
-
DOM处理:
- 该组件实例对应的整个 DOM 树会被从真实的文档流 (DOM tree) 中完全移除 (
detached) 。这就是为什么在页面检查器里看不到它的 DOM 了。 - 当这个组件再次被激活时,
keep-alive会从缓存中找到这个实例,直接复用这个组件实例(保留所有状态),并将它对应的 DOM 树重新插入 (attached) 到文档流中。
- 该组件实例对应的整个 DOM 树会被从真实的文档流 (DOM tree) 中完全移除 (
2.如何动态控制组件缓存
- 方案1:绑定动态include/exclude(响应式变量)
js
体验AI代码助手
代码解读
复制代码
<keep-alive :include="cachedComponents">
- 方案2:通过key强制重新渲染(改变key会销毁旧实例)
js
体验AI代码助手
代码解读
复制代码
<component :is="currentComponent" :key="componentKey">
3.keep-alive如何结合路由使用
- 搭配router-view
js
体验AI代码助手
代码解读
复制代码
<router-view v-slot="{ Component }">
<keep-alive>
<component :is="Component" v-if="$route.meta.keepAlive" />
</keep-alive>
<component :is="Component" v-if="!$route.meta.keepAlive" />
</router-view>
- 路由配置:通过meta字段标记需缓存的页面
js
体验AI代码助手
代码解读
复制代码
{ path: '/home', component: Home, meta: { keepAlive: true } }
4.缓存组件如何更新数据
- onActivated中刷新数据
js
体验AI代码助手
代码解读
复制代码
onActivated(() => {
fetchData(); // 重新请求数据
});
5.max属性的作用及淘汰策略
- 作用:避免内存无限增长,限制最大缓存实例
- 淘汰策略:LRU(最近最少使用),优先移除最久未被访问的实例
5.注意事项
- 组件必须设置name选项:否则include/exclude无法匹配
- 避免内存泄漏:及时清理不需要缓存的组件(如通过max或动态include)
- SSR不兼容:keep-alive仅在客户端渲染中生效
- 缓存组件的状态保留:表单内容等会被保留,需手动重置或通过key强制更新
6.实战实例
js
体验AI代码助手
代码解读
复制代码
<template>
<button @click="toggleComponent">切换组件</button>
<keep-alive :include="cachedComponents" :max="3">
<component :is="currentComponent" :key="currentComponent" />
</keep-alive>
</template>
<script setup>
import { ref } from 'vue';
import ComponentA from './ComponentA.vue';
import ComponentB from './ComponentB.vue';
const currentComponent = ref('ComponentA');
const cachedComponents = ref(['ComponentA', 'ComponentB']);
const toggleComponent = () => {
currentComponent.value = currentComponent.value === 'ComponentA' ? 'ComponentB' : 'ComponentA';
};
</script>
二、异步组件
1.核心概念与使用方式
1.定义异步组件
defineAsyncComponent函数(Vue3推荐方式)
js
体验AI代码助手
代码解读
复制代码
import { defineAsyncComponent } from 'vue';
const AsyncCom = defineAsyncComponent(() => import('./MyComponent.vue'));
- 动态
import()语法(结合构建工具如Webpack/Vite实现代码分割)
js
体验AI代码助手
代码解读
复制代码
const AsyncComp = defineAsyncComponent({
loader: () => import('./MyComponent.vue'),
loadingComponent: loadingSpinner, // 加载中组件
errorComponent: ErrorDisplay, // 错误组件
delay: 1000, // 延迟显示loading(防闪烁)
timeout, // 超时时间
})
2.Suspense组件
- 统一管理异步组件(如异步组件或异步setup函数):
js
体验AI代码助手
代码解读
复制代码
<template>
<Suspense>
<template #default>
<AsyncComp />
</template>
<template #fallback>
<div>Loading...</div>
</template>
</Suspense>
</template>
2.高频面试题
1.异步组件的核心作用
- 按需加载:减少初始包体积,提升首屏加载速度
- 性能优化:结合代码分割(
Code Spliting)动态加载非关键组件
2.如何配置异步组件的加载状态和错误处理?
loadingComponent:显示加载中的UI(如loading动画)errorComponent:加载失败时显示错误提示delay:延迟显示loading组件,避免快速加载时闪烁timeout:超时后触发错误组件
3.Suspense和异步组件的关系
- Suspense:内置组件,用于统一管理异步组件的加载状态(如多个异步组件并行加载)
- 异步组件:通过
defineAsyncComponent定义,由Suspense控制占位内容
4.如何实现组件加载失败后的重试逻辑
- 工厂函数返回Promise:在loader中捕获错误并重试
js
体验AI代码助手
代码解读
复制代码
const Async = defineAsyncComponent({
loader: () => import('./MyComponent.vue')
.catch(() => {
// 重试逻辑
return retryImport();
})
})
5.异步组件在路由懒加载中的应用
- Vue Router配置
js
体验AI代码助手
代码解读
复制代码
const router = createRouter({
route: [{
path: '/profile',
component: () => import('./Profile.vue'); // 直接动态导入
// 或使用defineAsyncComponent
component: defineAsyncComponent(() => import('./Profile.vue'))
}]
})
6.Vue3异步组件与Vue2的差异
- 语法差异:Vue3废弃
Vue.component('async-comp',() => import(...)),改用defineAsyncComponent - 功能增强:Vue3支持更细颗粒度的加载状态管理和
Suspense集成
3.底层原理优化
1.代码分割原理
- 构建工具(如webpack)将动态
import()的模块拆分为独立chunk,运行时按需加载
2.异步组件生命周期
- 加载阶段:触发loader -> 下载loader -> 初始化组件
- 缓存机制:已加载的组件实例会被缓存,避免重复加载
3.性能优化策略
- 预加载(prefetch) :通过Webpack魔法注释标记非关键资源
js
体验AI代码助手
代码解读
复制代码
() => import(/* webpackPrefetch: true */ './MyComponent.vue')
- 懒加载阈值:结合路由或用户行为预测延迟加载组件
4.注意事项
- 组件命名:异步组件需显式申明
name选项,以便调试和keep-alive匹配 - SSR限制:异步组件在服务端渲染中需特殊处理(如占位内容)
- 错误边界:结合
onErrorCaptured全局捕获异步组件错误 - 过度分割:避免过多小模块导致HTML请求激增
5.实战代码实例
js
体验AI代码助手
代码解读
复制代码
// 异步组件定义
const AsyncModal = defineAsyncComponent({
lodaer: () => import('./Modal.vue').catch((err) ==> {
console.log('加载失败,3s后重试...');
return new Promise(resolve => {
setTimeout(() => resolve(import('./Modal.vue')), 3000);
})
}),
loadingComponent: LoadingSpainner,
delay: 200,
timeout: 5000
});
// 在组合式API中使用
export default {
setup() {
const showModal = ref(false);
return { showModal, AsyncModal };
}
}
6.应用场景
- 大型应用模块懒加载:如管理后台的复杂表单/图表组件
- 条件渲染组件:用户交互后才加载的非必要组件(如弹窗)
- 路由级懒加载:结合Vue Router提升首屏性能
三、Vue-Router
1.Vue-Router 4.X核心变化
1.创建路由实例
js
体验AI代码助手
代码解读
复制代码
import { createRouter, createWebHistory } from 'vue-router';
const router = createRouter({
history: createWebHistory(), // 或 createWebHashHistory
routes: [...]
});
2.组合式API支持
- useRouter() :获取路由实例(替代
this.$router) - useRoute() :获取当前路由对象(替代
this.$route)
2.路由配置与核心概念
1.动态路由
js
体验AI代码助手
代码解读
复制代码
{ path: '/user/:id', component: User };
// 获取参数:route.params.id
2.嵌套路由
js
体验AI代码助手
代码解读
复制代码
{
path: '/parent',
component: Parent,
children: [
{ path: 'child', component: Child }
]
}
3.命名路由与编程式导航
js
体验AI代码助手
代码解读
复制代码
router.push({ name: 'user', params: { id: 1 } });
4.路由模式
createWebHistory():History模式(需服务器支持)createWebHashHistory():Hash模式createMemoryHistory():SSR或测试环境
5.重定向与别名
js
体验AI代码助手
代码解读
复制代码
{ path: '/home', redirect: '/' }
{ path: '/', alias: 'home' }
3.导航守卫
1.全局守卫
router.beforeEach((to, from, next) => { ... })router.afterEach((to, from) => { ... })router.beforeResolve()
2.路由独享守卫
js
体验AI代码助手
代码解读
复制代码
{
path: '/admin',
component: Admin,
beforeEnter: (to, from, next) => { ... }
}
3.组件内守卫
onBeforeRouteUpdate:路由参数变化onBeforeRouteLeave:离开组件前
js
体验AI代码助手
代码解读
复制代码
import { onBeforeRouteLeave } from 'vue-router';
export default {
setup() {
onBeforeRouteLeave((to, from, next) => {
// 清理逻辑
next();
});
}
};
4.高级特性与最佳实践
1.路由懒加载
js
体验AI代码助手
代码解读
复制代码
const User = () => import('./User.vue');
const User = defineAsyncComponent(() => import('./User.vue'));
2.路由元信息(meta)
js
体验AI代码助手
代码解读
复制代码
{ path: '/profile', meta: { requireAuth: true } }
// 在导航守卫中访问:to.meta.requiresAuth
3.动态路由
- 添加路由:
router.addRoute({ path: '/new', component: New }) - 删除路由:
router.removeRoute('route-name')
4.路由组件传参
js
体验AI代码助手
代码解读
复制代码
{ path: '/user/:id', component: User, props: true }
// 组件通过props:['id'] 接收
5.滚动行为控制
js
体验AI代码助手
代码解读
复制代码
const router = createRouter({
scrollBehavior(to, from, savedPosition) {
return savedBehavior || { top: 0 };
}
});
5.高频面试题
1.Vue-Router 4.X 与 3.X 的主要区别
- API命名调整(如
new VueRouter() -> createRouter()) - 组合式API支持(
useRouter/useRoute) - 动态路由API优化(
addRoute/removeRoute)
2.如何实现路由权限控制
- 全局守卫 + 元信息
js
体验AI代码助手
代码解读
复制代码
router.beforeEach((to, from, next) => {
if(to.meta.requireAuth && !isAuthenticated) next('/login');
else next();
});
3.如何处理动态路由加载顺序问题
router.isReady():确保初始路由解析完成再挂载应用
js
体验AI代码助手
代码解读
复制代码
router.isReady().then(() => app.mount('#app'));
4.如何捕获导航错误
js
体验AI代码助手
代码解读
复制代码
router.onError((error) => {
console.error('导航错误', error);
});
5.路由组件如何复用并响应参数变化
onBeforeRouteUpdate:监听路由参数变化
js
体验AI代码助手
代码解读
复制代码
onBeforeRouteUpdate((to, form, next) => {
fetchData(to.params.id);
next();
})
6.实战场景示例
js
体验AI代码助手
代码解读
复制代码
// 动态添加路由(权限控制)
const dynamicRoutes = [
{ path: '/admin', component: Admin, meta: { role: 'admin' } }
];
if (user.role === 'admin') {
dynamicRoutes.forEach(route => router.addRoute(route));
}
// 路由懒加载与预加载(webpack魔法注释)
const Home = () => import( /* webpackPrefetch: true */ './Home.vue' );
7.注意事项
- this.$router的兼容性:选项式API中仍可用,组合式API推荐useRouter
- SSR适配:需使用createMemoryHistory并处理客户端激活
- 路由命名冲突:动态路由添加时注意避免重复路径或名称
- 导航守卫异步处理:确保调用next()或返回Promise
四、状态管理
1、Vuex
1.Vuex核心概念与工作流程
1.核心角色
State:单一状态树,存储全局数据(响应式)Getter:基于State派生的计算属性(类似组件的computed)Mutation:同步修改State的唯一途径(通过commit触发)Action:处理异步操作,提交Mutations(通过dispatch触发)Modules:模块化拆分复杂Store 2.工作流程
js
体验AI代码助手
代码解读
复制代码
组件 -> dispatch(Action) -> Action -> commit(Mutation) -> Mutation -> 修改State -> 更新视图
3.Vue4.x对Vue3的支持
- 兼容Vue3的
Composition API,但核心API与Vuex 3.x一致 - 通过
useStore替代this.$store(组合式API中)
js
体验AI代码助手
代码解读
复制代码
import { useStore } from 'vuex';
export default {
setup() {
const store = useStore();
return { store };
}
};
2.核心API与使用
1.定义Store
js
体验AI代码助手
代码解读
复制代码
import { createStore } from 'vuex';
const store = createStore({
state: { count: 0 },
mutation: {
increment(state) { state.count++; }
},
actions: {
asyncIncrement({ commit }) {
setTimeout(() => commit('increment'), 1000);
}
},
getters: {
doubleCount: state => state.count * 2
}
});
2.组件中访问Store
- 选项式API:
this.$store.state.count或mapState/mapGetters辅助函数 - 组合式API:
const store = useStore(); store.state.count;
3.辅助函数
mapState / mapGetters:映射到计算属性- mapMutation / MapActions:映射到方法
js
体验AI代码助手
代码解读
复制代码
import { mapState, mapGetters, mapMutations, mapActions } from 'vuex';
export default {
computed: {
...mapState(['count']),
...mapGetters(['doubleCount'])
},
methods: {
...mapMutations(['increment']),
...mapActions(['asyncIncrement'])
}
};
3.模块化与命名空间
1.模块定义
js
体验AI代码助手
代码解读
复制代码
const moduleA = {
namespaced: true, // 启用命名空间
state: { ... },
mutation: { ... },
action: { ... }
};
const store = createStore({
modules: { a: moduleA }
});
2.命名空间访问
- 直接访问:
store.state.a.moduleData - 辅助函数
js
体验AI代码助手
代码解读
复制代码
...mapActions('a',['moduleAction']),
// 或通过createNamespacedHelpers
const { mapActions } = createNamespacedHelpers('a');
3.模块的局部上下文
- Root State:在模块的Action中通过rootState访问全局状态
- Root Commit:在模块Actions中通过
{ root: true }提交全局Mutation
js
体验AI代码助手
代码解读
复制代码
actions: {
localAction({ commit, dispatch, rootState }) {
commit('localMutation');
dispatch('gloabalAction', null, { root: true });
}
}
4.高级特性与最佳实践
1.严格模式
js
体验AI代码助手
代码解读
复制代码
const store = createStore({ strict: true });
// 直接修改state会抛出错误(仅限开发环境)
2.插件开发
- 订阅Mutations
js
体验AI代码助手
代码解读
复制代码
store.subscribe((mutation, state) => {
console.log('Mutation:', mutation.type);
});
- 持久化插件(如结合localStorage)
js
体验AI代码助手
代码解读
复制代码
const persistPlugin = (store) => {
store.subscribe((mutation, state) => {
localStorage.setItem('vuex-state', JSON.stringify(state));
});
};
3.动态注册模块
js
体验AI代码助手
代码解读
复制代码
store.registerModule('dynamicModule', { ... });
store.unregisterModule('dynamicModule', { ... });