# 在 vue3 中 ts 的巧妙使用
# 技巧一 (取 ref 对象)
# 说明:
在获取组件的 ref 对象时,我们可以通过 <InstanceType<typeof 组件 ref>> 来给 ref 对象限制类型
# 作用:
在取到 ref 对象后,如果调用其组件内的方法,如果方法不存在会报错,增强代码安全性
# 注意:
子组件部分的 setup 写法如果用 script 标签方式,需要用 defineExpose 将方法暴露出去,否则父组件取不到子组件的方法 (官方文档有说,如果用 setup () 函数的方法就不用考虑)
# 用法
// 父组件
<template>
<div id="login">
<login-account ref="loginAccountRef"> </login-account>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import loginAccount from './cpns/login-account.vue'
// 拿到loginAccount组件的ref对象
const loginAccountRef = ref<InstanceType<typeof loginAccount>>()
</script>
// 子组件
<template>
<div>哈哈</div>
</template>
<script lang="ts" setup>
// 定义方法
// 点击登录触发
const loginAction = () => {
console.log('哈哈啊哈')
}
defineExpose({
loginAction
})
</script>
<style scoped></style>
# 技巧二(vuex)
# 说明:
直接使用 vuex 里的 store 对象时,我们取里面的 state 的值是 any 类型,这是我们可以用小技巧给他一些类型限制
# 作用:
在调用 vuex 里面的 state 时随意乱写调用名称会报错,只有接口定义过的才能调用,增加代码安全性
# 用法:
# 根模块的接口类型定义
// store/type.ts | |
import type { ILoginState } from './login/type' | |
// 根 state 的类型限制 | |
export interface IRootState { | |
name: string | |
password: string | |
} | |
interface IRootWithModule { | |
login: ILoginState | |
} | |
export type IStoreType = IRootState & IRootWithModule |
# 根模块
// store/index.ts | |
import { createStore, Store, useStore as useVuexStore } from 'vuex' | |
import login from './login/login' | |
import type { IRootState, IStoreType } from './type' | |
const store = createStore<IRootState>({ | |
state() { | |
return { | |
name: '', | |
password: '' | |
} | |
}, | |
mutations: {}, | |
getters: {}, | |
actions: {}, | |
modules: { | |
login | |
} | |
}) | |
// 给 useStore 出来的实例对象 store 加 ts 类型限制 | |
export function useStore(): Store<IStoreType> { | |
return useVuexStore() | |
} | |
export default store |
# 子模块的接口类型定义
// store/login/type.ts | |
export interface ILoginState { | |
token: string | |
userInfo: any | |
userMenus: any | |
} |
# 子模块
// store/login/login.ts | |
import { Module } from 'vuex' | |
// 导入类型接口 | |
import type { ILoginState } from './type' | |
import type { IRootState } from '../type' | |
const loginModule: Module<ILoginState, IRootState> = { | |
namespaced: true, | |
state() { | |
return { | |
token: '', | |
userInfo: {}, | |
userMenus: [] | |
} | |
}, | |
getters: {}, | |
mutations: {}, | |
actions: {} | |
} | |
} | |
export default loginModule |
# 在组件中用法
<template>
<div>
哈哈哈
</div>
</template>
<script setup lang="ts">
// 这里导入的useStore不是vuex的,而是我们自己定义的那个(我们给它加了类型限制)
import { useStore } from '@/store'
const store = useStore()
// 到这里我们就可以发现store的类型不是any了,而是我们定义的Store<IStoreType>类型
// 而且在下面取state的时候我们会发现有代码提示了,如果写了state里面没有的值,会报错
const userMenus = store.state.login.userMenus
console.log(userMenus)
</script>