vue3.0使用TypeScript 如何拓展一个方法并且this可以访问,不报错?

1.我们都知道,如果在vue2.0版本想要给vue原型链上面拓展一个方法,用如下方式:

main.ts中

1
2
3
4
5
6
7
8
9
10
import Vue from "vue";
function myProperty(param){
  console.log(param)
}
Vue.prototype.$myProperty= myProperty;//拓展的可以是一个字符串变量,可以是一个类的实例,此处示例用了一个function
new Vue({
  router,
  store,
  render: (h) => h(App),
}).$mount("#app");

然后在根目录下面新建一个以.d.ts结尾的文件

1
2
3
4
5
6
7
8
9
10
// 1. 确保在声明补充的类型之前导入 'vue'
import Vue from 'vue'
// 2. 定制一个文件,设置你想要补充的类型
//    在 types/vue.d.ts 里 Vue 有构造函数类型
declare module 'vue/types/vue' {
// 3. 声明为 Vue 补充的东西
  interface Vue {
    $myProperty: string
  }
}

我们试着在一个组件里面调用一下这个方法,看如下截图(是不是成功获得智能提示了):


image.png

以上方法,在vue2.0的官方文档都可以找到,我只是做了一下总结。

2.那么在近期更新的vue3.0且使用ts的项目中,我们该怎样拓展一个方法呢?

vue3.0使用typescript重构,而拓展方法的方式也更加规范

main.ts中

1
2
3
4
5
6
7
8
9
10
11
12
13
import { createApp,defineComponent } from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";

const instance = createApp(App);

instance.use(function (vue) {
  vue.config.globalProperties.$myProperty = "我是渣男"
})
instance.use(router);
instance.use(store);
instance.mount("#app")

然后我们在组件里面用this调用一下

image.png

报错了,ts告诉我们$myProperty这个属性不在ComponentPublicInstance这个类型上面,我们来看一下解决办法。

vue3的源码里面有这样一段。传送门

新建index.d.ts文件

1
2
3
4
5
6
7
import { createApp } from 'vue'
import { Router, createRouter } from 'vue-router'
declare module "@vue/runtime-core" {
  interface ComponentCustomProperties {
    $myProperty: string;
  }
}

我们再来调用一下


image.png

OK,完美解决,以上问题告一段落。

3.那么在setUp中如何使用全局的方法呢?

首先我们使用到一个3.0的api

  • getCurrentInstance() //顾名思义,这个方法返回的就是当前组件的实例

实际用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<script lang="ts">
import {
  ComponentInternalInstance,
  defineComponent,
  getCurrentInstance,
} from 'vue';

export default defineComponent({
  name: 'HelloWorld',
  setup() {
    const {proxy} = getCurrentInstance() as ComponentInternalInstance;
    proxy?.$myProperty;
  },
  props: {
    msg: String,
  },
});
</script>

说明一下为什么要用as ,因为vue的源码里面,getCurrentInstance()这个方法返回的是
ComponentInternamInstance | null

image.png

或者
不用解构赋值,用?.也可以

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<script lang="ts">
import {
  ComponentInternalInstance,
  defineComponent,
  getCurrentInstance,
} from 'vue';

export default defineComponent({
  name: 'HelloWorld',
  setup() {
    // const {proxy} = getCurrentInstance() as ComponentInternalInstance;
    // proxy?.$myProperty;
    const proxy = getCurrentInstance()?.proxy;
    proxy?.$myProperty
   
  },
  props: {
    msg: String,
  },
});
</script>

注意,拓展完类型之后一定要重启,要不然会报错!!!!!