chrome/browser
这两个是浏览器为插件开发提供的API,Chrome浏览器的变量名叫chrome,火狐浏览器的变量名叫browser
代码提示
我用的编辑器是vscode,之前一直不明白怎么给这两个变量添加代码提示
最早尝试
最开始我想的是加一个全局变量,搜到可以在.eslintrc配置中添加一个globals,把变量名加进去,但后来发现这个东西跟代码提示没半毛钱关系。这是ESLint的配置文件,它的功能只是代码检查。
问过插件开发的大佬,大佬只说导入Library啥的,当时的我亿脸懵逼。
typings
看了github上的各种插件,发现有一个@types/chrome,typings是TypeScript的定义管理器,描述命名空间、接口、变量等各种东西,@types/chrome呢也就是别人写好的一个描述文件,去告诉编辑器我这里有个chrome变量,它下面有哪些方法之类的。
使用npm安装
npm install --save-dev @types/chrome安装好后发现chrome的代码提示有了,但只有chrome,火狐浏览器的browser依然没有。
自定义typings
前几天突发奇想,因为vue是可以自定义全局和实例变量的代码提示的,那么browser也许能自定义,于是照着这个思路,搜了一下怎么新建一个描述,去“继承”chrome
其实非常简单,只需要创建个文件,比如我在src/typings/下创建了一个browser.d.ts。这里具体在哪个文件夹下无所谓,读取这个文件是在tsconfig.json中配置的
{
"include": [
"src/**/*.ts",
"src/**/*.d.ts"
]
}意思就是,加载src目录下的包括所有文件夹中的.ts、.d.ts文件,所以只是创建在src目录下就行
然后在这个文件里添加
declare const browser: typeof chrome这样就有browser变量了
添加vue变量
再新建一个vue.d.ts,在里面添加
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为例,里面封装了一个网络请求
import axios from 'axios'
import Vue from 'vue'
Vue.chrome = Vue.prototype.$chrome = chrome || browser
Vue.chrome.runtime.onMessage.addListener((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中,也需要加入
import Popup from '@components/popup'
import Vue from 'vue'
import '@styles/popup'
Vue.chrome = Vue.prototype.$chrome = chrome || browser
export default new Vue({
components: {
Popup
},
render: h => h(Popup)
}).$mount('#app')在popup.vue中使用
<template>
<div>
<h1>{{ title }}</h1>
<span>{{ message }}</span>
<input v-model="uid" type="text" value="" placeholder="输入UID">
<button @click="btn">
请求数据测试
</button>
</div>
</template>
<script lang="ts">
import { Component, Vue } 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,直接引入就可以用