Ref

基本

ref是可以接收一个泛型的
image.png

如果不传东西,默认就是any
image.png

组件实例

一般是用 ref 获取组件实例,然后调用组件里面的方法
image.png
但是传null的话,泛型默认就是null,ts认为null是没有任何东西的,因此没办法使用组件内的方法
image.png
解决方法是传入下面的:
image.png

泛型里面要传入的,是一个类型,而你不能这样传 ref<组件名>,因为组件名,不是类型,只是一个类的实例。

要获取这个组件的类型,可以通过 InstanceType 的方式,获取到这个组件对应的类型(实际上是拥有构造函数的实例)

简单的说,就是这样获取一个组件对应的类型。

Props

在.vue文件,使用Vue3 的 setup语法糖,标注props属性的类型,需要这样:

  1. <script setup lang="ts">
  2. import { PropType } from "vue"
  3. /** 定义父组件可以传入的 props */
  4. const props = defineProps({
  5. columnProps: {
  6. type: Object as PropType<youTypes>, // 这里可以放入你的类型
  7. required: true
  8. }
  9. })
  10. </script>

Vuex

vuex基本都是推导出来的,但最好指定一个接口类型
image.png

模块

定义模块
image.png

但是看到有报错,原因是Module要求你传入2个泛型
第一个S是state的类型
第二个是根的state的类型
image.png

两个类型,都可以自己定义接口就可以了。
你先写state里的变量,然后接口写上对应的类型就可以了。

如果类型太多,可以单独拎出来写在对应的 types.ts 文件里面(名字随你自己定),表示这里存放类型
image.png
然后导出这个接口

  1. /** VueX 中 登录模块的 state 类型 */
  2. export interface LoginState {
  3. userName:String
  4. }

最后引入

  1. import { Module } from "vuex";
  2. import { IRootState } from "../../types";
  3. import { LoginState } from "./type";
  4. const loginModule:Module<LoginState,IRootState> = {
  5. namespaced:true,
  6. state(){
  7. return {
  8. userName:""
  9. }
  10. }
  11. }
  12. export default loginModule

useStore() 重新封装

问题的产生

vuex对TS的支持不是很好,直接用useStore的时候,类型是any,同时也没有对应的代码提示

即便你像下图这样传入一个泛型,也还是有点问题,而且还要去引入一个类型
image.png

重新封装useStore

要改善这个问题,可以对useStore进行重新封装。
image.png

1、定义一个storeType类型,这类型是联合了 vuex根state接口,和模块中state的接口
image.png

  1. // .src/store/types.ts
  2. /** 定义 Vuex 根接口 */
  3. export interface IRootState {
  4. /** 是否显示全屏加载中 */
  5. isSpinning:boolean
  6. }
  7. /** 定义 Vuex 模块接口 */
  8. export interface IRootWithModules {
  9. // 以后这里定义各个模块的state变量
  10. }
  11. /** 定义 Vuex 总接口,为 根接口 & 模块接口 */
  12. export type IStoreType = IRootState & IRootWithModules

2、store/index.ts 中,引入storeType类型,并导出一个我们封装的useStore( ),它的返回值是store类型,泛型是那个联合类型
image.png
image.png

  1. // =================== 1、引入 ===================
  2. // 引入 vuex 的 createStore创建实例,和 useStore 使用Vuex方法
  3. import { createStore,useStore as useVuexStore } from "vuex"
  4. // 引入 Vuex实例类型
  5. import type { Store } from "vuex"
  6. // 引入我们定义的 根类型,和Vuex根+模块类型
  7. import type { IRootState,IStoreType } from "./types";
  8. // =================== 2、定义 Vuex 根 ===================
  9. /** Vuex 根 */
  10. const store = createStore<IRootState>({
  11. state() {
  12. return {
  13. isSpinning: true
  14. }
  15. }
  16. })
  17. export default store
  18. // =================== 3、重新定义 useStore 方法 ===================
  19. // 后面在 .vue 文件中,需要通过 import { useStore } from "@/store/" ,引入我们新定义的useStore,才能正确显示store及其模块的类型
  20. /** 新的 useStore 方法 */
  21. export function useStore():Store<IStoreType>{
  22. return useVuexStore()
  23. }

3、在要使用的组件中,引入我们封装的useStore,就有正确的提示了
image.png
image.png

4、如果后面还有什么模块,直接加到模块类型里面就可以了
image.png

模块

1、需要先定义模块里面state的类型(接口或类,优先接口)
image.png

2、模块中,引入类型 Module 和 根的state类型(根的也是自己定义的)

然后模块的类型就是 Module<泛型>,泛型里面第一个参数就是模块的state类型,第二个参数是vuex根的state类型
image.png

3、vuex根文件,放入模块
image.png

4、vuex 的useStore重新封装的,加入新的模块的类型,让别的地方可以自动识别
image.png