Vue 3.3带来了很多新特性,但实战中也有很多坑。
本文分享我在Vue 3.3+实战中踩过的坑,包括Composition API、响应式、组件通信、TypeScript、构建部署,以及解决方法。
一、我的Vue 3经历
1. 从Vue 2到Vue 3
我从Vue 2转到Vue 3,经历了一个适应过程。
- Vue 2用Options API
- Vue 3推荐Composition API
- 刚开始不习惯
- 慢慢发现Composition API的好处
- 现在已经离不开了
Vue 3,是一次大的升级。
2. Vue 3.3的新特性
Vue 3.3带来了很多新特性:
- defineProps支持泛型
- defineEmits更简洁
- defineOptions
- 响应式props解构
- 更好的TypeScript支持
这些新特性,让开发更高效。
3. 踩过的坑
但实战中,我踩过很多坑。
- 响应式的坑
- 组件通信的坑
- TypeScript的坑
- 构建部署的坑
- 性能优化的坑
每个坑,都是一次学习。
二、Composition API的坑
1. 坑一:setup中this不可用
第一个坑:setup中this不可用。
- Vue 2中用this
- Vue 3的setup中没有this
- 刚开始很不习惯
- 不知道怎么获取实例
- 后来学会了用getCurrentInstance
解决方法:
import { getCurrentInstance } from 'vue'
const instance = getCurrentInstance()
// instance.proxy 相当于this但不建议滥用,大部分情况不需要this。
2. 坑二:ref和reactive分不清
第二个坑:ref和reactive分不清。
- 什么时候用ref
- 什么时候用reactive
- 刚开始很混乱
- 后来总结了规律
我的经验:
- 基本类型用ref
- 对象类型用reactive
- 但ref也可以包对象
- 统一用ref也可以
- 关键是要一致
3. 坑三:ref需要.value
第三个坑:ref需要.value。
- 在script中要写.value
- 在template中不用
- 经常忘记写.value
- 导致bug
解决方法:
- 养成习惯
- 用TypeScript提示
- 用unref统一处理
- 用reactive避免.value
4. 坑四:reactive解构丢失响应式
第四个坑:reactive解构丢失响应式。
const state = reactive({ count: 0 })
const { count } = state // 丢失响应式- 解构后就不是响应式了
- 刚开始不知道
- 后来学会了用toRefs
解决方法:
import { toRefs } from 'vue'
const { count } = toRefs(state)Vue 3.3的响应式props解构,也是类似的原理。
三、响应式的坑
1. 坑一:直接替换reactive对象
第一个坑:直接替换reactive对象。
const state = reactive({ list: [] })
state.list = newList // 可以
state = reactive({ list: newList }) // 不行,丢失响应式- reactive不能直接替换整个对象
- 只能替换属性
- 刚开始犯过这个错
解决方法:
- 用ref包对象
- 或者替换属性
- 不要替换整个reactive对象
2. 坑二:数组的响应式
第二个坑:数组的响应式。
- Vue 2中数组的某些方法不触发更新
- Vue 3中用Proxy解决了
- 但直接用索引修改还是有问题
- 要用splice或数组方法
Vue 3的响应式,比Vue 2好多了,但也要注意。
3. 坑三:watch的坑
第三个坑:watch的坑。
- watch监听ref
- watch监听reactive
- 深度监听
- 立即执行
- 刚开始参数搞不清
我的经验:
// 监听ref
watch(count, (newVal, oldVal) => {})
// 监听reactive的属性
watch(() => state.count, (newVal, oldVal) => {})
// 深度监听
watch(state, callback, { deep: true })
// 立即执行
watch(source, callback, { immediate: true })4. 坑四:computed的坑
第四个坑:computed的坑。
- computed默认是只读的
- 要写可写的computed需要get和set
- 刚开始不知道
- 直接赋值报错
解决方法:
const fullName = computed({
get: () => firstName.value + ' ' + lastName.value,
set: (val) => {
const [first, last] = val.split(' ')
firstName.value = first
lastName.value = last
}
})四、组件通信的坑
1. 坑一:props的坑
第一个坑:props的坑。
- props是只读的
- 不能直接修改
- 要通过emit修改
- 刚开始直接改props
- 控制台报警告
解决方法:
- 用computed包装
- 用emit通知父组件
- 用v-model
- 不要直接改props
2. 坑二:defineProps和withDefaults
第二个坑:defineProps和withDefaults。
Vue 3.3中:
const props = defineProps<{
name: string
age?: number
}>()
const props = withDefaults(defineProps<{
name: string
age?: number
}>(), {
age: 18
})- 刚开始不知道withDefaults
- 不知道怎么设默认值
- 后来学会了
3. 坑三:defineEmits
第三个坑:defineEmits。
Vue 3.3中更简洁:
const emit = defineEmits<{
(e: 'update', value: string): void
(e: 'close'): void
}>()- 类型声明方式
- 刚开始不习惯
- 后来觉得很好用
4. 坑四:provide/inject
第四个坑:provide/inject。
- 跨层级通信
- 但调试困难
- 不知道数据从哪来
- 容易出问题
我的建议:
- 简单场景用provide/inject
- 复杂场景用状态管理
- 不要滥用
- 保持数据流清晰
五、TypeScript的坑
1. 坑一:ref的类型
第一个坑:ref的类型。
const count = ref<number>(0)
const user = ref<User | null>(null)- ref要指定类型
- 特别是可能为null的
- 刚开始不指定
- 后来发现类型推断有问题
2. 坑二:reactive的类型
第二个坑:reactive的类型。
interface State {
count: number
list: Item[]
}
const state = reactive<State>({
count: 0,
list: []
})- reactive最好指定接口
- 类型更清晰
- 代码更可维护
3. 坑三:组件的类型
第三个坑:组件的类型。
- 组件的props类型
- 组件的emits类型
- 组件的实例类型
- 刚开始搞不清
Vue 3.3改进了很多,类型推导更好了。
4. 坑四:模板中的类型
第四个坑:模板中的类型。
- 模板中没有类型检查
- 写错了不知道
- 要用Volar插件
- 开启模板类型检查
工具,能帮你避免很多坑。
六、构建部署的坑
1. 坑一:vite配置
第一个坑:vite配置。
- Vue 3推荐用Vite
- Vite配置和webpack不同
- 刚开始不习惯
- 别名、代理、环境变量
- 都要重新学
Vite,是新的构建工具,需要学习。
2. 坑二:环境变量
第二个坑:环境变量。
- Vite中环境变量要以VITE_开头
- 用import.meta.env访问
- 和webpack的process.env不同
- 刚开始不知道
解决方法:
// .env
VITE_API_URL=https://api.example.com
// 代码中
const apiUrl = import.meta.env.VITE_API_URL3. 坑三:打包优化
第三个坑:打包优化。
- 代码分割
- 懒加载
- 预加载
- 压缩
- CDN
打包优化,是性能的关键。
4. 坑四:部署的坑
第四个坑:部署的坑。
- 路由history模式的404问题
- 静态资源路径
- 跨域问题
- 缓存问题
部署,也有很多坑。
七、性能优化的坑
1. 坑一:不必要的重渲染
第一个坑:不必要的重渲染。
- 父组件渲染,子组件都渲染
- 大列表性能差
- 要用v-memo
- 要用shallowRef
- 要合理拆分组件
性能优化,是Vue开发的必修课。
2. 坑二:大列表
第二个坑:大列表。
- 大量数据渲染慢
- 要用虚拟列表
- 要用分页
- 不要一次渲染太多
大列表,是性能的杀手。
3. 坑三:computed滥用
第三个坑:computed滥用。
- 什么都用computed
- 其实有些用方法就行
- computed有缓存
- 但也有开销
- 合理使用
computed,不是越多越好。
4. 坑四:watch滥用
第四个坑:watch滥用。
- 什么都用watch
- 其实可以用computed
- 可以用v-model
- 可以用事件
- 不要滥用watch
watch,要谨慎使用。
八、我的经验总结
1. 仔细看文档
第一个经验:仔细看文档。
- Vue文档写得很好
- 新特性先看文档
- 理解原理再用
- 不要想当然
- 文档会告诉你坑在哪里
文档,是最好的老师。
2. 用TypeScript
第二个经验:用TypeScript。
- TypeScript能发现很多问题
- 类型提示很方便
- 重构更安全
- 代码更可维护
- 强烈推荐
TypeScript,是Vue 3的好搭档。
3. 用Volar
第三个经验:用Volar。
- Volar是Vue 3的官方VS Code插件
- 类型提示
- 模板检查
- 自动补全
- 很好用
工具,能提高效率。
4. 组件拆分
第四个经验:合理拆分组件。
- 组件不要太大
- 职责单一
- 可复用
- 可测试
- 好的组件结构
组件拆分,是好代码的基础。
5. 状态管理
第五个经验:合理的状态管理。
- 简单场景用props/emit
- 跨层级用provide/inject
- 复杂场景用Pinia
- 不要什么都用全局状态
- 保持数据流清晰
状态管理,是架构的核心。
九、写在最后
Vue 3.3+实战,那些年我踩过的坑。
Composition API的坑:setup中没有this、ref和reactive分不清、ref需要.value、reactive解构丢失响应式。响应式的坑:直接替换reactive对象、数组的响应式、watch和computed的坑。组件通信的坑:props只读、defineProps和withDefaults、defineEmits、provide/inject。TypeScript的坑:ref和reactive的类型、组件类型、模板类型。构建部署的坑:vite配置、环境变量、打包优化、部署。性能优化的坑:不必要的重渲染、大列表、computed和watch滥用。
2023年了,Vue 3已经很成熟了,Vue 3.3带来了很多改进。但不管版本怎么变,核心的开发经验是不变的:理解原理、写好代码、注意性能、持续学习。踩坑不可怕,可怕的是不从坑中学习。
最后,用一句话总结:"Vue 3的坑,大多是因为不理解原理。理解了原理,就能避开大部分坑。仔细看文档,用TypeScript,用Volar,合理拆分组件,你也能写出好的Vue代码。"
希望我的经验,能帮你少踩一些坑。
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录