chrome/browser
这两个是浏览器为插件开发提供的API,Chrome浏览器的变量名叫chrome
,火狐浏览器的变量名叫browser
代码提示
我用的编辑器是vscode,之前一直不明白怎么给这两个变量添加代码提示
最早尝试
最开始我想的是加一个全局变量,搜到可以在.eslintrc
配置中添加一个globals
,把变量名加进去,但后来发现这个东西跟代码提示没半毛钱关系。这是ESLint
的配置文件,它的功能只是代码检查。
问过插件开发的大佬,大佬只说导入Library啥的,当时的我亿脸懵逼。
typings
看了github上的各种插件,发现有一个@types/chrome
,typings
是TypeScript的定义管理器,描述命名空间、接口、变量等各种东西,@types/chrome
呢也就是别人写好的一个描述文件,去告诉编辑器我这里有个chrome
变量,它下面有哪些方法之类的。
使用npm安装
1
| npm install --save-dev @types/chrome
|
安装好后发现chrome
的代码提示有了,但只有chrome
,火狐浏览器的browser
依然没有。
自定义typings
前几天突发奇想,因为vue是可以自定义全局和实例变量的代码提示的,那么browser
也许能自定义,于是照着这个思路,搜了一下怎么新建一个描述,去“继承”chrome
其实非常简单,只需要创建个文件,比如我在src/typings/
下创建了一个browser.d.ts
。这里具体在哪个文件夹下无所谓,读取这个文件是在tsconfig.json
中配置的
1 2 3 4 5 6
| "include": [ "src/**/*.ts", "src/**/*.d.ts", ],
|
意思就是,加载src
目录下的包括所有文件夹中的.ts
、.d.ts
文件,所以只是创建在src
目录下就行
然后在这个文件里添加
1
| declare const browser : typeof chrome;
|
这样就有browser
变量了
添加vue变量
再新建一个vue.d.ts
,在里面添加
1 2 3 4 5 6 7 8 9
| import Vue from 'vue' declare module 'vue/types/vue' { interface Vue { $chrome: typeof chrome } interface VueConstructor { chrome: typeof chrome } }
|
更多详情可参考vue官网的说明:《TypeScript 支持》
以上,代码提示添加完成
使用示例
然后你就可以给Vue的chrome赋值,以background.ts
为例,里面封装了一个网络请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| import axios from 'axios'; import Vue from 'vue';
Vue.chrome = Vue.prototype.$chrome = chrome || browser;
Vue.chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) { const headers = typeof request.headers !== 'undefined' ? request.headers : { 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36' };
switch (request.type) { case 'get': axios.get(request.url, headers) .then(response => { sendResponse(response.data); }); break; case 'post': axios.post(request.url, request.data, headers) .then(response => { sendResponse(response.data); }); break; }
return true; });
|
然后popup.ts
中,也需要加入
1 2 3 4 5 6 7 8 9 10 11 12
| import Vue from 'vue'; import Popup from '@components/popup'; import '@styles/popup';
Vue.chrome = Vue.prototype.$chrome = chrome || browser;
export default new Vue({ components: { Popup }, render: h => h(Popup) }).$mount('#app');
|
在popup.vue
中使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| <template> <div> <h1>{{ title }}</h1> <span>{{ message }}</span> <input type="text" v-model="uid" value="" placeholder="输入UID"> <button @click="btn">请求数据测试</button> </div> </template>
<script lang="ts">
import { Vue, Component } from 'vue-property-decorator';
@Component export default class Popup extends Vue {
title = 'Popup'; message = ''; uid = '';
public btn() { if (this.uid === '') { this.message = '未输入UID'; return; }
this.$chrome.runtime.sendMessage({ type: 'get', url: `https://api.bilibili.com/x/web-interface/card?mid=${this.uid}&photo=1&jsonp=jsonp` }, (json) => { console.log(json); if (typeof json.data !== 'undefined') { this.message = `获取成功!昵称:${json.data.card.name},当前粉丝数:${json.data.card.fans}`; } }); } } </script>
|
其他细节可查看Github项目:Btools-vue
总结
如果typescript项目用到的某变量没有代码提示可在npm搜索@types/xxx
查找
typings完全可以手写,只是比较麻烦
为一个变量声明类型可以用typeof xxx
之前想到了在typings文件中声明,但不知道得用typeof,一直报错:namespace不能作为类型使用
更新
2021-07-06 更新,发现有一个插件API的包webextension-polyfill-ts,直接引入就可以用