用 Vue 开发自己的 Chrome 扩展[每日前端夜话0x7F]
栏目: JavaScript · 发布时间: 5年前
内容简介:翻译:疯狂的技术宅来源:
每日前端夜话 0x7E
每日前端夜话,陪你聊前端。
每天晚上18:00准时推送。
正文共:3509 字
预计阅读时间: 10 分钟
翻译:疯狂的技术宅
来源: sitepoint
浏览器扩展程序是可以修改和增强 Web 浏览器功能的小程序。它们可用于各种任务,例如阻止广告,管理密码,组织标签,改变网页的外观和行为等等。
好消息是浏览器扩展并不难写。可以用你已经熟悉的 Web 技术(HTML、CSS 和 JavaScript)创建 —— 就像普通网页一样。但是与网页不同的是,扩展程序可以访问许多特定于浏览器的 API,这才是有趣的地方。
在本教程中,我将向你展示如何为 Chrome 构建一个能够改变新标签页行为的简单扩展。这个扩展程序的 JavaScript 部分,我将使用 Vue.js 框架,因为它将允许我们快速启动并运行,而且用 vue 工作是很有趣。
本教程的代码可以在GitHub上找到:
https://github.com/sitepoint-editors/dad-joke-chrome-extension
Chrome 扩展程序的基础知识
Chrome扩展程序的核心部分是 manifest 文件 和后台脚本。manifest 文件采用JSON格式,提供有关扩展的重要信息,例如其版本、资源或所需的权限。后台脚本允许扩展对特定的浏览器事件做出反应,例如创建新选项卡。
为了演示这些概念,让我们先写一个“Hello,World!” Chrome 扩展。
创建一个名为 hello-world-chrome
的新文件夹和两个文件: manifest.json
和 background.js
:
1mkdir hello-world-chrome 2cd hello-world-chrome 3touch manifest.json background.js
打开 manifest.json
并添加以下代码:
1{ 2 "name": "Hello World Extension", 3 "version": "0.0.1", 4 "manifest_version": 2, 5 "background": { 6 "scripts": ["background.js"], 7 "persistent": false 8 } 9}
name
、 version
和 manifest_version
都是必填字段。 name
和 version
字段可以是你想要的任何内容; manifest version 应设置为2(从Chrome 18开始)。
background
允许我们注册一个后台脚本, 在 scripts
后面的数组中列出。除非扩展需要用 chrome.webRequest API来阻止或修改网络请求,否则 persistent
键应设置为 false
。
将以下代码添加到 background.js
,使浏览器在安装扩展时弹出出 hello 对话框:
1chrome.runtime.onInstalled.addListener(() => { 2 alert('Hello, World!'); 3});
最后安装扩展程序。打开 Chrome 并在地址栏中输入 chrome://extensions/
。你应该看到一个显示已安装扩展程序的页面。
由于我们要从文件(而不是Chrome网上应用店)安装自己的扩展程序,因此需要使用页面右上角的切换按钮来激活 开发者模式 。这应该添加一个额外的菜单栏,其中包含 Load unpacked 选项。单击此按钮并选择你之前创建的 hello-world-chrome
文件夹。单击 打开 ,应该能够看到已安装的扩展,并弹出“Hello,World!”窗口。
恭喜!你刚刚制作了一个 Chrome 扩展程序。
覆盖 Chrome 的新标签页
为了在打开新选项卡时迎接我们的是自己的扩展程序。可以通过使用 Override Pages API 【 https://developer.chrome.com/extensions/override 】来完成此操作。
注意:在你取得进展之前,请务必停用其他能够覆盖 Chrome 新标签页的扩展程序。一次只允许一个扩展改变这种行为。
首先创建一个要显示的页面,而不是新的标签页。我们称之为 tab.html
。它应该与清单文件和后台脚本位于同一文件夹中:
1<!DOCTYPE html> 2<html lang="en"> 3<head> 4 <meta charset="UTF-8"> 5 <title>My New Tab Page!</title> 6</head> 7<body> 8 <h1>My New Tab Page!</h1> 9 <p>You can put any content here you like</p> 10</body> 11</html>
接下来需要让扩展知道页面的存在。可以通过在清单文件中指定 chrome_url_overrides
来实现,如下所示:
1"chrome_url_overrides": { 2 "newtab": "tab.html" 3}
最后,你需要重新加载扩展才能使更改生效。你可以通过在 Chrome 的扩展程序页面上单击 Hello World 扩展程序的 reload 图标来执行此操作。
现在,当你打开新标签页时,你的自定义消息会出现。
将Vue添加到扩展
现在我们有一个非常基本的扩展,接下来要实现剩下的需功能了。当用户打开新标签页时,我希望扩展能够:
-
从精彩的笑话网站 icanhazdadjoke.com 获取一个笑话。
-
以良好的格式向用户显示该笑话。
-
显示用户喜欢该笑话的按钮。这样可以把笑话保存到
chrome.storage
。 -
显示一个按钮,供用户查看已收藏的笑话。
当然你也可以用纯 JavaScript 或像 jQuery 这样的库来完成所有这些 —— 你开心就好!
但是出于本教程的目的,我将用 Vue 和令人敬畏的 vue-web-extension【 https://github.com/Kocal/vue-web-extension 】 样板来实现此功能。
用 Vue 可以让我又快又好地编写更有条理的代码。正如我们所看到的,样板文件提供了几个脚本,可以在构建 Chrome 扩展程序时解决一些痛苦的常见任务(例如:每当你进行更改时都必须重新加载扩展程序)。
vue-web-extension-boilerplate
本节假定你的计算机上安装了 Node 和 npm。如果不是这样,你可以到 https://nodejs.org/en/ 获取相关二进制文件,或者你可以使用版本管理器【 https://www.sitepoint.com/quick-tip-multiple-versions-node-nvm/ 】。我建议使用版本管理器。
我们还需要安装 Vue CLI 和 @vue/cli-init package:
1npm install -g @vue/cli 2npm install -g @vue/cli-init
完成后,让我们得到样板的副本:
1vue init kocal/vue-web-extension new-tab-page
这将打开一个向导,询问你一堆问题。为了保证本教程的重点,我把回答列出来:
1? Project name new-tab-page 2? Project description A Vue.js web extension 3? Author James Hibbard <jim@example.com> 4? License MIT 5? Use Mozilla's web-extension polyfill? No 6? Provide an options page? No 7? Install vue-router? No 8? Install vuex? No 9? Install axios? Yes 10? Install ESLint? No 11? Install Prettier? No 12? Automatically install dependencies? npm 13
你可以根据自己的喜好调整答案,但是你一定要安装 axios。我们会用它来获取笑话。
接下来,切换到项目目录并安装依赖项:
1cd new-tab-page 2npm install
然后就可以用样板提供的脚本构建我们的新扩展了:
1npm run watch:dev
这会将扩展构建到项目根目录中的 dist
文件夹中,来进行开发并监视更改。
要将扩展程序添加到 Chrome,请执行上述相同的步骤,要选择 dist
文件夹作为扩展程序目录。如果一切按计划进行,那么当扩展程序初始化时,你应该看到“Hello world!”消息。
项目设置
让我们花一点时间来看看样板给了我们些什么。当前文件夹结构应如下所示:
1. 2├── dist 3│ └── <the built extension> 4├── node_modules 5│ └── <one or two files and folders> 6├── package.json 7├── package-lock.json 8├── scripts 9│ ├── build-zip.js 10│ └── remove-evals.js 11├── src 12│ ├── background.js 13│ ├── icons 14│ │ ├── icon_128.png 15│ │ ├── icon_48.png 16│ │ └── icon.xcf 17│ ├── manifest.json 18│ └── popup 19│ ├── App.vue 20│ ├── popup.html 21│ └── popup.js 22└── webpack.config.js
在项目根目录中可以看到,样板文件正在使用 webpack。这很好,因为这为我们的后台脚本提供了 Hot Module Reloading【 https://webpack.js.org/concepts/hot-module-replacement 】。
src
文件夹包含我们将用于扩展的所有文件。manifest 文件和 background.js
对于我们来说是熟悉的,但也要注意包含Vue 组件的 popup
文件夹。当样板文件将扩展构建到 dist
文件夹中时,它将通过 vue-loader 管理所有 .vue
文件并输出一个浏览器可以理解的 JavaScript 包。
在 src
文件夹中还有一个 icons
文件夹。如果你看一眼 Chrome 的 工具 栏,会看到我们的扩展程序的新图标(也被称为 browser action【 https://developer.chrome.com/extensions/browserAction 】)。这就是从此文件夹中拿到的。如果单击它,你应该会看到一个弹出窗口,显示“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
:
1mkdir src/tab 2touch src/tab/{App.vue,tab.html,tab.js}
打开 tab.html
并添加以下内容:
1<!DOCTYPE html> 2<html lang="en"> 3<head> 4 <meta charset="UTF-8"> 5 <title>New Tab Page</title> 6 <link rel="stylesheet" href="tab.css"> 7</head> 8<body> 9 <div id="app"></div> 10 <script src="tab.js"></script> 11</body> 12</html>
这里没什么特别的。这是一个简单的 HTML 页面,它将保存我们的 Vue 实例。
接下来在 tab.js
中添加:
1import Vue from 'vue'; 2import App from './App'; 3 4new Vue({ 5 el: '#app', 6 render: h => h(App) 7});
在这里导入 Vue,用它为元素传递一个选择器,然后告诉它渲染 App
组件。
最后在 App.vue
中写如下代码:
1<template> 2 <p>{{ message }}</p> 3</template> 4 5<script> 6export default { 7 data () { 8 return { 9 message: "My new tab page" 10 } 11 } 12} 13</script> 14 15<style scoped> 16p { 17 font-size: 20px; 18} 19</style>
在使用这个新标签页之前,我们需要更新 manifest 文件:
1{ 2 "name":"new-tab-page", 3 ... 4 "chrome_url_overrides": { 5 "newtab": "tab/tab.html" 6 } 7}
为了使它们可用于扩展,我们还需要让样板编译我们的文件并复制到 dist
文件夹。
像下面这样修改 webpack.config.js
,更新 entry
和 plugins
键:
1entry: { 2 'background': './background.js', 3 'popup/popup': './popup/popup.js', 4 'tab/tab': './tab/tab.js' 5} 6plugins: [ 7 ... 8 new CopyWebpackPlugin([ 9 { from: 'icons', to: 'icons', ignore: ['icon.xcf'] }, 10 { from: 'popup/popup.html', to: 'popup/popup.html', transform: transformHtml }, 11 { from: 'tab/tab.html', to: 'tab/tab.html', transform: transformHtml }, 12 ... 13 })
你需要重新启动 npm run watch:dev
任务才能使这些更改生效。完成此操作后,重新加载扩展程序并打开新选项卡。你应该会看到“My new tab page”。
获取并显示笑话
好的,我们已经覆盖了 Chrome 的新标签页,并且将其替换为了 mini Vue app。但是我们要做的不仅仅是显示一条消息。
更改 src/tab/App.vue
中的模板部分如下:
1<template> 2 <div> 3 <div v-if="loading"> 4 <p>Loading...</p> 5 </div> 6 <div v-else> 7 <p class="joke">{{ joke }}</p> 8 </div> 9 </div> 10</template>
将 <script>
部分更改为如下代码:
1<script> 2import axios from 'axios'; 3 4export default { 5 data () { 6 return { 7 loading: true, 8 joke: "", 9 } 10 }, 11 mounted() { 12 axios.get( 13 "https://icanhazdadjoke.com/", 14 { 'headers': { 'Accept': 'application/json' } } 15 ) 16 .then(res => { 17 this.joke = res.data.joke 18 this.loading = false; 19 }); 20 } 21} 22</script> 23
最后,将 <style>
部分更改为如下代码:
1<style> 2body { 3 height: 98vh; 4 text-align: center; 5 color: #353638; 6 font-size: 22px; 7 line-height: 30px; 8 font-family: Merriweather,Georgia,serif; 9 background-size: 200px; 10 display: flex; 11 align-items: center; 12 justify-content: center; 13} 14 15.joke { 16 max-width: 800px; 17} 18</style>
如果你正在运行 npm run watch:dev
任务,则扩展程序会自动重新加载,并且每当你打开新标签页时都会看到一个笑话。
接下来花点时间来了解一下自己都做了些什么。
在模板中,我们使用 v-if 块来显示加载消息或笑话,具体取决于 loading
的状态。最初它被设置为 true
(显示加载消息),然后我们的脚本将触发 Ajax 请求来检索笑话。一旦 Ajax 请求完成, loading
属性将被设置为 false
,导致组件被重新渲染并显示笑话。
在 <script>
部分,我们导入了 axios,然后声明了几个数据属性——前面提到的 loading
属性和一个 joke
属性来保存这个笑话。然后使用了 mount
生命周期钩子【 https://vuejs.org/v2/guide/instance.html#Instance-Lifecycle-Hooks 】,一旦我们的 Vue 实例被挂载就会触发,向 joke API 【 https://icanhazdadjoke.com/api 】发出 Ajax 请求。请求完成后,更新两个数据属性使组件重新渲染。
到目前为止还挺好。
将笑话持持久化到 Chrome Storage
接下来,添加一些能够让用户喜欢一个笑话和列出喜欢的笑话列表的按钮。由于我们将使用 Chrome’s storage API 【 https://developer.chrome.com/extensions/storage 】来保存这些笑话,所以可能需要添加第三个按钮来删除 storage 中的笑话。
将按钮添加到 v-else 块:
1<div v-else> 2 <p class="joke">{{ joke }}</p> 3 4 <button @click="likeJoke" :disabled="likeButtonDisabled">Like Joke</button> 5 <button @click="logJokes" class="btn">Log Jokes</button> 6 <button @click="clearStorage" class="btn">Clear Storage</button> 7</div>
没有什么令人兴奋的东西了。请注意我们将类似按钮的 disabled
属性绑定到 Vue 实例上的数据属性来确定其状态。这是因为用户不应该多次喜欢一个笑话。
接下来,将 click handler 和 Like Button Disabled
添加到脚本部分:
1export default { 2 data () { 3 return { 4 loading: true, 5 joke: "", 6 likeButtonDisabled: false 7 } 8 }, 9 methods: { 10 likeJoke(){ 11 chrome.storage.local.get("jokes", (res) => { 12 if(!res.jokes) res.jokes = []; 13 res.jokes.push(this.joke) 14 chrome.storage.local.set(res); 15 this.likeButtonDisabled = true; 16 }); 17 }, 18 logJokes(){ 19 chrome.storage.local.get("jokes", (res) => { 20 if(res.jokes) res.jokes.map(joke => console.log(joke)) 21 }); 22 }, 23 clearStorage(){ 24 chrome.storage.local.clear(); 25 } 26 }, 27 mounted() { ... } 28}
在这里,我们声明了三个新方法来处理这三个新按钮。
likeJoke
方法在 Chrome 的存储中查找 jokes
属性。如果它不存在(也就是说,用户尚未喜欢一个笑话),会将其初始化为空数组。然后它将当前的笑话推送到此数组并将其保存到 storage。最后,将 likeButtonDisabled
数据属性设置为 true
,并禁用 like 按钮。
logJokes
方法还在 Chrome storage 中查找 jokes
属性。如果找到了,会遍历其所有条目并将它们输出到控制台。
clearStorage
方法负责清除数据。
继续在扩展中调整这个新功能,直到自己满意。
为扩展做一些美化
它能够工作了,但是按钮是很丑,页面也有点简单。下面就要给扩展做一些润色。
下一步,安装 vue-awesome 库。它能够使我们在页面上使用 Font Awesome 图标,并使这些按钮看起来更漂亮一些:
1npm install vue-awesome
在 src/tab/tab.js
中对库进行注册:
1import Vue from 'vue'; 2import App from './App'; 3import "vue-awesome/icons"; 4import Icon from "vue-awesome/components/Icon"; 5 6Vue.component("icon", Icon); 7 8new Vue({ 9 el: '#app', 10 render: h => h(App) 11});
修改模板:
1<template> 2 <div> 3 <div v-if="loading" class="centered"> 4 <p>Loading...</p> 5 </div> 6 <div v-else> 7 <p class="joke">{{ joke }}</p> 8 9 <div class="button-container"> 10 <button @click="likeJoke" :disabled="likeButtonDisabled" class="btn"><icon name="thumbs-up"></icon></button> 11 <button @click="logJokes" class="btn"><icon name="list"></icon></button> 12 <button @click="clearStorage" class="btn"><icon name="trash"></icon></button> 13 </div> 14 </div> 15 </div> 16</template> 17
最后,让我们为按钮添加更多样式,并添加一张图片:
1<style> 2body { 3 height: 98vh; 4 text-align: center; 5 color: #353638; 6 font-size: 22px; 7 line-height: 30px; 8 font-family: Merriweather,Georgia,serif; 9 background: url("https://dab1nmslvvntp.cloudfront.net/wp-content/uploads/2018/12/1544189726troll-dad.png") no-repeat 1% 99%; 10 background-size: 200px; 11 display: flex; 12 align-items: center; 13 justify-content: center; 14} 15 16.joke { 17 max-width: 800px; 18} 19 20.button-container { 21 position: absolute; 22 right: 0px; 23 top: calc(50% - 74px); 24} 25 26.btn { 27 background-color: #D8D8D8; 28 border: none; 29 color: white; 30 padding: 12px 16px; 31 font-size: 16px; 32 cursor: pointer; 33 display: block; 34 margin-bottom: 5px; 35 width: 50px; 36} 37 38.btn:hover { 39 background-color: #C8C8C8; 40} 41 42.btn:disabled { 43 background-color: #909090; 44} 45</style>
重新加载扩展并打开一个新标签,你应该看到这样的东西。
将扩展程序上传到 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 指南【 https://developer.chrome.com/webstore/publish 】。
总结
在本教程中,我重点介绍了 Chrome 扩展程序的主要部分,并展示了如何用在 Vue.js 中 vue-web-extension 样板构建扩展程序,最后讲解了如何将扩展上传到 Web Store。
希望你喜欢本教程,并用它指导你始构建自己的 Chrome 扩展。
原文:https://www.sitepoint.com/build-vue-chrome-extension/
图书推荐
下面夹杂一些私货:也许你和高薪之间只差这一张图
2019年京程一灯课程体系上新,这是我们第一次将全部课程列表对外开放。
愿你有个好前程,愿你月薪30K。我们是认真的 !
在公众号内回复“体系”查看高清大图
长按二维码,加大鹏老师微信好友
拉你加入前端技术交流群
唠一唠怎样才能拿高薪
往期精选
小手一抖,资料全有。长按二维码关注 前端先锋 ,阅读更多技术文章和业界动态。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Vue生命周期钩子简介[每日前端夜话0x8A]
- Node.js 究竟是什么?[每日前端夜话0x72]
- 关于 Git 的 20 个面试题[每日前端夜话0x75]
- React 的未来,与 Suspense 同行[每日前端夜话0x85]
- 一文学会Vue中间件管道[每日前端夜话0x8C]
- 为什么要用 Node.js?[每日前端夜话0x77]
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
HTML 编码/解码
HTML 编码/解码
正则表达式在线测试
正则表达式在线测试