Vue3 创建效率倍增指南:自动注册、懒加载、Suspense、Teleport、KeepAlive、VueUse 实战技巧一网打尽
1. 组件自动注册
在项目中,尤其是当公共组件数量增多时,逐个导入和注册会变得非常繁琐。组件自动注册可以让你在使用组件时无需单独引入,提升开发效率。
无需手动在每个页面 import MyComponent from '@/components/MyComponent.vue',自动全局注册。
借助 Vite 插件 unplugin-vue-components。
npm i -D unplugin-vue-components
然后在 vite.config.js 配置:
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
export default {
plugins: [
Components({
resolvers: [ElementPlusResolver()], // 自动引入 ElementPlus 组件
dirs: ['src/components'], // 自动导入的目录
}),
],
}
这样就可以直接使用:
2. 图片懒加载自定义指令(v-lazy)
只在图片即将进入可视区域时才加载,提升性能。
核心原理:
利用现代浏览器提供的 IntersectionObserver API,它可以高效地监听一个元素是否进入了可视区域,避免了传统监听scroll事件带来的性能问题。
实现步骤:
- 创建自定义指令:定义一个指令(例如 v-lazy),在它的 mounted 钩子函数中,创建一个IntersectionObserver实例来观察绑定的元素(通常是<img>标签)。
- 监听交叉状态:当元素进入可视区时,IntersectionObserver的回调函数会被触发。
- 加载真实图片:在回调函数中,将预先存储在data-src等自定义属性中的真实图片URL赋值给元素的src属性,从而触发图片加载。
- 停止观察:图片加载后,应停止对该元素的观察,以节省资源。
// directives/lazy.js
export default {
mounted(el, binding) {
const observer = new IntersectionObserver(([entry]) => {
if (entry.isIntersecting) {
el.src = binding.value
observer.unobserve(el)
}
})
observer.observe(el)
},
}
注册后使用:
![lazy]()
注意一定要设置图片的占位符,防止页面出现抖动。
3. 动态 CSS 变量,动态 Class
方便实现主题切换、动态配色、响应式样式变化。
动态 CSS 变量
<script setup>
import { ref } from 'vue'
const themeColor = ref('#42b983') // 初始绿色
const size = ref(100) // 初始大小100px
const toggleColor = () => {
themeColor.value = themeColor.value === '#42b983' ? '#e91e63' : '#42b983'
}
const increaseSize = () => {
size.value += 20
}
const decreaseSize = () => {
size.value = Math.max(60, size.value - 20)
}
</script>
动态 Class
<script setup>
import { ref } from 'vue';
const changeColor = ref(false);
</script>
4. “加载协调员”(Suspense)
在组件中有异步内容(如异步组件、async setup、await 数据请求)时,
在等待它们加载完成之前,用「备用内容(fallback)」进行占位。
加载中...
4.1. 使用示例
正在加载用户数据,请稍候...
<script setup>
import UserInfo from './UserInfo.vue'
</script>
UserInfo.vue
欢迎回来,{{ user.name }}
年龄:{{ user.age }}
<script setup>
import { ref } from 'vue'
// 模拟异步请求
const user = ref(null)
await new Promise(resolve => setTimeout(resolve, 2000)) // 模拟网络延迟
user.value = {
name: '小明',
age: 25,
}
</script>
当 <UserInfo> 内部的异步逻辑(例如数据请求)还没完成时,
Vue 会先显示 fallback 部分的内容。
等异步逻辑完成后,再切换显示 default 部分。
4.2. 可以协调哪些异步内容?
异步来源 | 示例 |
异步组件( ) |
|
|
|
内部有异步子组件 |
|
异步数据获取 |
|
4.3. 使用注意点
<Suspense>只会等待setup()内部的异步任务:如果你在onMounted中请求数据,它不会等待。因为组件已经“挂载”了。
const data = await fetchData() // 放在 setup 里
- 不能包裹多个根节点:default、fallback 模板都必须有且只有一个根节点。
- 可嵌套使用:外层 Suspense 可以等待内层多个 Suspense。
5. 组件传送(Teleport)
Vue 默认组件内容渲染在父组件 DOM 树内。
<Teleport> 可以把某个组件的内容挂载到指定 DOM 节点(如 body、模态框容器等)。
简单来说:<Teleport> 是一个内置组件,它可以将一个组件的模板内容“传送”到DOM树的另一个位置,而该组件的逻辑关系(父子关系、props和事件)保持不变。
典型应用场景:模态框 / 弹窗、Toast 通知、全局 Tooltip / Popover、下拉菜单
to:CSS 选择器或 DOM 元素- 内部内容会移动到目标位置,但逻辑仍属于当前组件
5.1. 使用示例
<script setup>
import { ref } from 'vue'
const showModal = ref(false)
</script>
5.2. 特性
- 保持响应式:传送后依然可以访问父组件的数据和方法。
- 解决层级问题:模态框、弹出菜单不受父容器
overflow: hidden或 z-index 限制。 - 支持条件渲染可以配合
v-if、v-show使用。 - 支持 DOM 选择器和元素
...
6. 组件缓存(KeepAlive)
Vue 默认情况下,组件被切换或卸载时会销毁:DOM 元素被移除、setup 或 data 中的状态丢失
<keep-alive> 可以:缓存被包裹的动态组件、下次切换回来时,状态、DOM、滚动位置等依然保留
简单来说:<KeepAlive> 是一个内置组件,用于在多个动态组件之间切换时,缓存非活动组件的实例,而不是销毁它们。
常用场景:tab 切换页、列表分页、多页面 SPA 的高频组件
6.1. 使用示例
<script setup>
import { ref } from 'vue'
import TabA from './TabA.vue'
import TabB from './TabB.vue'
const currentTab = ref('TabA')
const handleChangeTab = (tab) => {
console.log(tab)
currentTab.value = tab
}
// 组件映射
const components = {
TabA,
TabB,
}
</script>
Tab A
输入值:{{ text }}
<script setup>
import { ref } from 'vue'
const text = ref('')
</script>
Tab B
计数:{{ count }}
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
6.2. 属性介绍
属性 | 说明 |
| 缓存指定组件,支持字符串、正则 |
| 不缓存指定组件 |
| 最多缓存组件数量,超出会按 LRU(最近最少使用)策略清理 |
生命周期 | 被缓存组件有额外生命周期钩子: |
6.3. 总结
结合 onActivated / onDeactivated 做额外逻辑
import { onActivated, onDeactivated } from 'vue'
onActivated(() => console.log('组件被激活'))
onDeactivated(() => console.log('组件被停用'))
性能优化:对于大量组件可以配合 max 控制缓存数量
动态组件 + 路由:<RouterView> 也可以包裹 <keep-alive> 缓存路由页面
一句话:<keep-alive> = 组件缓存器,切换时不销毁组件,保留状态和 DOM,让用户体验更流畅。
7. 用 VueUse 库提升开发效率
VueUse 是一个基于 Vue 组合式 API 的高质量、高性能的工具函数集合。它提供了大量开箱即用的组合式函数(Composables),可以极大简化常见功能的开发,让你专注于业务逻辑。
VueUse的优势:
- 功能全面:涵盖浏览器API、状态、传感器、动画、DOM操作等多个方面。
- 按需引入:完全支持摇树优化(Tree-shaking),只会打包你用到的函数。
- 兼容性好:一个包即可同时支持 Vue 2 和 Vue 3。
常用函数举例:
- useClipboard():轻松实现复制到剪贴板功能。
- useStorage():便捷地操作localStorage或sessionStorage,并保持响应式。
- useTitle():响应式地修改页面标题。
- useDebounceFn() / useThrottleFn():快速实现防抖和节流功能。
- useIntersectionObserver():封装了IntersectionObserver,可用于实现懒加载等功能。
浙公网安备 33010602011771号