众所周知,在 vue中,如果想定义一个全局变量的方法很简单,直接在 vue的原型上挂载属性或者方法即可。

但是,加上了typescript之后, Vue.prototype.$xxx = xxx  这种挂载方式就不行了。无论在哪里都访问不了挂载的内容。Vue原型上也没有。那怎么办呢?

第一种方式(推荐):插件

官方文档在 TypeScript 支持 这一项中的  增强类型以配合插件使用  表示了可以用插件的方式来定义全局变量,然后用 xxx.d.ts 这种文件来声明类型。

那就开始开发插件:官方开发插件说明

插件最重要的就是 install 方法。举个最简单的例子:

testInstall.ts

const protoInstall = {
install: (Vue:any,options:any) => {
Vue.prototype.$install = function(){
console.log('install')
};
Vue.prototype.$testData = 'testData';
}
} export default protoInstall;

(1)不要说我Vue:any,options:any 这种写法,因为我不知道这两个的类型到底是什么ヾ(。 ̄□ ̄)ツ゜゜゜

main.ts

import hhInstall from './assets/js/testInstall';

Vue.use(hhInstall);

使用的时候:

结果:

(1)可以看到,虽然报未找到该属性,或者该方法的错误,但是不影响结果。

(2)那怎么解决这个问题呢?这时就需要添加 声明文件了。

解决:

(1)在src 下新建一个 xxx.d.ts 文件  。我是在src下再新建一个type文件夹,然后再把刚才的声明文件放到 这文件夹中,方便管理。

(2)xxx 名称可以随便写,反正我写的 vue-prototype.d.ts  更清晰一点。

vue-prototype.d.ts

declare module "vue/types/vue" {
interface Vue {
$testData:string;
$install:Function;
}
}

保存后,如果未生效,再重新启动一下项目就行。然后就有类型提示了。以后如果还需要添加全局属性或者方法,在插件里面挂载之后,声明文件里面再添加类型说明。

不过我有不明白的地方:

(1) 官方文档说,确保在声明补充的类型之前导入 'vue'。我的声明文件 vue.prototype.d.ts 并未导入vue,但是没问题。为什么呢?难道是我用vue-cli3 脚手架搭建的项目,shims-vue.d.ts 这个文件已经导入就不用了吗?

(2) 这种 xxx.d.ts 文件,vue内部是怎么识别的?又是怎么处理的呢?

第二种方法:mixin混入

由于是想全局定义属性和方法,那么mixin也能实现。比如:

main.ts

const vueMixins = {
data(){
return {
$testData:'mixin testData',
}
},
methods:{
$install:function(){
console.log('mixin install')
}
}
}
Vue.mixin(vueMixins)

使用:

 结果:

可以看到,定义的属性 $testData 是undefined。而去看vue实例,发现挂载到 $data 里面的。但是为什么访问不了,而只有 通过  this.$data.$testData  来访问?这个我也不太清楚

相同的,出现属性不存在的问题,还是要添加 声明文件来说明一下。

用这种方式,如果定义一个构造函数在data里面,后面的方法都没提示。不太方便。

最后贴上我自己的全局事件总线代码,就是为了不想用的时候还要引入,才知道了 typescript 不能直接定义全局变量的问题

ヾ(゚∀゚ゞ)

如果不想全局引入,那就不搞成插件的方式就行了,直接export default class xxx。

代码比较垃圾,轻喷。

assets/js/eventBus.ts

/**
* @desc 全局事件总线
*/ /**
* 事件信息接口
*/
interface EventItem {
name:string;
fun:Function;
} /**
* 判断是否存在已经绑定的事件接口
*/
interface JudgeStatus{
status:boolean;
index:number
} export class EventBusHandler{ private EventArr:EventItem[] = []; private static _instance: EventBusHandler; public static get instance(): EventBusHandler {
if (!EventBusHandler._instance) {
EventBusHandler._instance = new EventBusHandler();
}
return EventBusHandler._instance;
} /**
* 判断是否已经存在注册的事件
* @param eventName 事件名
*/
private judgeHadEventAlready(eventName: string):JudgeStatus{
let status = false;
let pos = -1;
this.EventArr.forEach((val,index) => {
if(val.name === eventName){
status = true;
pos = index;
}
})
return {
status:status,
index: pos
}
} /**
* 事件监听
* @param eventName 事件名
* @param func 回调函数
*/
public on(eventName: string, func: Function) {
const statusTarget = this.judgeHadEventAlready(eventName);
// 如果未监听过则添加进去
if (!statusTarget.status) {
this.EventArr.push({
name:eventName,
fun:func
})
}
} /**
* 事件触发
* @param eventName 事件名
* @param arg 传入的参数。如果想传多个参数,可把 arg:any 换成 ...arg:any[]
*/
public emit(eventName: string, arg:any) {
const statusTarget = this.judgeHadEventAlready(eventName);
if(statusTarget.status){
const func = this.EventArr[statusTarget.index].fun;
this.EventArr[statusTarget.index].fun = func;
func(arg);
}else{
console.warn('暂未监听:'+eventName+ '事件');
}
} /**
* 事件移除
* @param eventName
* @param func
*/
public remove(eventName: string) {
const statusTarget = this.judgeHadEventAlready(eventName);
if(statusTarget.status){
this.EventArr.splice(statusTarget.index,1);
}else{
console.warn('未监听:'+eventName+ '事件');
}
} } const EventBusFunc = {
install: (Vue:any,options:object) => {
Vue.prototype.$eventBus = EventBusHandler.instance;
}
} export default EventBusFunc;

声明文件:

import {EventBusHandler} from '@/assets/js/eventBus';

declare module "vue/types/vue" {
interface Vue {
$eventBus:EventBusHandler;
}
}

main.ts 引入: 

import EventBus from './assets/js/eventBus';

Vue.use(EventBus);

使用:

this.$eventBus.on('func',() => {})
this.$eventBus.emit('func','1111')
this.$eventBus.remove('func')

果然还是实践出真知,网上的大部分答案都不靠谱 (⊙﹏⊙)

vue + typescript,定义全局变量或者方法的更多相关文章

  1. vue当中设置全局变量的方法

    import fn from 'fn' Vue.prototype.fn = fn; 调用的时候 this.fn.way

  2. typescript 定义全局变量以及扩展原生js对象

    使用“declare global”操作即可. 项目根目录下新建myDeclareFile.d.ts declare global { interface Navigator { mediaSessi ...

  3. 【C++】【MFC】定义全局变量的方法

    在stafx.h 里面加extern CString place在stafx.app 里面加CString place

  4. vue定义全局变量和全局方法

    一.全局引入文件 1.先定义共用组件 common.vue <script type="text/javascript"> // 定义一些公共的属性和方法 const ...

  5. C/C++定义全局变量/常量几种方法的区别

    在讨论全局变量之前我们先要明白几个基本的概念: 1. 编译单元(模块):    在IDE开发工具大行其道的今天,对于编译的一些概念很多人已经不再清楚了,很多程序员最怕的就是处理连接错误(LINK ER ...

  6. C++定义全局变量/常量几种方法的区别

    在讨论全局变量之前我们先要明白几个基本的概念: 1. 编译单元(模块):    在IDE开发工具大行其道的今天,对于编译的一些概念很多人已经不再清楚了,很多程序员最怕的就是处理连接错误(LINK ER ...

  7. 在vue项目中 如何定义全局变量 全局函数

    如题,在项目中,经常有些函数和变量是需要复用,比如说网站服务器地址,从后台拿到的:用户的登录token,用户的地址信息等,这时候就需要设置一波全局变量和全局函数 定义全局变量 原理: 设置一个专用的的 ...

  8. 在 Vuejs 项目中如何定义全局变量 全局函数

    在 Vuejs 项目中如何定义全局变量 全局函数 在项目中,经常有些函数和变量是需要复用,比如说网站服务器地址,从后台拿到的:用户的登录 token, 用户的地址信息等,这时候就需要设置一波全局变量和 ...

  9. vue + typescript 项目起手式

    https://segmentfault.com/a/1190000011744210 2017-10-27 发布 vue + typescript 项目起手式 javascript vue.js t ...

随机推荐

  1. Elasticsearch系列---实现分布式锁

    概要 Elasticsearch在文档更新时默认使用的是乐观锁方案,而Elasticsearch利用文档的一些create限制条件,也能达到悲观锁的效果,我们一起来看一看. 乐观锁与悲观锁 乐观锁 E ...

  2. Docker安装Alibaba Nacos教程(单机)

    SpringCloudAlibaba实战教程系列 阿里巴巴Nacos官方文档 docker:官网 docker:镜像官网:镜像官网可以所有应用,选择安装环境:会给出安装命令,例如:docker pul ...

  3. SpringBoot中使用Fastjson/Jackson对JSON序列化格式化输出的若干问题

    来源 :https://my.oschina.net/Adven/blog/3036567 使用springboot-web编写rest接口,接口需要返回json数据,目前国内比较常用的fastjso ...

  4. 《数据分析实战:基于EXCEL和SPSS系列工具的实践》一1.4 数据分析的流程

    本节书摘来华章计算机<数据分析实战:基于EXCEL和SPSS系列工具的实践>一书中的第1章 ,第1.4节,纪贺元 著 更多章节内容可以访问云栖社区"华章计算机"公众号查 ...

  5. FreeRTOS-Qemu 实现三任务同步通信机制以及API信息

    1. 本次作业的考察要点: 作业地址:github.com/HustWolfzzb-Git/GCC/GDB/QEMU等工具的使用.FreeRTOS多任务同步和通信机制的掌握. 2. 编程作业: 在gi ...

  6. Spring LDAP的使用

    LDAP入门http://www.jianshu.com/p/7e4d99f6baaf Spring LDAP,是Spring的一个组件,实现对LDAP的操作. 在编程操作MySQL时,我们除了用JD ...

  7. CentOS 7 编译错误解决方法集合

    解决 error: the HTTP XSLT module requires the libxml2/libxslt 错误 yum -y install libxml2 libxml2-dev yu ...

  8. The 2019 Asia Nanchang First Round Online Programming Contest B Fire-Fighting Hero(阅读理解)

    This is an era of team success, but also an era of heroes. Throughout the ages, there have been nume ...

  9. libevent(六)http server

    客户端: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <signa ...

  10. msf的rpc和json-rpc,我该选择哪个?

    msf的rpc有两种调用方式,那么我们应该调用哪一个呢? 其中restful接口暂且不谈,这个rest api其实是简单对接了一下msf的后端数据库,这个自己也能读数据库来做,这个以后有时间再谈 首先 ...