使用Vue3+Element Plus开发Chrome插件

  • 引言
  • 初始Vue项目的创建
  • Element-Plus组件的安装及导入
  • 其他文件配置
    • .eslintrc.js文件
    • vue.config.js文件
    • package.json
    • src/文件夹
      • assets/
      • background/main.js
      • content/components/app.vue文件
      • content/main.js文件
      • plugins/inject.js
      • plugins/manifest.json文件
      • popup/components/app.vue文件
      • popup/index.html
  • 成果检验
  • 热更新设置
  • 2022-8-17使用的vue环境

引言

本人Vue3小白一枚,目前正在研究基于Vue3的Chrome浏览器插件的使用,经过不断尝试和整合各路大佬方法,现将自己尝试有效的项目框架搭建流程进行总结。在此非常感谢大佬们的分享。
本文主要参考文章——15000字大章带你一步一步使用Vue3开发chrome浏览器插件

初始Vue项目的创建

  • 控制台中输入vue create XXX创建新的vue工程项目
  • 在创建工程过程中选择Manually select features手动配置模块
  • 选中babel、linter、router后进行下一步,其中router项目若无需求可不选
  • 对于vue.js选择3.x版本
  • Router模式选择history
  • 选择ESLint with error prevention only,不选其他的,不然代码规范对后续开发产生很多麻烦
  • 随后选择Lint on save,如果有Git也可选择下面那项
  • 选择In dedicated config files将eslint、babel等文件分别单独存放
  • 完成初始Vue项目的创建

Element-Plus组件的安装及导入

  • 控制台输入npm install element-plus --save向Vue项目安装element-plus组件
  • 项目结构可参考大佬的文章所给出的结构,我的项目最终产出的目录结构为:
├── dist
│   ├── assets
│   │   ├── images
│   │   │   ├── icon128.png
│   │   │   ├── icon16.png
│   │   │   └── icon48.png
│   │   └── logo.png
│   ├── js
│   │   ├── background.js
│   │   ├── chunk-vendors.js
│   │   ├── content.js
│   │   ├── inject.js
│   │   └── popup.js
│   ├── manifest.json
│   └── popup.html
├── src
│   ├── assets
│   │   ├── images
│   │   │   ├── icon128.png
│   │   │   ├── icon16.png
│   │   │   └── icon48.png
│   │   └── logo.png
│   ├── background
│   │   └── main.js
│   ├── content
│   │   ├── components
│   │   │   └── app.vue
│   │   └── main.js
│   ├── plugins
│   │   ├── inject.js
│   │   └── manifest.json
│   ├── popup
│   │   ├── components
│   │   │   └── app.vue
│   │   ├── index.html
│   │   └── main.js
│   ├── router
│   │   └── index.js
│   └── utils
│       └── hotReload.js
├── .browserslistrc
├── .eslintrc.js
├── .gitignore
├── babel.config.js
├── jsconfig.json
├── package-lock.json
├── package.json
├── README.md
└── vue.config.js
  • 其中dist文件夹为执行npm run build指令后生成的,其他均应在执行npm run build前准备就绪
  • (如果开发的插件不涉及路由等操作,则删除src文件夹下的router/index.js文件夹及文件)
  • src/popup/main.js中添加element-plus插件,代码如下:
import { createApp } from 'vue'
import App from './components/app.vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import zhCn from 'element-plus/es/locale/lang/zh-cn'const app = createApp(App)
app.use(ElementPlus, {locale: zhCn})
app.mount('#app')
  • 至此,项目的创建和element-plus组件的导入完成

其他文件配置

.eslintrc.js文件

  • 主要是在globals中添加chrome: true从而让chrome属性在全局的.js文件中为可用状态
  • 复制以下内容到eslintrc.js文件中
module.exports = {root: true,globals: {chrome: true,},env: {node: true},'extends': ['plugin:vue/vue3-essential','eslint:recommended'],parserOptions: {parser: '@babel/eslint-parser'},rules: {'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off','no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'}
}

vue.config.js文件

  • vue.config.js作为项目配置文件,对打包生成的dist文件夹以及src文件夹下的各文件起到关键作用
  • 复制以下代码到vue.config.js文件中
const CopyWebpackPlugin = require("copy-webpack-plugin");
const path = require("path");// 复制文件到指定目录
const copyFiles = [{from: path.resolve("src/plugins/manifest.json"),to: `${path.resolve("dist")}/manifest.json`},{from: path.resolve("src/assets"),to: path.resolve("dist/assets")},{from: path.resolve("src/plugins/inject.js"),to: path.resolve("dist/js")}
];// 复制插件
const plugins = [new CopyWebpackPlugin({patterns: copyFiles})
];// 页面文件
const pages = {};
// 配置 popup.html 页面
const chromeName = ["popup"];chromeName.forEach(name => {pages[name] = {entry: `src/${name}/main.js`,template: `src/${name}/index.html`,filename: `${name}.html`};
});module.exports = {pages,productionSourceMap: false,// 配置 content.js background.jsconfigureWebpack: {entry: {content: "./src/content/main.js",background: "./src/background/main.js"},output: {filename: "js/[name].js"},plugins},// 配置 content.csscss: {extract: {filename: "css/[name].css"}},chainWebpack: config => {if (process.env.NODE_ENV === 'production') {config.output.filename('js/[name].js').end()config.output.chunkFilename('js/[name].js').end()}}
}

package.json

  • 在 "scripts"字段中添加 “watch”: “vue-cli-service build --watch”,来增加NPM脚本中对插件的热监控功能
  "scripts": {"watch": "vue-cli-service build --watch","serve": "vue-cli-service serve","build": "vue-cli-service build","lint": "vue-cli-service lint"},

src/文件夹

  • src文件夹下主要针对manifest.json文件、popup中的文件、content中的文件进行更改

assets/

  • assets文件中用于存放图标,注意images文件夹内的三张图片要是同一个图片的不同的名称,例如:

background/main.js

  • background作为Chrome插件的后台,随着浏览器的启动而启动,可将全局性的、一直运行的功能放在此处
  • 考虑到仅仅做一个demo,此处此处打印一串字作为测试,将以下内容复制到main.js中
console.log('this is background')

content/components/app.vue文件

  • 添加以下内容到app.vue文件作为植入到浏览器中的HTML文件(不植入无法获取网页中的DOM)
  • 注意:此时的.vue文件尚未具有注入HTML中的能力
<template><div class="head">this is the content</div>
</template><script setup>
</script><style scoped>
.head{color: red;position: fixed;z-index: 100001;right: 10px;bottom: 10px;
}
</style>

content/main.js文件

  • 添加以下内容到main.js文件中,在浏览器当前Tab中创建一个< div >标签并将app.vue文件加载到标签中以完成HTML的植入的操作
  • 当app.vue成功植入到HTML中时,我们便可以通过chrome自带的功能猥琐欲为了
import { createApp } from 'vue'
import app from './components/app.vue'
joinContent(app)
injectJsInsert()
function joinContent (element) {const div = document.createElement('div')div.id = 'joinContentApp'document.body.appendChild(div)console.log(div)createApp(element).mount('#joinContentApp')
}
//chrome的API接口,用于传输或监听数据信号
chrome.extension.onRequest.addListener( function (request) {if (request.popAction == "Test") {console.log("test")}}
);
function injectJsInsert () {document.addEventListener('readystatechange', () => {const injectPath = 'js/inject.js'const script = document.createElement('script')script.setAttribute('type', 'text/javascript')script.src = chrome.extension.getURL(injectPath)document.body.appendChild(script)})
}

plugins/inject.js

  • inject.js文件主要负责分析网页的DOM,拿到大图资源链接,并翻页,直到获取足够数量的图片
  • 可以在此文件内输入以下内容,最终结果可在浏览器窗口的控制台中打印出来
console.log('this is inject')

plugins/manifest.json文件

  • manifest.json文件的重要性再此不多做赘述了,文件中各个字段的意义和功能请见其他大佬的博客——Chrome插件manifest.json文件详解
  • 复制以下内容到manifest.json中以完成Chrome插件的配置
{"manifest_version": 2,"name": "test","description": "Vue3的Chrome插件","version": "1.0.0","browser_action": {"default_title": "plugin-base-vue3","default_icon": "assets/images/icon48.png","default_popup": "popup.html"},"permissions": [],"background": {"scripts": ["js/chunk-vendors.js", "js/background.js"]},"icons": {"16": "assets/images/icon16.png","48": "assets/images/icon48.png","128": "assets/images/icon128.png"},"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'","content_scripts": [{"matches": ["http://*/*", "https://*/*"],"css": ["css/content.css"],"js": ["js/chunk-vendors.js", "js/content.js"],"run_at": "document_idle"}],"web_accessible_resources": ["js/inject.js"]
}

popup/components/app.vue文件

  • 添加以下内容到app.vue文件中作为浏览器插件的前端显示窗口
<template><div class="wrapper"><el-button type="danger" @click="test">测试按钮</el-button></div>
</template>
<script setup>
const test = () => {chrome.tabs.getSelected(null, function(tab){chrome.tabs.sendRequest(tab.id, { popAction: "Test"});});
}
</script>
<style scoped>
.wrapper{width: 100px;height: 100px;background-color: aquamarine;
}
</style>

popup/index.html

  • index.html文件作为.vue文件的载体,其内容使用新建项目时的初始内容即可
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1.0"><title>test</title></head><body><noscript><strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body>
</html>
  • 上述文件内容填写完成后在控制台执行npm run build指令以获得dist文件,使用Chrome加载dist文件夹以加载插件

成果检验

  • 在加载插件的窗口中,点击查看视图旁的背景页可以看到来自background/main.js文件的打印内容
  • 打开任意一个页面可以看到右下角出现了this is the content-script字样,这说明我们的content里的app.vue文件已经成功植入到网页的html文件中了
  • 打开插件,出现了带有Element-plus控件元素的按钮,说明Element已经成功引入
  • 打开控制台(F12)可以看到植入到html页面中的< div >元素被打印了出来,同时来自plugins/inject.js的内容也被打印了出来
  • 点击插件中的按钮在控制台中出现了test字样,这说明content中的js文件已经接收到了来自popup中js传来的信息(由于.vue内带有script的编写区域,因此chrome的数据传输功能可直接在.vue文件中进行)
  • 恭喜你!你已经成功搭建了基于Vue3+Element-plus的Chrome框架

热更新设置

  • 如果不采用热更新,开发过程中将会不断经历"更改->打包->加载->再更改"的痛苦历程,为了提高开发效率,在utils/hotReload.js文件中添加以下内容:
// 加载文件const filesInDirectory = dir =>new Promise(resolve =>dir.createReader().readEntries(entries => {Promise.all(entries.filter(e => e.name[0] !== '.').map(e =>e.isDirectory ? filesInDirectory(e) : new Promise(resolve => e.file(resolve)))).then(files => [].concat(...files)).then(resolve);}));// 遍历插件目录,读取文件信息,组合文件名称和修改时间成数据
const timestampForFilesInDirectory = dir =>filesInDirectory(dir).then(files =>files.map(f => f.name + f.lastModifiedDate).join());// 刷新当前活动页
const reload = () => {window.chrome.tabs.query({active: true,currentWindow: true},tabs => {// NB: see https://github.com/xpl/crx-hotreload/issues/5if (tabs[0]) {window.chrome.tabs.reload(tabs[0].id);}// 强制刷新页面window.chrome.runtime.reload();});
};// 观察文件改动
const watchChanges = (dir, lastTimestamp) => {timestampForFilesInDirectory(dir).then(timestamp => {// 文件没有改动则循环监听watchChanges方法if (!lastTimestamp || lastTimestamp === timestamp) {setTimeout(() => watchChanges(dir, timestamp), 1000); // retry after 1s} else {// 强制刷新页面reload();}});
};const hotReload = () => {window.chrome.management.getSelf(self => {if (self.installType === 'development') {// 获取插件目录,监听文件变化window.chrome.runtime.getPackageDirectoryEntry(dir => watchChanges(dir));}});
};export default hotReload;
  • 同时修改background/main.js为:
import hotReload from '@/utils/hotReload'
hotReload()
console.log('this is background')
  • package.json中的scripts字段中添加"watch": "vue-cli-service build --watch",来向NPM脚本中添加热更新快捷操作

2022-8-17使用的vue环境

  • 本文创建于2022-8-17日,采用的package.json为:
{"name": "plugin","version": "0.1.0","private": true,"scripts": {"watch": "vue-cli-service build --watch","serve": "vue-cli-service serve","build": "vue-cli-service build","lint": "vue-cli-service lint"},"dependencies": {"core-js": "^3.8.3","element-plus": "^2.2.13","vue": "^3.2.13","vue-router": "^4.0.3"},"devDependencies": {"@babel/core": "^7.12.16","@babel/eslint-parser": "^7.12.16","@vue/cli-plugin-babel": "~5.0.0","@vue/cli-plugin-eslint": "~5.0.0","@vue/cli-plugin-router": "~5.0.0","@vue/cli-service": "~5.0.0","eslint": "^7.32.0","eslint-plugin-vue": "^8.0.3","less": "^4.1.3","less-loader": "^11.0.0"}
}
  • 通常来说,即使不采用本文的各模块版本,按照本文提供的方法一步一步执行也可以创建出Chrome插件的框架
  • 本文所讲述内容,作者从项目创建开始一步一步执行,亲测有效,所涉及各项功能均无异常

使用Vue3+Element Plus开发Chrome插件相关推荐

  1. 一文教会你如何用Vue开发Chrome插件

    前言 作为一个常年的B端前端开发者来说,千篇一律的业务开发有着些许的枯燥无味.在联调过程中,会经常发现后端在部署服务,然后又不知什么时候部署好,由于公司的部署系统查看系统部署状态入口较深,所以闲暇之余 ...

  2. 开发chrome 插件, background.js中 console log 看不到解决方法

    开发chrome 插件, background.js中 console log 看不到解决方法 参考文章: (1)开发chrome 插件, background.js中 console log 看不到 ...

  3. blazor wasm开发chrome插件

    用blazor(Wasm)开发了一个chrome插件感觉效率挺高的,分享给大家 先简单介绍下WebAssembly的原理: "WebAssembly是一种用于基于堆栈的虚拟机的二进制指令格式 ...

  4. 利用Vue 脚手架 开发chrome 插件,太方便了

    前言 一个 Chrome 插件,核心就是 manifest.json 文件,manifest.json 下的属性 content_scripts 指定inject的脚本列表 js,css [ inje ...

  5. 使用 React.js 开发 Chrome 插件

    (点击上方公众号,可快速关注) 来源:UncleChen unclechen.github.io/2017/06/16/使用ReactJS开发Chrome插件/ 一.背景 相信看到这篇文章的人应该都用 ...

  6. 记录--使用Vue开发Chrome插件

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 环境搭建 Vue Web-Extension - A Web-Extension preset for VueJS (vue-web-ex ...

  7. 开发chrome插件(扩展)

    官方文档 https://developer.chrome.com/extensions/getstarted.html [干货]Chrome插件(扩展)开发全攻略 http://blog.haoji ...

  8. React开发chrome插件系列教程之chrome插件基本介绍

    文章目录 chrome插件能干什么 chrome插件的版本 chrome插件的浏览器支持 chrome插件的功能组成 manifest.json popup content script backgr ...

  9. 试着开发chrome插件

    我的第一个chrome插件,是app形式的 代码如下 创建一个文件: 1.manifest.json 1 { 2 "version": "1.0", 3 &qu ...

最新文章

  1. 网民关注iPhone、Google、微软和安全
  2. sicily 1068. Euro Efficiency
  3. 怎么查看mysql正在运行的语句_MySQL如何查询当前正在运行的SQL语句
  4. 与素数有关的一些性质及证明(一)
  5. Struts2之命名空间与Action的三种创建方式
  6. HashMap中,比较key是否相等为什么要重写equal() 和hashCode()这两个方法?
  7. iOS:const的使用
  8. spring常见用法之安全模块(注册登录模块)
  9. eclipse 图形界面设计技巧——JLabel
  10. 苹果Mac电脑缓存如何清理?
  11. 【转】精彩RSS源推荐
  12. 蓝桥杯练习题之数列特征
  13. 关于图灵机的妙文(3)——图灵机杂思(rev#2)(刘未鹏)
  14. kvaser leaf light v2 安装 UBUNTU
  15. js几行代码搞定html转图片制作海报,html2canvas应用实例
  16. 【推荐+转摘】如何又快又好的做出一份优质PPT
  17. Unity3d实现双人网络坦克大战
  18. 带你认识不一样的常春藤之一的普林斯顿大学
  19. 程序员应该如何读好书?
  20. Java中,通过synchronizedXxx()将线程不安全的集合转换成线程安全的集合

热门文章

  1. Linux下系统恢复
  2. 最近用到ListView需要几人人物,于是整理了下以前看的玄幻小说人名,时间不够,只整理了几本,凑合用着 1》诛仙
  3. 【Net】全球十大搜索引擎,你听过几个?
  4. 【模拟 简易银行系统~python】
  5. 函数自变量与因变量的关系
  6. 饥荒机器人怎么解锁_《饥荒》全人物解锁属性及技能详解 全人物介绍
  7. 病毒无孔不入:电邮一打开病毒自然来(转)
  8. DHU Matlab Experiment【6】作业记录_第七章
  9. js添加多marker 高德地图_web开发如何使用高德地图API(四)通过AMap.Marker自定义标点...
  10. h5 java实现微信分享_WebApp实现微信分享功能