解决问题
大约 2 分钟
Vue2.7 存在的问题
TS 支持不友好
2.7 加入了组合式 API 的写法,同时也支持 TS,但是 2.7 对 TS 的支持并不友好,2.7 不能定义插槽参数的类型,这导致如果直接解构 slotProps
的话,row
的类型为 any,读取 row
中的属性会导致编辑器报错。
下列代码在 webstorm 中会出现 “未解析的变量 itemTitle” 的报错,虽然运行没有问题,但是很影响开发体验。
<template #default="{ row }">
{{ row.itemTitle }}
</template>
访问路由不方便
此外,由于在 2.7 中使用组合式写法,但是 vue-router
又没有提供 useRouter
和 useRoute
这两个 API。
useRouter
我们可以像 Vue2 一样导入 router 对象来使用,但是 useRoute
没有很好的替代品。既失去了 $route
的写法,又不能使用 useRoute
,那我们如何获取路由信息呢?
我们可以使用 getCurrentInstance()
解构出一个 proxy
对象,通过 proxy.$route
可以访问路由信息。
警告
如果想要观察 route 的变化,必须监听 proxy.$route
。
import { watch, getCurrentInstance } from "vue"
const { proxy }: any = getCurrentInstance()
// 这种方式获取的 route 是一个固定值,它将不会变化
const route = getCurrentInstance()?.proxy.$route!
watch(() => proxy.$route, route => {
// 可以监听 route 的变化
})
watch(() => route, route => {
// !!不能监听 route 的变化
})
立即监听导致的引用问题
在 watch 中使用了后面定义的响应式数据,并开启立即监听,出现 Cannot access 'searchForm' before initialization
的报错。
const status = ref("1")
watch(status, status => {
search(status)
}, {
immediate: true
})
const searchForm = reactive({ /* some params */ })
async function search(status: string) {
await apiSearch({
...searchForm, // Cannot access 'searchForm' before initialization
status
})
}
如果是一个普通数据,就不会出现报错。
const status = ref("1")
watch(status, () => {
console.log(searchForm)
}, {
immediate: true
})
const searchForm = {
/* some params */
}
结论:开启立即监听时,不能在 watch 中引用定义在其之后的响应式数据,但是可以引用普通数据。