As we all know, in vue, if you want to define a global variable method is very simple, you can directly mount attributes or methods on the prototype of vue.
However, with typescript added Vue.prototype $XXX = XXX is not a good way to mount. No matter where you are, you can't access the content. It's not on the Vue prototype either. Then what shall I do?
First way (recommended): plug in
Official documents in TypeScript support The enhanced type in this item indicates that the global variables can be defined by plug-in, and then the type can be declared by xxx.d.ts.
Start developing plug-ins: Official development plug-in description
The most important thing about plug-ins is the install method. Take the simplest example:
testInstall.ts
const protoInstall = { install: (Vue:any,options:any) => { Vue.prototype.$install = function(){ console.log('install') }; Vue.prototype.$testData = 'testData'; } } export default protoInstall;
(1) Don't talk about me Vue:any,options:any This way of writing, because I don't know what the two types are.  ̄□ ̄)ツ゜゜゜
main.ts
import hhInstall from './assets/js/testInstall'; Vue.use(hhInstall);
When using:
result:
(1) It can be seen that although the property is not found or the error of the method is reported, the result is not affected.
(2) How to solve this problem? You need to add a declaration file.
solve:
(1) Create a new xxx.d.ts file under src. I want to create a new type folder under src, and then put the declaration file in this folder for easy management.
(2) The name of xxx can be written at will. Anyway, my Vue prototype.d.ts is clearer.
vue-prototype.d.ts
declare module "vue/types/vue" { interface Vue { $testData:string; $install:Function; } }
After saving, if it does not take effect, restart the project. Then there's the type prompt. If you need to add global properties or methods in the future, after the plug-in is mounted, add the type description in the declaration file.
But I don't understand:
(1) The official documentation says make sure to import 'Vue' before declaring the supplementary type. My statement vue.prototype.d.ts did not import Vue, but no problem. Why? Is it the project that I built with vue-cli3 scaffold? The file shims-vue.d.ts has been imported, so it's unnecessary?
(2) How is this xxx.d.ts file recognized in vue? How to deal with it?
The second method: mixin
Because you want to define properties and methods globally, mixin can also be implemented. For example:
main.ts
const vueMixins = { data(){ return { $testData:'mixin testData', } }, methods:{ $install:function(){ console.log('mixin install') } } } Vue.mixin(vueMixins)
use:
Results:
As you can see, the defined property $testData is undefined. When you look at the vue instance, you find that it is attached to $data. But why can't we access it only through this.$data.$testData? I don't know that
In the same way, if there is a problem that the property does not exist, you need to add a declaration file to explain it.
In this way, if a constructor is defined in data, the following methods are not prompted. Not very convenient.
Finally, I pasted my own global event bus code, which is to be introduced when I don't want to use it. Then I learned that typescript can't directly define global variables
ヾ(゚∀゚ゞ)
If you don't want to import globally, you can just export default class xxx without plug-in.
Code is rubbish, spray lightly.
assets/js/eventBus.ts
/** * @desc Global event bus */ /** * Event information interface */ interface EventItem { name:string; fun:Function; } /** * Determine whether there is a bound event interface */ 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; } /** * Determine whether the registered event already exists * @param eventName Event name */ 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 } } /** * event listeners * @param eventName Event name * @param func Callback function */ public on(eventName: string, func: Function) { const statusTarget = this.judgeHadEventAlready(eventName); // Add if not monitored if (!statusTarget.status) { this.EventArr.push({ name:eventName, fun:func }) } } /** * Event triggered * @param eventName Event name * @param arg The parameter passed in. If you want to pass more than one parameter, you can arg:any Change to 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('Not monitored yet:'+eventName+ 'event'); } } /** * Event removal * @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('Not monitored:'+eventName+ 'event'); } } } const EventBusFunc = { install: (Vue:any,options:object) => { Vue.prototype.$eventBus = EventBusHandler.instance; } } export default EventBusFunc;View Code
Declaration document:
import from '@/assets/js/eventBus'; declare module "vue/types/vue" { interface Vue { $eventBus:EventBusHandler; } }
main.ts Introduction:
import EventBus from './assets/js/eventBus'; Vue.use(EventBus);
use:
this.$eventBus.on('func',() => {}) this.$eventBus.emit('func','1111') this.$eventBus.remove('func')
As expected, it is true that most of the answers on the Internet are not reliable