使用Vue开发自己的Chrome扩展程序过程详解


Posted in Javascript onJune 21, 2019

前言

浏览器扩展程序是可以修改和增强 Web 浏览器功能的小程序。它们可用于各种任务,例如阻止广告,管理密码,组织标签,改变网页的外观和行为等等。

好消息是浏览器扩展并不难写。可以用你已经熟悉的 Web 技术(HTML、CSS 和 JavaScript)创建 —— 就像普通网页一样。但是与网页不同的是,扩展程序可以访问许多特定于浏览器的 API,这才是有趣的地方。

在本教程中,我将向你展示如何为 Chrome 构建一个能够改变新标签页行为的简单扩展。这个扩展程序的 JavaScript 部分,我将使用 Vue.js 框架,因为它将允许我们快速启动并运行,而且用 vue 工作是很有趣的。

本教程的代码可以在GitHub上找到

Chrome 扩展程序的基础知识

Chrome扩展程序的核心部分是 manifest 文件 和后台脚本。manifest 文件采用JSON格式,提供有关扩展的重要信息,例如其版本、资源或所需的权限。后台脚本允许扩展对特定的浏览器事件做出反应,例如创建新选项卡。

为了演示这些概念,让我们先写一个“Hello,World!” Chrome 扩展。

创建一个名为 hello-world-chrome 的新文件夹和两个文件:manifest.json 和 background.js:

mkdir hello-world-chrome
cd hello-world-chrome
touch manifest.json background.js

打开 manifest.json 并添加以下代码:

{
"name": "Hello World Extension",
"version": "0.0.1",
"manifest_version": 2,
"background": {
"scripts": ["background.js"],
"persistent": false
}
}

name、version 和 manifest_version 都是必填字段。 name 和 version 字段可以是你想要的任何内容; manifest version 应设置为2(从Chrome 18开始)。

background 允许我们注册一个后台脚本, 在scripts 后面的数组中列出。除非扩展需要用 chrome.webRequest API来阻止或修改网络请求,否则 persistent 键应设置为 false。

将以下代码添加到 background.js ,使浏览器在安装扩展时弹出出 hello 对话框:

chrome.runtime.onInstalled.addListener(() => {
alert('Hello, World!');
});

最后安装扩展程序。打开 Chrome 并在地址栏中输入 chrome://extensions/。你应该看到一个显示已安装扩展程序的页面。
由于我们要从文件(而不是Chrome网上应用店)安装自己的扩展程序,因此需要使用页面右上角的切换按钮来激活开发者模式。

这应该添加一个额外的菜单栏,其中包含 Load unpacked选项。单击此按钮并选择你之前创建的 hello-world-chrome 文件夹。单击打开,应该能够看到已安装的扩展,并弹出“Hello,World!”窗口。

使用Vue开发自己的Chrome扩展程序过程详解

恭喜!你刚刚制作了一个 Chrome 扩展程序。

覆盖 Chrome 的新标签页

为了在打开新选项卡时迎接我们的是自己的扩展程序。可以通过使用 Override Pages API 来完成此操作。

注意:在你取得进展之前,请务必停用其他能够覆盖 Chrome 新标签页的扩展程序。一次只允许一个扩展改变这种行为。

首先创建一个要显示的页面,而不是新的标签页。我们称之为 tab.html。它应该与清单文件和后台脚本位于同一文件夹中:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My New Tab Page!</title>
</head>
<body>
<h1>My New Tab Page!</h1>
<p>You can put any content here you like</p>
</body>
</html>

接下来需要让扩展知道页面的存在。可以通过在清单文件中指定 chrome_url_overrides 来实现,如下所示:

"chrome_url_overrides": {
"newtab": "tab.html"
}

最后,你需要重新加载扩展才能使更改生效。你可以通过在 Chrome 的扩展程序页面上单击 Hello World 扩展程序的 reload 图标来执行此操作。

使用Vue开发自己的Chrome扩展程序过程详解

现在,当你打开新标签页时,你的自定义消息会出现。

将Vue添加到扩展

现在我们有一个非常基本的扩展,接下来要实现剩下的需功能了。当用户打开新标签页时,我希望扩展能够:

  • 从精彩的笑话网站 icanhazdadjoke.com 获取一个笑话。
  • 以良好的格式向用户显示该笑话。
  • 显示用户喜欢该笑话的按钮。这样可以把笑话保存到 chrome.storage。
  • 显示一个按钮,供用户查看已收藏的笑话。

当然你也可以用纯 JavaScript 或像 jQuery 这样的库来完成所有这些 —— 你开心就好!

但是出于本教程的目的,我将用 Vue 和令人敬畏的vue-web-extension 样板来实现此功能。

用 Vue 可以让我又快又好地编写更有条理的代码。正如我们所看到的,样板文件提供了几个脚本,可以在构建 Chrome 扩展程序时解决一些痛苦的常见任务(例如:每当你进行更改时都必须重新加载扩展程序)。

vue-web-extension-boilerplate

本节假定你的计算机上安装了 Node 和 npm。如果不是这样,你可以到 nodejs.org/en/ 获取相关二进制文件,或者你可以使用版本管理器。我建议使用版本管理器。

我们还需要安装 Vue CLI 和 @vue/cli-init package:

npm install -g @vue/cli
npm install -g @vue/cli-init

完成后,让我们得到样板的副本:

vue init kocal/vue-web-extension new-tab-page

这将打开一个向导,询问你一堆问题。为了保证本教程的重点,我把回答列出来:

? Project name new-tab-page
? Project description A Vue.js web extension
? Author James Hibbard <jim@example.com>
? License MIT
? Use Mozilla's web-extension polyfill? No
? Provide an options page? No
? Install vue-router? No
? Install vuex? No
? Install axios? Yes
? Install ESLint? No
? Install Prettier? No
? Automatically install dependencies? npm

你可以根据自己的喜好调整答案,但是你一定要安装 axios。我们会用它来获取笑话。

接下来,切换到项目目录并安装依赖项:

cd new-tab-page
npm install

然后就可以用样板提供的脚本构建我们的新扩展了:

npm run watch:dev

这会将扩展构建到项目根目录中的 dist 文件夹中,来进行开发并监视更改。

要将扩展程序添加到 Chrome,请执行上述相同的步骤,要选择 dist 文件夹作为扩展程序目录。如果一切按计划进行,那么当扩展程序初始化时,你应该看到“Hello world!”消息。

项目设置

让我们花一点时间来看看样板给了我们些什么。当前文件夹结构应如下所示:

.
├── dist
│ └── <the built extension>
├── node_modules
│ └── <one or two files and folders>
├── package.json
├── package-lock.json
├── scripts
│ ├── build-zip.js
│ └── remove-evals.js
├── src
│ ├── background.js
│ ├── icons
│ │ ├── icon_128.png
│ │ ├── icon_48.png
│ │ └── icon.xcf
│ ├── manifest.json
│ └── popup
│ ├── App.vue
│ ├── popup.html
│ └── popup.js
└── webpack.config.js

在项目根目录中可以看到,样板文件正在使用 webpack。这很好,因为这为我们的后台脚本提供了 Hot Module Reloading。

src文件夹包含我们将用于扩展的所有文件。manifest 文件和 background.js 对于我们来说是熟悉的,但也要注意包含Vue 组件的 popup 文件夹。当样板文件将扩展构建到 dist 文件夹中时,它将通过vue-loader 管理所有 .vue 文件并输出一个浏览器可以理解的 JavaScript 包。

在 src 文件夹中还有一个 icons 文件夹。如果你看一眼 Chrome 的工具栏,会看到我们的扩展程序的新图标(也被称为 browser action)。这就是从此文件夹中拿到的。如果单击它,你应该会看到一个弹出窗口,显示“Hello world!” 这是由 popup/App.vue 创建的。

最后,请注 scripts 文件夹的两个脚本:一个用于删除 eval 用法以符合 Chrome Web Store 的内容安全策略,另一个用于当你要把扩展上传到Chrome Web Store时将其打包到 .zip 文件中,。

在 package.json 文件中还声明了各种脚本。我们将用 npm run watch:dev 来开发扩展,然后使用 npm run build-zip 生成一个ZIP文件以上传到 Chrome Web Store。

在新标签页中使用 Vue 组件

首先从 background.js 中删除烦人的 alert 语句。

在 src 文件夹中创建一个新的 tab 文件夹来存放新标签页的代码。我们将在这个新文件夹中添加三个文件 —— App.vue,tab.html, tab.js:

mkdir src/tab
touch src/tab/{App.vue,tab.html,tab.js}

打开 tab.html 并添加以下内容:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>New Tab Page</title>
<link rel="stylesheet" href="tab.css" rel="external nofollow" >
</head>
<body>
<div id="app"></div>
<script src="tab.js"></script>
</body>
</html>

这里没什么特别的。这是一个简单的 HTML 页面,它将保存我们的 Vue 实例。

接下来在 tab.js 中添加:

import Vue from 'vue';
import App from './App';
new Vue({
el: '#app',
render: h => h(App)
});

在这里导入 Vue,用它为元素传递一个选择器,然后告诉它渲染 App 组件。

最后在 App.vue 中写如下代码:

<template>
<p>{{ message }}</p>
</template>
<script>
export default {
data () {
return {
message: "My new tab page"
}
}
}
</script>
<style scoped>
p {
font-size: 20px;
}
</style>

在使用这个新标签页之前,我们需要更新 manifest 文件:

{
"name":"new-tab-page",
...
"chrome_url_overrides": {
"newtab": "tab/tab.html"
}
}

为了使它们可用于扩展,我们还需要让样板编译我们的文件并复制到 dist 文件夹。

像下面这样修改 webpack.config.js,更新entry和plugins键:

entry: {
'background': './background.js',
'popup/popup': './popup/popup.js',
'tab/tab': './tab/tab.js'
}
plugins: [
...
new CopyWebpackPlugin([
{ from: 'icons', to: 'icons', ignore: ['icon.xcf'] },
{ from: 'popup/popup.html', to: 'popup/popup.html', transform: transformHtml },
{ from: 'tab/tab.html', to: 'tab/tab.html', transform: transformHtml },
...
})

你需要重新启动 npm run watch:dev 任务才能使这些更改生效。完成此操作后,重新加载扩展程序并打开新选项卡。你应该会看到“My new tab page”。

使用Vue开发自己的Chrome扩展程序过程详解

获取并显示笑话

好的,我们已经覆盖了 Chrome 的新标签页,并且将其替换为了 mini Vue app。但是我们要做的不仅仅是显示一条消息。

更改 src/tab/App.vue 中的模板部分如下:

<template>
<div>
<div v-if="loading">
<p>Loading...</p>
</div>
<div v-else>
<p class="joke">{{ joke }}</p>
</div>
</div>
</template>

将 <script> 部分更改为如下代码:

<script>
import axios from 'axios';
export default {
data () {
return {
loading: true,
joke: "",
}
},
mounted() {
axios.get(
"https://icanhazdadjoke.com/",
{ 'headers': { 'Accept': 'application/json' } }
)
.then(res => {
this.joke = res.data.joke
this.loading = false;
});
}
}
</script>

最后,将 <style> 部分更改为如下代码:

<style>
body {
height: 98vh;
text-align: center;
color: #353638;
font-size: 22px;
line-height: 30px;
font-family: Merriweather,Georgia,serif;
background-size: 200px;
display: flex;
align-items: center;
justify-content: center;
}
.joke {
max-width: 800px;
}
</style>

如果你正在运行 npm run watch:dev 任务,则扩展程序会自动重新加载,并且每当你打开新标签页时都会看到一个笑话。

使用Vue开发自己的Chrome扩展程序过程详解

接下来花点时间来了解一下自己都做了些什么。

在模板中,我们使用 v-if 块来显示加载消息或笑话,具体取决于 loading 的状态。最初它被设置为 true(显示加载消息),然后我们的脚本将触发 Ajax 请求来检索笑话。一旦 Ajax 请求完成,loading 属性将被设置为 false,导致组件被重新渲染并显示笑话。

在 <script> 部分,我们导入了 axios,然后声明了几个数据属性——前面提到的 loading 属性和一个 joke 属性来保存这个笑话。然后使用了 mount 生命周期钩子,一旦我们的 Vue 实例被挂载就会触发,向 joke API 发出 Ajax 请求。请求完成后,更新两个数据属性使组件重新渲染。

到目前为止还挺好。

将笑话持持久化到 Chrome Storage

接下来,添加一些能够让用户喜欢一个笑话和列出喜欢的笑话列表的按钮。由于我们将使用 Chrome's storage API 来保存这些笑话,所以可能需要添加第三个按钮来删除 storage 中的笑话。
将按钮添加到 v-else 块:

<div v-else>
<p class="joke">{{ joke }}</p>
<button @click="likeJoke" :disabled="likeButtonDisabled">Like Joke</button>
<button @click="logJokes" class="btn">Log Jokes</button>
<button @click="clearStorage" class="btn">Clear Storage</button>
</div>

没有什么令人兴奋的东西了。请注意我们将类似按钮的 disabled 属性绑定到 Vue 实例上的数据属性来确定其状态。这是因为用户不应该多次喜欢一个笑话。

接下来,将 click handler 和 Like Button Disabled 添加到脚本部分:

export default {
data () {
return {
loading: true,
joke: "",
likeButtonDisabled: false
}
},
methods: {
likeJoke(){
chrome.storage.local.get("jokes", (res) => {
if(!res.jokes) res.jokes = [];
res.jokes.push(this.joke)
chrome.storage.local.set(res);
this.likeButtonDisabled = true;
});
},
logJokes(){
chrome.storage.local.get("jokes", (res) => {
if(res.jokes) res.jokes.map(joke => console.log(joke))
});
},
clearStorage(){
chrome.storage.local.clear();
}
},
mounted() { ... }
}

在这里,我们声明了三个新方法来处理这三个新按钮。

likeJoke 方法在 Chrome 的存储中查找 jokes 属性。如果它不存在(也就是说,用户尚未喜欢一个笑话),会将其初始化为空数组。然后它将当前的笑话推送到此数组并将其保存到 storage。最后,将 likeButtonDisabled 数据属性设置为 true,并禁用 like 按钮。

logJokes 方法还在 Chrome storage 中查找 jokes 属性。如果找到了,会遍历其所有条目并将它们输出到控制台。

clearStorage 方法负责清除数据。

继续在扩展中调整这个新功能,直到自己满意。

使用Vue开发自己的Chrome扩展程序过程详解

为扩展做一些美化

它能够工作了,但是按钮是很丑,页面也有点简单。下面就要给扩展做一些润色。

下一步,安装 vue-awesome 库。它能够使我们在页面上使用 Font Awesome 图标,并使这些按钮看起来更漂亮一些:

npm install vue-awesome

在 src/tab/tab.js 中对库进行注册:

import Vue from 'vue';
import App from './App';
import "vue-awesome/icons";
import Icon from "vue-awesome/components/Icon";
Vue.component("icon", Icon);
new Vue({
el: '#app',
render: h => h(App)
});

修改模板:

<template>
<div>
<div v-if="loading" class="centered">
<p>Loading...</p>
</div>
<div v-else>
<p class="joke">{{ joke }}</p>
<div class="button-container">
<button @click="likeJoke" :disabled="likeButtonDisabled" class="btn"><icon name="thumbs-up"></icon></button>
<button @click="logJokes" class="btn"><icon name="list"></icon></button>
<button @click="clearStorage" class="btn"><icon name="trash"></icon></button>
</div>
</div>
</div>
</template>

最后,让我们为按钮添加更多样式,并添加一张图片:

<style>
body {
height: 98vh;
text-align: center;
color: #353638;
font-size: 22px;
line-height: 30px;
font-family: Merriweather,Georgia,serif;
background: url("https://dab1nmslvvntp.cloudfront.net/wp-content/uploads/2018/12/1544189726troll-dad.png") no-repeat 1% 99%;
background-size: 200px;
display: flex;
align-items: center;
justify-content: center;
}
.joke {
max-width: 800px;
}
.button-container {
position: absolute;
right: 0px;
top: calc(50% - 74px);
}
.btn {
background-color: #D8D8D8;
border: none;
color: white;
padding: 12px 16px;
font-size: 16px;
cursor: pointer;
display: block;
margin-bottom: 5px;
width: 50px;
}
.btn:hover {
background-color: #C8C8C8;
}
.btn:disabled {
background-color: #909090;
}
</style>

重新加载扩展并打开一个新标签,你应该看到这样的东西。

使用Vue开发自己的Chrome扩展程序过程详解

将扩展程序上传到 Chrome Web Store

如果想让其他人也可以使用你的扩展程序,可以通过Chrome Web Store 做到。

首先你需要有一个 Google 帐户,可以用该帐户登录 Developer Dashboard 。系统会提示你输入开发人员详细信息,在发布第一个应用程序之前,你必须支付 5 美元的开发人员注册费(通过信用卡)。

接下来,你需要为自己的应用创建一个 ZIP 文件。你可以通过 npm run build-zip 在本地执行这项操作。这会在项目根目录中创建一个名为 dist-zip 的文件夹,其中包含准备上传到 Web Store 的 ZIP 文件。

对于简单的小扩展,这就够了。但是,在你上传自己的扩展之前,请务必阅读官方 Publish in the Chrome Web Store 指南。

总结

在本教程中,我重点介绍了 Chrome 扩展程序的主要部分,并展示了如何用在 Vue.js 中 vue-web-extension 样板构建扩展程序,最后讲解了如何将扩展上传到 Web Store。

希望你喜欢本教程,并用它指导你始构建自己的 Chrome 扩展。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jquery蒙版控件实现代码
Dec 08 Javascript
背景图跟随鼠标移动的Mootools插件实现代码
Dec 12 Javascript
javascript中方便增删改cookie的一个类
Oct 11 Javascript
jquery中ajax跨域方法实例分析
Dec 18 Javascript
浅析JS异步加载进度条
May 05 Javascript
js当前页面登录注册框,固定div,底层阴影的实例代码
Oct 04 Javascript
jQuery文字轮播特效
Feb 12 Javascript
微信小程序page的生命周期和音频播放及监听实例详解
Apr 07 Javascript
Vue 进阶教程之v-model详解
May 06 Javascript
vue 路由嵌套高亮问题的解决方法
May 17 Javascript
vue 监听窗口变化对页面部分元素重新渲染操作
Jul 28 Javascript
JavaScript中EventBus实现对象之间通信
Oct 18 Javascript
如何测量vue应用运行时的性能
Jun 21 #Javascript
Vue组件之高德地图地址选择功能的实例代码
Jun 21 #Javascript
如何提升vue.js中大型数据的性能
Jun 21 #Javascript
配置node服务器并且链接微信公众号接口配置步骤详解
Jun 21 #Javascript
微信小程序实现点击效果
Jun 21 #Javascript
JS利用prototype给类添加方法操作详解
Jun 21 #Javascript
三分钟教你用Node做一个微信哄女友(基友)神器(面向小白)
Jun 21 #Javascript
You might like
解析将多维数组转换为支持curl提交的一维数组格式
2013/07/08 PHP
PHP大转盘中奖概率算法实例
2014/10/21 PHP
php rsa加密解密使用详解
2015/01/14 PHP
使用 PHPStorm 开发 Laravel
2015/03/24 PHP
详解PHP中的mb_detect_encoding函数使用方法
2015/08/18 PHP
利用phpexcel对数据库数据的导入excel(excel筛选)、导出excel
2017/04/27 PHP
javascript 日期时间函数(经典+完善+实用)
2009/05/27 Javascript
jquery自定义类似$.ajax()的方法实现代码
2013/08/13 Javascript
使用apply方法实现javascript中的对象继承
2013/12/16 Javascript
jQuery Validate 数组 全部验证问题
2017/01/12 Javascript
jQuery实现注册会员时密码强度提示信息功能示例
2017/09/05 jQuery
详解利用Angular实现多团队模块化SPA开发框架
2017/11/27 Javascript
Vue.js实现的购物车功能详解
2019/01/27 Javascript
layui上传图片到服务器的非项目目录下的方法
2019/09/26 Javascript
微信小程序实现左侧滑动导航栏
2020/04/08 Javascript
JS实现页面鼠标点击出现图片特效
2020/08/19 Javascript
vue 监听 Treeselect 选择项的改变操作
2020/08/31 Javascript
node.js通过url读取文件
2020/10/16 Javascript
js 压缩图片的示例(只缩小体积,不更改图片尺寸)
2020/10/21 Javascript
Python中执行存储过程及获取存储过程返回值的方法
2017/10/07 Python
对python数据切割归并算法的实例讲解
2018/12/12 Python
Python基础教程之异常详解
2019/01/10 Python
Python使用ctypes调用C/C++的方法
2019/01/29 Python
python如何给字典的键对应的值为字典项的字典赋值
2019/07/05 Python
Python中的特殊方法以及应用详解
2020/09/20 Python
HTML5 Canvas绘制文本及图片的基础教程
2016/03/14 HTML / CSS
Canvas引入跨域的图片导致toDataURL()报错的问题的解决
2018/09/19 HTML / CSS
adidas旗下高尔夫装备供应商:TaylorMade Golf(泰勒梅高尔夫)
2016/08/28 全球购物
Giuseppe Zanotti美国官方网站:将鞋履视为高级时装般精心制作
2018/02/06 全球购物
Lookfantastic西班牙官网:英国知名美妆购物网站
2018/06/13 全球购物
简单英文演讲稿
2014/01/01 职场文书
幼儿园大班评语大全
2014/04/17 职场文书
工业设计专业自荐书
2014/06/05 职场文书
个人租房协议书
2014/11/28 职场文书
自愿离婚协议书2015
2015/01/26 职场文书
创业计划书之o2o水果店
2019/08/30 职场文书