-
2021-07-29 15:43:09
Google chrome 浏览器开发vue项目时,需要安装vue浏览器插件。
Vue.js devtools可以方便查看vue组件,events, 路由,vuex等信息。
这是未安装时的*warning*
这是浏览器扩展程序中的插件
步骤如下:
1. 进入warning中提示的github仓库
https://github.com/vuejs/vue-devtools
可以下载zip包,也可以clone仓库。这里我下载的压缩包。
2. 解压后,在终端进入文件夹路径。
Tips 解压后的文件夹名称一定要与package.json中的name一致。否则build报错。
这里下载下来的文件夹名称是devtools-main,手动改成vue-devtools
执行:
cnpm install
结束后,再执行:
cnpm run build
最后在浏览器扩展程序中,加载已解压的扩展程序
选中
vue-devtools/packages/shell-chrome
添加成功!
更多相关内容 -
vue开发浏览器插件
2021-02-25 16:52:00vue-devtools-5.3.4.zip 适用于vue2.0 3.0未测试 -
vue开发浏览器调试插件
2018-04-09 14:39:03vue开发浏览器调试插件 vue开发浏览器调试插件 vue开发浏览器调试插件 vue开发浏览器调试插件 -
Chrome浏览器的vue开发插件
2018-09-27 15:22:56Chrome浏览器的vue开发插件,解决本地扩展程序中没有vue的情况,对前端页面进行高效调试 -
用VueJS写一个Chrome浏览器插件的实现方法
2020-10-17 08:49:24This extension demonstrates a browser action with kittens. -
vue-cli3开发Chrome Extension实践 | vue开发浏览器插件 | vue开发chrome插件
2022-03-03 20:58:21之前找了不少如何开发谷歌插件的文章,结果发现都是些很基础的内容,并没有写到如何...后来发现了vue-cli-plugin-chrome-ext插件,通过这个插件能很方便地用vue-cli3来开发谷歌插件,并能直接引用各种UI框架跟npm插件。转自: Mrli2016 的博客 vue-cli3开发Chrome Extension实践
简介
之前找了不少如何开发谷歌插件的文章,结果发现都是些很基础的内容,并没有写到如何快速编译打包插件。我就在想为什么不能通过webpack来打包插件呢?如果通过webpack编译的话,就能使开发过程变得更舒服,使文件结构趋向模块化,并且打包的时候直接编译压缩代码。后来发现了vue-cli-plugin-chrome-ext插件,通过这个插件能很方便地用vue-cli3来开发谷歌插件,并能直接引用各种UI框架跟npm插件。
tip:如果你没接触过谷歌插件开发的话建议先看看基础文档:
环境需求
- node
- yarn
- vue cli
注意:因开发环境随时间前进,存在版本优化升级,按本文操作可能存在个别微差,有能力者自行解决,如无法解决可在文末下载已搭建好的框架模板,或调整到和我一致的开发环境
搭建环境
-
创建一个vue-cli3项目: vue create vue-extension,对话流程选择默认就行。
-
进入项目cd vue-extension
-
安装vue-cli-plugin-chrome-ext插件:vue add chrome-ext,根据安装对话选项设置好。
-
删除vue-cli3无用文件跟文件夹:src/main.js、src/components
运行项目
- 运行开发环境
npm run build-watch
运行开发环境,对修改文件进行实时编译并自动在根目录下生成dist文件夹,然后在浏览器上加载dist文件夹完成插件安装。(注意:
修改background文件跟manifest.json文件并不能实时刷新代码,需要重新加载插件才行。后面已经有实时刷新的解决方法)- 运行生产环境
npm run build
运行生产环境编译打包,将所有文件进行整合打包。
浏览器加载生成的dish
引入element UI
- 目前的插件加载到浏览器后弹出页面是这种界面: 平时我们肯定要引入好看的UI框架的,在这里我们可以引入element-ui
npm install element-ui
如果出现"Not Found - Get … @vue%2fvue-loader-…"的情况多半是选择vue2开发但vue cli版本过高导致,解决办法可以调整vue cli版本或安装指定"core-js"版本号(如3.6.5)
- 考虑到插件打包后的文件大小,最后通过按需加载的方式来引入组件,按照element-ui官方的按需加载方法,要先安装babel-plugin-component插件:
npm install babel-plugin-component -D
- 然后,将babel.config.js修改为
module.exports = { presets: [ '@vue/app' ], "plugins": [ [ "component", { "libraryName": "element-ui", "styleLibraryName": "theme-chalk" } ] ] }
- 接下来修改popup相关文件引入所需组件, src/popup/index.js内容
import Vue from "vue"; import AppComponent from "./App/App.vue"; Vue.component("app-component", AppComponent); import { Card } from 'element-ui'; Vue.use(Card); new Vue({ el: "#app", render: createElement => { return createElement(AppComponent); } });
- src/popup/App/App.vue 内容
<template> <el-card class="box-card"> <div slot="header" class="clearfix" > <span>卡片名称</span> <el-button style="float: right; padding: 3px 0" type="text" >操作按钮</el-button> </div> <div v-for="o in 4" :key="o" class="text item" > {{'列表内容 ' + o }} </div> </el-card> </template> <script> export default { name: 'app', } </script> <style> .box-card { width: 300px; } </style>
- 渲染效果
当然,不仅仅是插件内部的页面,还可以将element-ui组件插入到content页面。
content.js(注入web脚本)使用element-ui组件
content.js主要作用于浏览网页,对打开的网页进行插入、修改DOM,对其进行操作交互。别觉得element-ui只能配合vue使用,其实就是一个前端框架,只要我们引入了就能使用,webpack会自动帮我们抽离出来编译打包。
根据评论的朋友提示,可以通过Chrome插件的chrome.extension.getURLAPI来引入字体文件,解决element-ui无法引入相对路径的字体文件问题。
- 首先我们创建src/content/index文件,在里面我们通过chrome.extension.getURLAPI来引入插件的字体文件,内容
import { Message, MessageBox } from 'element-ui'; // 通过Chrome插件的API加载字体文件 (function insertElementIcons() { let elementIcons = document.createElement('style') elementIcons.type = 'text/css'; elementIcons.textContent = ` @font-face { font-family: "element-icons"; src: url('${ window.chrome.extension.getURL("fonts/element-icons.woff")}') format('woff'), url('${ window.chrome.extension.getURL("fonts/element-icons.ttf ")}') format('truetype'); /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/ } ` document.head.appendChild(elementIcons); })(); MessageBox.alert('这是一段内容', '标题名称', { confirmButtonText: '确定', callback: action => { Message({ type: 'info', message: `action: ${ action }` }); } })
content.js里调用了chrome API而在vue里并不知道chrome是全局变量,可执行npm install --save @types/chrome 或 在根目录添加 .eslintrc.js 进行全局变量声明
- vue.config.js增加content.js文件的打包配置,因为content.js(background.js同样可以只生成js文件)只有js文件,不用像app模式那样打包生成相应的html文件。这里我们还要对字体打包配置处理下,因为默认打包后的文件名是带有hash值的,在这里我们要去除掉,完整内容如下
const CopyWebpackPlugin = require("copy-webpack-plugin"); const path = require("path"); // Generate pages object const pagesObj = {}; const chromeName = ["popup", "options"]; chromeName.forEach(name => { pagesObj[name] = { entry: `src/${name}/index.js`, template: "public/index.html", filename: `${name}.html` }; }); // 生成manifest文件 const manifest = process.env.NODE_ENV === "production" ? { from: path.resolve("src/manifest.production.json"), to: `${path.resolve("dist")}/manifest.json` } : { from: path.resolve("src/manifest.development.json"), to: `${path.resolve("dist")}/manifest.json` }; const plugins = [ CopyWebpackPlugin([ manifest ]) ] module.exports = { pages: pagesObj, // // 生产环境是否生成 sourceMap 文件 productionSourceMap: false, configureWebpack: { entry: { 'content': './src/content/index.js' }, output: { filename: 'js/[name].js' }, plugins: plugins }, css: { extract: { filename: 'css/[name].css' // chunkFilename: 'css/[name].css' } }, chainWebpack: config => { // 处理字体文件名,去除hash值 const fontsRule = config.module.rule('fonts') // 清除已有的所有 loader。 // 如果你不这样做,接下来的 loader 会附加在该规则现有的 loader 之后。 fontsRule.uses.clear() fontsRule.test(/\.(woff2?|eot|ttf|otf)(\?.*)?$/i) .use('url') .loader('url-loader') .options({ limit: 1000, name: 'fonts/[name].[ext]' }) } };
- 最后在manifest.development.json加载content.js文件,以及将字体文件添加到网页可加载资源字段web_accessible_resources里去
{ "manifest_version": 2, "name": "chrome-ext", "description": "chrome extension", "version": "0.0.1", "options_page": "options.html", "browser_action": { "default_popup": "popup.html" }, "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'", "content_scripts": [{ "matches": [ "*://*.baidu.com/*" ], "css": [ "css/content.css" ] ,"js": [ "js/content.js" ], "run_at": "document_end" }], "web_accessible_resources": ["fonts/*"] }
- 然后浏览器重新加载插件后打开https://www.baidu.com/网址后可看到:
实时刷新插件
之前写的时候发现单纯地通过vue-cli3更新代码并不能使插件的background.js、content.js也跟着更新,因为代码已经加载到浏览器了,浏览器并不会监听这些文件的变化。也是通过评论的朋友推荐,通过crx-hotreload可以完美实现实时刷新功能,而不用重新手动加载。代码还简单易用,在这里我们直接将代码复制到src/utils/hot-reload.js文件:
// 代码来源:https://github.com/xpl/crx-hotreload/edit/master/hot-reload.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/5 if (tabs[0]) { window.chrome.tabs.reload(tabs[0].id) } window.chrome.runtime.reload() }) } const watchChanges = (dir, lastTimestamp) => { timestampForFilesInDirectory(dir).then(timestamp => { if (!lastTimestamp || (lastTimestamp === timestamp)) { setTimeout(() => watchChanges(dir, timestamp), 1000) // retry after 1s } else { reload() } }) } window.chrome.management.getSelf(self => { if (self.installType === 'development') { window.chrome.runtime.getPackageDirectoryEntry(dir => watchChanges(dir)) } })
- 然后在vue.config.js对热刷新代码进行处理,如果是开发环境的话就将其复制到assets文件夹里面:
// vue.config.js ... // 在这段下面添加 const plugins = [ CopyWebpackPlugin([ manifest ]) ] // 开发环境将热加载文件复制到dist文件夹 if (process.env.NODE_ENV !== 'production') { plugins.push( CopyWebpackPlugin([{ from: path.resolve("src/utils/hot-reload.js"), to: path.resolve("dist") }]) ) } ...
-
vue.config.js 配置如图
-
最后只要在开发环境manifest.development.json里配置一下,将hot-reload.js加载到background运行环境中即可:
"background": { "scripts": ["hot-reload.js"] }
添加打包文件大小预览配置
既然用了vue-cli3了,怎能不继续折腾呢,我们平时用webpack开发肯定离不开打包组件预览功能,才能分析哪些组件占用文件大,该有的功能一个都不能少😎。这么实用的功能,实现起来也无非就是添加几行代码的事:
// vue.config.js module.export = { /* ... */ chainWebpack: config => { // 查看打包组件大小情况 if (process.env.npm_config_report) { // 在运行命令中添加 --report参数运行, 如:npm run build --report config .plugin('webpack-bundle-analyzer') .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin) } } }
-
配置代码如图
-
就辣么简单,然后运行npm run build --report看看效果
npm run build --report
自动打包zip
做过Chrome插件的都知道,提交到谷歌插件市场的话需要打包为zip文件才行。如果每次我们都需要将编译文件打包成zip的话就太麻烦了,这种每次都要经历的重复流程当然是交给程序来处理啦。 想打包zip的话首先要安装zip-webpack-plugin插件到开发环境:
npm install --save-dev zip-webpack-plugin
- 然后添加打包代码到vue.config.js:
- vue.config.js最终全文代码
// vue.config.js const CopyWebpackPlugin = require("copy-webpack-plugin"); const ZipPlugin = require('zip-webpack-plugin'); const path = require("path"); // Generate pages object const pagesObj = {}; const chromeName = ["popup", "options"]; chromeName.forEach(name => { pagesObj[name] = { entry: `src/${name}/index.js`, template: "public/index.html", filename: `${name}.html` }; }); // 生成manifest文件 const manifest = process.env.NODE_ENV === "production" ? { from: path.resolve("src/manifest.production.json"), to: `${path.resolve("dist")}/manifest.json` } : { from: path.resolve("src/manifest.development.json"), to: `${path.resolve("dist")}/manifest.json` }; const plugins = [ CopyWebpackPlugin([ manifest ]) ] // 开发环境将热加载文件复制到dist文件夹 if (process.env.NODE_ENV !== 'production') { plugins.push( CopyWebpackPlugin([{ from: path.resolve("src/utils/hot-reload.js"), to: path.resolve("dist") }]) ) } // 生产环境打包dist为zip if (process.env.NODE_ENV === 'production') { plugins.push( new ZipPlugin({ path: path.resolve("dist"), filename: 'dist.zip', }) ) } module.exports = { pages: pagesObj, // // 生产环境是否生成 sourceMap 文件 productionSourceMap: false, configureWebpack: { entry: { 'content': './src/content/index.js' }, output: { filename: 'js/[name].js' }, plugins: plugins }, css: { extract: { filename: 'css/[name].css' // chunkFilename: 'css/[name].css' } }, chainWebpack: config => { // 处理字体文件名,去除hash值 const fontsRule = config.module.rule('fonts') // 清除已有的所有 loader。 // 如果你不这样做,接下来的 loader 会附加在该规则现有的 loader 之后。 fontsRule.uses.clear() fontsRule.test(/\.(woff2?|eot|ttf|otf)(\?.*)?$/i) .use('url') .loader('url-loader') .options({ limit: 1000, name: 'fonts/[name].[ext]' }); // 查看打包组件大小情况 if (process.env.npm_config_report) { config .plugin('webpack-bundle-analyzer') .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin) } } };
搞定收工!
结语
事实证明,vue-cli3很强大,vue相关的插件并不是不能应用于开发浏览器插件,element-ui也不仅限于vue的运用。只有你想不到,没有做不到的事😁。
tip:如果你懒得从头开始搭建模板的话也可以从GitHub拉取 vue-extension-template 或 csdn 下载
-
vue浏览器插件开发工具devtools
2020-07-18 07:04:18vue浏览器插件开发工具devtools,使用方式:打开谷歌扩展程序页面,并打开该页的开发者模式按钮,点击加载已解压的扩展程序,选择解压后的文件,重启浏览器,打开浏览器开发工具即可使用. -
使用 vue3.x版本开发 chrome插件
2020-12-31 14:37:15使用vue开发chrome浏览器插件,可以方便前端人员开发插件页面,不管是popup页面,content页面等都可以使用vue开发模式很方便的开发需求 码云地址:https://gitee.com/guoqiankun/my-vue3-plugin github地址:... -
15000字大章带你一步一步使用Vue3开发chrome浏览器插件
2020-12-31 14:00:00之前写过一篇 chrome 浏览器插件开发的文章 全方面手把手从0到1带你开发谷歌浏览器插件 ,但是不是 vue/react 这种第三方框架的,是原生和 jquery 混合的,但是那种开发前端方式比较麻烦,所以下面是用 vue 来开发...之前写过一篇 chrome 浏览器插件开发的文章 全方面手把手从0到1带你开发谷歌浏览器插件 ,但是不是
vue/react
这种第三方框架的,是原生和jquery
混合的,但是那种开发前端方式比较麻烦,所以下面是用vue
来开发插件github地址:https://github.com/18055975947/my-vue3-plugin
码云地址:https://gitee.com/guoqiankun/my-vue3-plugin一、创建 Vue 项目
使用
vue-cli
创建vue3.x
版本的vue
项目
vue create my-vue3-plugin
如果在创建项目的时候报错,报错内容如下:error Couldn't find package "postcss-normalize-string@^4.0.2" required by "cssnano-preset-default@^4.0.0" on the "npm" registry. Error: Couldn't find package "@vue/cli-overlay@^4.5.9" required by "@vue/cli-service@~4.5.0" on the "npm" registry. at MessageError.ExtendableBuiltin (/usr/local/lib/node_modules/yarn/lib/cli.js:243:66) at new MessageError (/usr/local/lib/node_modules/yarn/lib/cli.js:272:123) at PackageRequest.<anonymous> (/usr/local/lib/node_modules/yarn/lib/cli.js:38988:17) at Generator.throw (<anonymous>) at step (/usr/local/lib/node_modules/yarn/lib/cli.js:92:30) at /usr/local/lib/node_modules/yarn/lib/cli.js:105:13 at process._tickCallback (internal/process/next_tick.js:68:7) ERROR command failed: yarn
可以参考 使用
vue-cli
创建vue3.x
版本项目报错 文章来处理
此时文件目录为:. ├── README.md ├── babel.config.js ├── package.json ├── public │ ├── favicon.ico │ └── index.html ├── src │ ├── App.vue │ ├── assets │ │ └── logo.png │ ├── components │ │ └── HelloWorld.vue │ └── main.js └── yarn.lock
二、修改项目
因为我们要开发
chrome
插件项目,而这种生成的vue
项目里面的文件夹和文件很多我们不需要,所以我们需要处理下:- 在根目录下创建
vue.config.js
的vue
配置文件; - 把
src
文件夹下面的app.vue、components
文件夹删除 - 在
assets
文件中创建images
文件夹,并在images
文件夹里面添加自己插件的icon
- 删除根目录下的
public
文件夹 - 在
src
文件夹下 创建background、content、plugins、popup、utils
文件夹 - 在
background
文件夹下创建main.js
- 在
content
文件夹下创建components
文件夹和main.js
,components
文件夹下创建app.vue
- 在
plugins
文件夹下创建inject.js、manifest.json
文件 - 在
popup
文件夹下创建components
文件夹main.js
和index.html
,components
文件夹下创建app.vue
步骤解析:
vue.config.js
是vue
项目的打包、运行、等的配置文件,我们需要生成插件项目,这个文件需要创建并且自行配置- 删除多余的文件,我们插件里面目前只有 需要一个
popup
页面,不需要 外部的app.vue
和 组件 - 自己的插件
icon
,按照16 * 16、48 * 48、128 * 128
三个尺寸 - 不需要
public
文件夹里面的index.html
- 创建我们插件需要的
background.js、content.js、popup页面、插件配置
等 - 创建
background.js
文件 - 创建
content.js
文件 - 创建
popup.js、popup.html
文件
此时文件目录:
. ├── README.md ├── babel.config.js ├── package.json ├── src │ ├── assets │ │ ├── images │ │ │ ├── icon128.png │ │ │ ├── icon16.png │ │ │ └── icon48.png │ │ └── logo.png │ ├── background │ │ └── main.js │ ├── content │ │ ├── components │ │ │ └── app.vue │ │ └── main.js │ ├── main.js │ ├── plugins │ │ ├── inject.js │ │ └── manifest.json │ ├── popup │ │ ├── components │ │ │ └── app.vue │ │ ├── index.html │ │ └── main.js │ └── utils ├── vue.config.js └── yarn.lock
三、配置项目
1、
plugins/manifest.json
文件配置先配置
manifest.json
文件,在按照此文件配置vue.config.js
文件{ "manifest_version": 2, "name": "my-vue3-plugin", "description": "基于vue3.x版本的chrome插件", "version": "1.0.0", "browser_action": { "default_title": "my-vue3-plugin", "default_icon": "assets/images/icon48.png", "default_popup": "popup.html" }, "permissions": [], "background": { "scripts": ["js/background.js"] }, "icons": { "16": "assets/images/icon16.png", "48": "assets/images/icon48.png", "128": "assets/images/icon128.png" }, "content_scripts": [ { "matches": ["https://*.taobao.com/*"], "css": ["css/content.css"], "js": ["js/content.js"], "run_at": "document_idle" } ], "web_accessible_resources": ["js/inject.js"] }
解析:
browser_action
中的default_popup
配置为 和manifest.json
文件一级的popup.html
browser_action
中的default_icon
配置为assets/images/icon48.png
background
配置为js/background.js
icons
文件进行 项目的配置content_scripts
配置对应的js、css、和 matches
web_accessible_resources
配置网页内置js/inject.js
2、配置
vue.config.js
文件通过上面的
manifest.json
文件可以看出,我们需要配置js
文件夹,css
文件夹,popup.html
文件,background.js
文件,inject.js
文件,content.js
文件,content.css
文件;1. 添加
copy-webpack-plugin
模块,用于复制文件我们需要把
plugins
文件夹下的文件复制到打包之后的dist
文件中安装:
yarn add copy-webpack-plugin@6.0.2 --dev
2. 文件内容
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.js configureWebpack: { entry: { content: "./src/content/main.js", background: "./src/background/main.js" }, output: { filename: "js/[name].js" }, plugins }, // 配置 content.css css: { extract: { filename: "css/[name].css" } } }
3. 解析:
copyFiles
是复制文件的字段pages
是配置多页面的文件字段configureWebpack
来配置content.js
、background.js
文件css
配置content.css
文件
3、
popup
文件夹修改从上面的配置我们知道了,
popup
文件夹是用来生成browser_action
的popup.html
文件的,所以此时我们来写入popup
文件夹1.
popup/index.html
popup
文件夹下的index.html
文件,因为这个是html
文件,我们就只需要按照vue create
生成的项目中的public
文件夹下的index.html
文件内容拷贝过来即可,顺便把favicon
删除,把title
修改下<!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>my-vue-chrome-plugin</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> <!-- built files will be auto injected --> </body> </html>
2.
popup/main.js
这个是
vue
项目的入口配置文件,就按照src
下面的main.js
复制过来即可,别忘了改下 大小写import { createApp } from 'vue' import app from './components/app.vue' createApp(app).mount('#app')
3.
popup/components/app.vue
此文件就是正常的
vue
文件,按照平时写vue
项目开发即可<template> <div class="popup_page"> this is popup page <div class="popup_page_main"> this is popup page main </div> </div> </template> <script> export default { } </script> <style></style>
4、
content
文件夹修改content
文件夹下是对应chrome
插件的content.js
,这个可以在嵌入页面里面渲染页面,我们也可以用vue
开发1.
content/components/app.vue
正常的
vue
开发<template> <div class="content_page"> content_page <div class="content_page_main"> content_page_main </div> </div> </template> <script> export default { } </script> <style> </style>
2.
content/main.js
main.js
这个文件是比较重要的,是通过这个文件引入vue
组件以及使用vue
开发content
页面的,所以这个页面,需要在插件嵌入的页面,增加一个dom
元素,并把这个插件的content
页面,渲染进去。import { createApp } from 'vue' import app from './components/app.vue' joinContent(app) function joinContent (element) { const div = document.createElement('div') div.id = 'joinContentApp' document.body.appendChild(div) console.log(div) createApp(element).mount('#joinContentApp') }
解析:
- 引入
vue3
的createApp
- 引入
app
组件 - 创建一个
id
为joinContentApp
的dom
元素,把此元素插入body
中,并把应用实例挂载到此dom
上
5、
background
文件夹此文件夹是对应的
background.js
文件,可以只写一个简单的日志打印即可console.log('this is background main.js')
6、
yarn run build
打包此时,先进行
run build
打包,如果你报错了,是eslint
报错,可以进行在.eslintrc.js
文件中进行配置,添加一些我常用的eslint
配置module.exports = { root: true, env: { node: true }, extends: [ 'plugin:vue/vue3-essential', '@vue/standard' ], parserOptions: { parser: 'babel-eslint' }, rules: { "generator-star-spacing": "off", "object-curly-spacing": "off", "no-var": "error", "semi": 0, "eol-last": "off", "no-tabs": "off", "indent": "off", "quote-props": 0, "no-mixed-spaces-and-tabs": "off", "no-trailing-spaces": "off", "arrow-parens": 0, "spaced-comment": "off", "space-before-function-paren": "off", "no-empty": "off", "no-else-return": "off", "no-unused-vars": [2, {"vars": "all", "args": "after-used"}], "no-console": "off", 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off' } }
然后在进行打包
此时的文件内容
. ├── README.md ├── babel.config.js ├── dist │ ├── assets │ │ ├── images │ │ │ ├── icon128.png │ │ │ ├── icon16.png │ │ │ └── icon48.png │ │ └── logo.png │ ├── js │ │ ├── background.js │ │ ├── chunk-vendors.fa86ccee.js │ │ ├── content.js │ │ ├── inject.js │ │ └── popup.js │ ├── manifest.json │ └── popup.html ├── package.json ├── src │ ├── assets │ │ ├── images │ │ │ ├── icon128.png │ │ │ ├── icon16.png │ │ │ └── icon48.png │ │ └── logo.png │ ├── background │ │ └── main.js │ ├── content │ │ ├── components │ │ │ └── app.vue │ │ └── main.js │ ├── main.js │ ├── plugins │ │ ├── inject.js │ │ └── manifest.json │ ├── popup │ │ ├── components │ │ │ └── app.vue │ │ ├── index.html │ │ └── main.js │ └── utils ├── vue.config.js └── yarn.lock
此时我们可以看到
dist
文件夹下已经按照我们需要的内容进行打包了,但是没有css
文件夹那是因为我们没有写入css
7、引入
less
我们写页面少不了使用
css
,现在都是使用预处理器,我比较倾向于less
,所以我使用less、less-loader
1. 引入
less less-loader
yarn add less less-loader --dev
2. 修改
app.vue
文件然后我们在
content/components/app.vue
和popup/components/app.vue
文件中写入css
样式content/components/app.vue
<template> <div class="content_page"> content_page <div class="content_page_main"> content_page_main </div> </div> </template> <script> export default { } </script> <style lang="less" scoped> .content_page{ color: red; position: fixed; z-index: 100001; right: 10px; bottom: 10px; .content_page_main{ color: green; } } </style>
popup/components/app.vue
<template> <div class="popup_page"> this is popup page <div class="popup_page_main"> this is popup page main </div> </div> </template> <script> export default { } </script> <style lang="less" scoped> .popup_page{ color: red; .popup_page_main{ color: green; } } </style>
3.
yarn run build
打包此时
tree dist
查看dist
文件夹内容dist ├── assets │ ├── images │ │ ├── icon128.png │ │ ├── icon16.png │ │ └── icon48.png │ └── logo.png ├── css │ ├── content.css │ └── popup.css ├── js │ ├── background.js │ ├── chunk-vendors.4f73d0d4.js │ ├── content.js │ ├── inject.js │ └── popup.js ├── manifest.json └── popup.html
我们可以看到,我们通过
vue.config.js
文件配置的内容都已经生成到dist
文件夹中了四、导入插件项目
1、在谷歌拓展程序中打开我们的插件
点击 加载已解压的拓展程序,选择我们的
dist
文件夹,此时我们的插件就被引入进来了2、打开 淘宝首页
1. 为什么打开淘宝首页呢?
因为我们在
manifest.json
中的content_scripts
中配置"matches": ["https://*.taobao.com/*"]
2. 点击右上角的插件
icon
我们可以看到我们的popup
页面已经我们给它写的样式3、我们的
content
文件呢?我们在
content
文件中配置的main.js
和app.vue
也写入了样式,也挂载到dom
实例上了,但是为什么没有渲染,也没有打印function joinContent (element) { const div = document.createElement('div') div.id = 'joinContentApp' document.body.appendChild(div) console.log(div) createApp(element).mount('#joinContentApp') }
我们在
js
文件中有个console.log
日志输入,但是可以看到淘宝页面的控制台并没有输入1. 为什么没有输出
因为我们是用的
vue
开发项目,在main.js
中是用的vue
开发,所以我们得引入vue
文件,得在content
中引入vue
才可以2. 解决方法,引入
vue
我们可以看到
dist
文件夹下面有一个chunk-vendors.4f73d0d4.js
,这个就是vue
打包之后的文件,我们先在dist
中的manifest.json
文件先把它引入进来先看下dist/manifest.json
文件下的content_scripts
字段"content_scripts": [ { "matches": ["https://*.taobao.com/*"], "css": ["css/content.css"], "js": ["js/chunk-vendors.4f73d0d4.js", "js/content.js"], "run_at": "document_idle" } ],
此时,拓展程序页面刷新插件,并刷新淘宝首页,可以看到
此时可以看到我们的content
文件已经输出了。4、
background.js
文件还记得我们在
background
文件夹下中的main.js
写入日志输出吗?console.log('this is background main.js')
我们打开拓展程序,找到我们的插件,点击 背景页 按钮
此时,背景页的控制台就出来,我们可以看到我们的日志输出,好像并没有输出我们的日志???1. 原因
此问题的原因和上面的
content
文件的原因是一致的,也是没有引入vue
文件2. 解决,引入
vue
dist/manifest.json
中background
字段"background": { "scripts": ["js/chunk-vendors.4f73d0d4.js", "js/background.js"] },
此时,刷新插件,可以看到日志输出
5、引入
inject
文件1. 首先我们在
plugins/inject.js
文件中输出日志console.log('this is my inject.js')
2. 然后在
content/main.js
文件中引入inject.js
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') } 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) }) }
3.
yarn run build
打包此时打包可以发现报错了
yarn run v1.22.10 $ vue-cli-service build ⠼ Building for production... ERROR Failed to compile with 1 error 上午11:12:48 error in ./src/content/main.js Module Error (from ./node_modules/thread-loader/dist/cjs.js): /Users/guoqiankun/work/chromePlugin/my-vue3-plugin/src/content/main.js 21:16 error 'chrome' is not defined no-undef ✖ 1 problem (1 error, 0 warnings) ERROR Build failed with errors. error Command failed with exit code 1. info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
error 'chrome' is not defined no-undef
我们在上面插入
jnject
文件使用的chrome
未定义,那我们就定义一下;4. 修改
.eslintrc.js
文件root: true, globals: { chrome: true, }, env: { node: true },
增加一个
globals
字段,里面chrome: true
然后在进行
yarn run build
打包然后我们可以看到
dist/manifest.json
文件中的content_scripts
和background/scripts
已经没有引入vue
了,所以我们不能在dist
文件夹中修改,我们要在plugins/manifest.json
文件中修改但是我们可以看到,我们每次打包生成的
chunk-vendors.js
会跟一个hash
,因为我们此时没有修改别的文件,所以hash
后缀没有变化,但是如果我们改了内容之后在yarn run build
呢?此时hash
就会变化,总不能在改一次manifest.json
再打一次包吧…6、修改
vue.config.js
文件,让打包时生成的chunk-vendors.js
不带hash
1. 配置
chainWebpack
字段配置
chainWebpack
字段,对config
内容进行处理module.exports = { pages, productionSourceMap: false, // 配置 content.js background.js configureWebpack: { entry: { content: "./src/content/main.js", background: "./src/background/main.js" }, output: { filename: "js/[name].js" }, plugins }, // 配置 content.css css: { 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() } } }
2. 修改
plugin/manifest.json
文件在此文件中引入
chunk-vendors.js
plugin/manifest.json
"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_scripts": [ { "matches": ["https://*.taobao.com/*"], "css": ["css/content.css"], "js": ["js/chunk-vendors.js", "js/content.js"], "run_at": "document_idle" } ],
3.
yarn run build
打包dist ├── assets │ ├── images │ │ ├── icon128.png │ │ ├── icon16.png │ │ └── icon48.png │ └── logo.png ├── css │ ├── content.css │ └── popup.css ├── js │ ├── background.js │ ├── chunk-vendors.js │ ├── content.js │ ├── inject.js │ └── popup.js ├── manifest.json └── popup.html
4. 刷新插件,刷新页面
属性插件,刷新页面,之后可以看到
五、热加载
此时我们的
vue
开发插件项目已经基本上可以了,剩下的就是按照需求开发插件页面,按照需求添加manifest.json
字段即可,但是我们不能每一次想看样式就打个包,然后属性插件,刷新页面看下,这样也可以,但是我们是开发,这样效率比较低,我不服…所以我们需要添加一下热加载
1、热加载
在
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/5 if (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;
2、引入
在
bckground/main.js
中 引入import hotReload from '@/utils/hotReload' hotReload() console.log('this is background main.js')
3、修改
package.json
中的scripts
1. 增加一个
watch
用来监听打包"scripts": { "watch": "vue-cli-service build --watch", "serve": "vue-cli-service serve", "build": "vue-cli-service build", "lint": "vue-cli-service lint" },
2. 此时运行
yarn run watch
yarn run v1.22.10 $ vue-cli-service build --watch ⠙ Building for development... DONE Compiled successfully in 3956ms 上午11:39:00 File Size Gzipped dist/js/chunk-vendors.js 668.79 KiB 122.48 KiB dist/js/content.js 26.47 KiB 3.71 KiB dist/js/popup.js 26.23 KiB 3.55 KiB dist/js/background.js 15.57 KiB 3.30 KiB dist/js/inject.js 0.04 KiB 0.05 KiB dist/css/content.css 0.18 KiB 0.14 KiB dist/css/popup.css 0.11 KiB 0.09 KiB Images and other types of assets omitted. DONE Build complete. Watching for changes...
可以看到一直在监听改变
3. 然后我们刷新插件和页面
发现有一个报错
Uncaught EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "script-src 'self' blob: filesystem:".
4. 按照错误解决问题:
在
plugins/manifest.json
中添加:"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
5. 重新运行
yarn run bild
6. 清除插件错误、刷新插件、淘宝页面
4、修改
content/components/app.vue
文件<template> <div class="content_page"> content_page <div class="content_page_main"> content_page_main </div> <div class="content_page_footer"> content_page_footer </div> </div> </template>
保存
然后发现插件自动刷新、浏览器页面自动刷新。
此时浏览器页面右下角我们新加的内容就展示在上面了。
六、总结
- 使用
vue
开发插件,要先想一下我们要做成什么样 - 针对性的修改对应的文件,按照我们的需求去配置
- 遇到问题先想一下哪一步的问题,为什么出现,可以自己先想想,最后在寻求帮助
- 完结🎉🎉🎉
七、源码地址
github地址:https://github.com/18055975947/my-vue3-plugin
码云地址:https://gitee.com/guoqiankun/my-vue3-plugin
参考资料
- 在根目录下创建
-
谷歌Chrome浏览器VueJS开发插件vue-devtools最新版
2021-10-20 18:21:44根据最新vue插件源码编译,支持最新chrome浏览器,chrome开发者模式选择解压后的目录安装插件 -
vue开发chrome插件,实现获取界面数据和保存到数据库功能
2021-01-18 15:28:46要开启评估平台,查看平台和保存平台,感觉非常繁琐,开发了一款可以获取评估平台数据,查看项目排期和直接保存数据到数据库的chrome插件,由于我需要使用之前vue封装的一个日历插件,这里就用vue来开发这个插件。... -
使用Vue开发Chrome插件
2021-09-18 12:41:45原文链接:使用Vue开发Chrome插件 - 愧怍的小站 (kuizuo.cn) 前言 我当时学习开发Chrome插件的时候,还不会Vue,更别说Webpack了,所以使用的都是原生的html开发,效率就不提了,而这次就准备使用vue-cli来进行编写...原文链接: 使用Vue开发Chrome插件 - 愧怍的小站 (kuizuo.cn)
前言
我当时学习开发Chrome插件的时候,还不会Vue,更别说Webpack了,所以使用的都是原生的html开发,效率就不提了,而这次就准备使用vue-cli来进行编写一个某B站获取视频信息,评论的功能(原本是打算做自动回复的),顺便巩固下chrome开发(快一年没碰脚本类相关技术了),顺便写套模板供自己后续编写Chrome插件做铺垫。
关于Chrome插件开发的基本知识就不赘述了,之前写过一篇原生开发的Chrome插件开发 - 愧怍的小站,里面有附带相关文档链接。
相关代码开源github地址
环境搭建
Vue Web-Extension - A Web-Extension preset for VueJS (vue-web-extension.netlify.app)
npm install -g @vue/cli npm install -g @vue/cli-init vue create --preset kocal/vue-web-extension my-extension cd my-extension npm run server 复制代码
会提供几个选项,如Eslint,background.js,tab页,axios,如下图
选择完后,将会自动下载依赖,通过npm run server将会在根目录生成dist文件夹,将该文件拖至Chrome插件管理便可安装,由于使用了webpack,所以更改代码将会热更新,不用反复的编译导入。
项目结构
├─src | ├─App.vue | ├─background.js | ├─main.js | ├─manifest.json | ├─views | | ├─About.vue | | └Home.vue | ├─store | | └index.js | ├─standalone | | ├─App.vue | | └main.js | ├─router | | └index.js | ├─popup | | ├─App.vue | | └main.js | ├─override | | ├─App.vue | | └main.js | ├─options | | ├─App.vue | | └main.js | ├─devtools | | ├─App.vue | | └main.js | ├─content-scripts | | └content-script.js | ├─components | | └HelloWorld.vue | ├─assets | | └logo.png ├─public ├─.browserslistrc ├─.eslintrc.js ├─.gitignore ├─babel.config.js ├─package.json ├─vue.config.js ├─yarn.lock 复制代码
根据所选的页面,并在src与vue.config.js中配置页面信息编译后dist目录结构如下
├─devtools.html ├─favicon.ico ├─index.html ├─manifest.json ├─options.html ├─override.html ├─popup.html ├─_locales ├─js ├─icons ├─css 复制代码
安装组件库
安装elementUI
整体的开发和vue2开发基本上没太大的区别,不过既然是用vue来开发的话,那肯定少不了组件库了。
要导入Element-ui也十分简单,
Vue.use(ElementUI);
Vue2中怎么导入element,便怎么导入。演示如下不过我没有使用babel-plugin-component来按需引入,按需引入一个按钮打包后大约1.6m,而全量引入则是5.5左右。至于为什么不用,因为我需要在content-scripts.js中引入element组件,如果使用babel-plugin-component将无法按需导入组件以及样式(应该是只支持vue文件按需引入,总之就是折腾了我一个晚上的时间)
安装tailwindcss
不过官方提供了如何使用TailwindCSS,这里就演示一下
在 Vue 3 和 Vite 安装 Tailwind CSS - Tailwind CSS 中文文档
推荐安装低版本,最新版有兼容性问题
npm install tailwindcss@npm:@tailwindcss/postcss7-compat postcss@^7 autoprefixer@^9 复制代码
创建postcss.config.js文件
// postcss.config.js module.exports = { plugins: [ // ... require('tailwindcss'), require('autoprefixer'), // if you have installed `autoprefixer` // ... ] } 复制代码
创建tailwind.config.js文件
// tailwind.config.js module.exports = { purge: { // Specify the paths to all of the template files in your project content: ['src/**/*.vue'], // Whitelist selectors by using regular expression whitelistPatterns: [ /-(leave|enter|appear)(|-(to|from|active))$/, // transitions /data-v-.*/, // scoped css ], } // ... } 复制代码
在src/popup/App.vue中导入样式,或在新建style.css在mian.js中
import "../style.css";
<style> /* purgecss start ignore */ @tailwind base; @tailwind components; /* purgecss end ignore */ @tailwind utilities; </style> 复制代码
从官方例子导入一个登陆表单,效果如下
项目搭建
页面搭建
页面搭建就没什么好说的了,因为使用的是element-ui,所以页面很快就搭建完毕了,效果如图
悬浮窗
悬浮窗其实可有可无,不过之前写Chrome插件的时候就写了悬浮窗,所以vue版的也顺带写一份。
要注意的是悬浮窗是内嵌到网页的(且在document加载前载入,也就是
"run_at": "document_start"
),所以需要通过content-scripts.js才能操作页面Dom元素,首先在配置清单manifest.json与vue.confing.js中匹配要添加的网站,以及注入的js代码,如下"content_scripts": [ { "matches": ["https://www.bilibili.com/video/*"], "js": ["js/jquery.js", "js/content-script.js"], "css": ["css/index.css"], "run_at": "document_start" }, { "matches": ["https://www.bilibili.com/video/*"], "js": ["js/jquery.js", "js/bilibili.js"], "run_at": "document_end" } ] 复制代码
contentScripts: { entries: { 'content-script': ['src/content-scripts/content-script.js'], bilibili: ['src/content-scripts/bilibili.js'], }, }, 复制代码
由于是用Vue,但又要在js中生成组件,就使用
document.createElement
来进行创建元素,Vue组件如下(可拖拽):::danger
如果使用
babel-plugin-component
按需引入,组件的样式将无法载入,同时自定义组件如果编写了style标签,那么也同样无法载入,报错:Cannot read properties of undefined (reading 'appendChild')大致就是css-loader无法加载对应的css代码,如果执意要写css的话,直接在manifest.json中注入css即可
:::
完整代码
// 注意,这里引入的vue是运行时的模块,因为content是插入到目标页面,对组件的渲染需要运行时的vue, 而不是编译环境的vue (我也不知道我在说啥,反正大概意思就是这样) import Vue from 'vue/dist/vue.esm.js'; import ElementUI, { Message } from 'element-ui'; Vue.use(ElementUI); // 注意,必须设置了run_at=document_start此段代码才会生效 document.addEventListener('DOMContentLoaded', function() { console.log('vue-chrome扩展已载入'); insertFloat(); }); // 在target页面中新建一个带有id的dom元素,将vue对象挂载到这个dom上。 function insertFloat() { let element = document.createElement('div'); let attr = document.createAttribute('id'); attr.value = 'appPlugin'; element.setAttributeNode(attr); document.getElementsByTagName('body')[0].appendChild(element); let link = document.createElement('link'); let linkAttr = document.createAttribute('rel'); linkAttr.value = 'stylesheet'; let linkHref = document.createAttribute('href'); linkHref.value = 'https://unpkg.com/element-ui/lib/theme-chalk/index.css'; link.setAttributeNode(linkAttr); link.setAttributeNode(linkHref); document.getElementsByTagName('head')[0].appendChild(link); let left = 0; let top = 0; let mx = 0; let my = 0; let onDrag = false; var drag = { inserted: function(el) { (el.onmousedown = function(e) { left = el.offsetLeft; top = el.offsetTop; mx = e.clientX; my = e.clientY; if (my - top > 40) return; onDrag = true; }), (window.onmousemove = function(e) { if (onDrag) { let nx = e.clientX - mx + left; let ny = e.clientY - my + top; let width = el.clientWidth; let height = el.clientHeight; let bodyWidth = window.document.body.clientWidth; let bodyHeight = window.document.body.clientHeight; if (nx < 0) nx = 0; if (ny < 0) ny = 0; if (ny > bodyHeight - height && bodyHeight - height > 0) { ny = bodyHeight - height; } if (nx > bodyWidth - width) { nx = bodyWidth - width; } el.style.left = nx + 'px'; el.style.top = ny + 'px'; } }), (el.onmouseup = function(e) { if (onDrag) { onDrag = false; } }); }, }; window.kz_vm = new Vue({ el: '#appPlugin', directives: { drag: drag, }, template: ` <div class="float-page" ref="float" v-drag> <el-card class="box-card" :body-style="{ padding: '15px' }"> <div slot="header" class="clearfix" style="cursor: move"> <span>悬浮窗</span> <el-button style="float: right; padding: 3px 0" type="text" @click="toggle">{{ show ? '收起' : '展开'}}</el-button> </div> <transition name="ul"> <div v-if="show" class="ul-box"> <span> {{user}} </span> </div> </transition> </el-card> </div> `, data: function() { return { show: true, list: [], user: { username: '', follow: 0, title: '', view: 0, }, }; }, mounted() {}, methods: { toggle() { this.show = !this.show; }, }, }); } 复制代码
因为只能在js中编写vue组件,所以得用template模板,同时使用了directives,给组件添加了拖拽的功能(尤其是
window.onmousemove
,如果是元素绑定他自身的鼠标移动事件,那么拖拽鼠标将会十分卡顿),还使用了transition来进行缓慢动画效果其中注入的css代码如下.float-page { width: 400px; border-radius: 8px; position: fixed; left: 50%; top: 25%; z-index: 1000001; } .el-card__header { padding: 10px 15px !important } .ul-box { height: 200px; overflow: hidden; } .ul-enter-active, .ul-leave-active { transition: all 0.5s; } .ul-enter, .ul-leave-to { height: 0; } 复制代码
相关逻辑可自行观看,这里不在赘述了,并不复杂。
也顺带是复习一下HTML中鼠标事件和vue自定义命令了
功能实现
主要功能
-
检测视频页面,输出对应up主,关注数以及视频标题播放(参数过多就不一一显示了)
-
监控关键词根据内容判断是否点赞,例如文本出现了下次一定,那么就点赞。
输出相关信息
这个其实只要接触过一丢丢爬虫的肯定都会知道如何实现,通过右键审查元素,像这样
然后使用dom操作,选择对应的元素,输出便可
> document.querySelector("#v_upinfo > div.up-info_right > div.name > a.username").innerText < '老番茄' 复制代码
当然使用JQuery效果也是一样的。后续我都会使用JQuery来进行操作
在src/content-script/bilibili.js中写下如下代码
window.onload = function() { console.log('加载完毕'); function getInfo() { let username = $('#v_upinfo > div.up-info_right > div.name > a.username').text(); let follow = $(`#v_upinfo > div.up-info_right > div.btn-panel > div.default-btn.follow-btn.btn-transition.b-gz.following > span > span > span`).text(); let title = $(`#viewbox_report > h1 > span`).text(); let view = $('#viewbox_report > div > span.view').attr('title'); console.log(username, follow, title, view); } getInfo(); }; 复制代码
重新加载插件,然后输出查看结果
加载完毕 bilibili.js:19 老番茄 1606.0万 顶级画质 总播放数2368406 复制代码
这些数据肯定单纯的输出肯定是没什么作用的,要能显示到内嵌悬浮窗口,或者是popup页面上(甚至发送ajax请求到远程服务器上保存)
对上面代码微改一下
window.onload = function() { console.log('加载完毕'); function getInfo() { let username = $('#v_upinfo > div.up-info_right > div.name > a.username').text().trim() let follow = $(`#v_upinfo > div.up-info_right > div.btn-panel > div.default-btn.follow-btn.btn-transition.b-gz.following > span > span > span`).text(); let title = $(`#viewbox_report > h1 > span`).text(); let view = $('#viewbox_report > div > span.view').attr('title'); //console.log(username, follow, title, view); window.kz_vm.user = { username, follow, title, view, }; } getInfo(); }; 复制代码
其中
window.kz_vm
是通过window.kz_vm = new Vue()
初始化的,方便我们操作vm对象,就需要通过jquery选择元素在添加属性了。如果你想的话也可以直接在content-script.js上编写代码,这样就无需使用window对象,但这样导致一些业务逻辑都堆在一个文件里,所以我习惯分成bilibili.js 然后注入方式为document_end,然后在操作dom元素吗,实现效果如下如果像显示到popup页面只需要通过页面通信就行了,不过前提得先popup打开才行,所以一般都是通过background来进行中转,一般来说很少 content –> popup(因为操作popup的前提都是popup要打开),相对更多的是content –> background 或 popup –> content
content-script主动发消息给后台 我是小茗同学 - 博客园 (cnblogs.com)
实现评论
这边简单编写了一下页面,通过popup给content,让content输入评论内容,与点击发送,先看效果
同样的,找到对应元素位置
// 评论文本框 $('#comment > div > div.comment > div > div.comment-send > div.textarea-container > textarea').val("要回复的内容"); // 评论按钮 $('#comment > div > div.comment > div > div.comment-send > div.textarea-container > button').click(); 复制代码
接着就是写页面通信的了,可以看到是popup向content发送请求
window.onload = function() { console.log('content加载完毕'); function comment() { chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) { let { cmd, message } = request; if (cmd === 'addComment') { $('#comment > div > div.comment > div > div.comment-send > div.textarea-container > textarea').val(message); $('#comment > div > div.comment > div > div.comment-send > div.textarea-container > button').click(); } sendResponse('我收到了你的消息!'); }); } comment(); }; 复制代码
<template> <div> <el-container> <el-header height="24">B站小工具</el-header> <el-main> <el-row :gutter="5"> <el-input type="textarea" :rows="2" placeholder="请输入内容" v-model="message" class="mb-5" > </el-input> <div> <el-button @click="addComment">评论</el-button> </div> </el-row> </el-main> </el-container> </div> </template> <script> export default { name: 'App', data() { return { message: '', list: [], open: false, } }, created() { chrome.storage.sync.get('list', (obj) => { this.list = obj['list'] }) }, mounted() { chrome.runtime.onMessage.addListener(function ( request, sender, sendResponse ) { console.log('收到来自content-script的消息:') console.log(request, sender, sendResponse) sendResponse('我是后台,我已收到你的消息:' + JSON.stringify(request)) }) }, methods: { sendMessageToContentScript(message, callback) { chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) { chrome.tabs.sendMessage(tabs[0].id, message, function (response) { if (callback) callback(response) }) }) }, addComment() { this.sendMessageToContentScript( { cmd: 'addComment', message: this.message }, function () { console.log('来自content的回复:' + response) } ) }, }, } </script> 复制代码
代码就不解读了,调用sendMessageToContentScript方法即可。相关源码可自行下载查看
实现类似点赞功能也是同理的。
整体体验
当时写Chrome插件的效率不能说慢,反正不快就是了,像一些tips,都得自行封装。用过Vue的都知道写网页很方便,写Chrome插件未尝不是编写一个网页,当时的我在接触了Vue后就萌发了使用vue来编写Chrome的想法,当然肯定不止我一个这么想过,所以我在github上就能搜索到相应的源码,于是就有了这篇文章。
如果有涉及到爬取数据相关的,我肯定是首选使用HTTP协议,如果在搞不定我会选择使用puppeteerjs,不过Chrome插件主要还是增强页面功能的,可以实现原本页面不具备的功能。
本文仅仅只是初步体验,简单编写了个小项目,后期有可能会实现一个百度网盘一键填写提取码,Js自吐Hooke相关的。(原本是打算做pdd商家自动回复的,客户说要用客户端而不是网页端(客户端可以多号登陆),无奈,这篇博客就拿B站来演示了)
-
-
Chrom浏览器Vue调试插件最新版本VueDevTools-5.3.3
2020-05-27 14:28:18VueDevTools-5.3.3,Chrom浏览器Vue调试插件目前最新版本,可再开发这工具中进行vue的前端代码调试工作 Chrome and Firefox DevTools extension for debugging Vue.js applications. -
VueTemplate:配置vue项目开发常用插件
2021-05-30 05:22:25基于Vue.js 2.9.6搭建,引入多个插件,实现快速进入项目开发状态,多个用法在项目中都有示例。 引入的插件 Vuex 新建store/store.js,有简单的state、mutations、actions、getters示例 Axios 在utils/http.js里进行... -
浏览器调试vue2工具.zip
2021-11-30 16:18:44浏览器调试vue2工具.zip -
【Chrome浏览器插件开发】浏览器插件运行机制03之实战使用Vue.js 3 + Vite 2开发出简易的浏览器插件(含源码...
2022-04-27 22:13:30vite 是由 vue 作者尤雨溪开发的一种最新的脚手架工具,相比我们熟悉的 webpack 它有一下几个特点: 1、快速的冷启动 2、即时的模块热更新 3、真正的按需编译 Vite,一个基于浏览器原生 ES imports 的开发服务器。... -
vue浏览器调试工具
2018-07-03 11:59:28一款非常好用的vue浏览器调试工具 开发vue使用的插件 浏览器调试工具 -
关于安装了Vue-devtools插件但在浏览器控制台不显示的解决方案
2021-06-23 09:54:26解决方法: 官方建议在项目入口文件(main.js)引入: Vue.config.devtools = true; -
使用vue 开发chrome 插件
2021-09-12 23:06:05原文 项目中需要从百度图片和谷歌图片批量抓取一系列关键词的图片,而且需要是大图资源,不能是缩略图。...于是我想起了以前玩过的杂技——浏览器插件。通过javascript控制浏览器打开网页,搜索关键词,页面 -
Vue Google浏览器插件 Vue Devtools无法使用的解决办法
2019-06-19 18:00:001.插件安装不必多说 一定要用Vue.js 开发版 Vue.min.js 在控制面板就不会显示 2.本地调试 用的是file://协议修改插件允许访问文件网址 打上对勾 ... -
【Vue.js】Vue.js的Chrome浏览器开发插件DevTools的安装步骤
2020-08-31 21:49:33Vue.js的Chrome浏览器开发插件DevTools的源码版本插件的安装步骤和插件安装包(.crx文件)的安装步骤。 -
Vue Devtools | 谷歌(Chrome)浏览器插件
2021-03-03 16:47:43热门 高效开发 Chrome插件 【插件安装教程】 请下载文件后先解压,然后进入页面: chrome://extensions/ 将文件拖拽到该页面,完成安装。 具体步骤: https://t.csdnimg.cn/NxMv 【热门插件】 ·CSDN 浏览器... -
调试vue.js应用的浏览器扩展 Chrome插件
2017-12-07 14:08:15Vue.js devtools:调试vue.js应用的浏览器扩展 Chrome插件 -
Vue.js Devtools | 谷歌(Chrome)浏览器插件
2021-03-03 16:50:22热门 高效开发 Chrome插件 【插件安装教程】 请下载文件后先解压,然后进入页面: chrome://extensions/ 将文件拖拽到该页面,完成安装。 具体步骤: https://t.csdnimg.cn/NxMv 【热门插件】 ·CSDN 浏览器... -
3步添加 vue 谷歌浏览器调试插件(最简单最容易操作的方法)
2020-06-29 15:29:561 下载插件 百度网盘:https://pan.baidu.com/s/1nuD48dlWYd-ERAJ2aiPIsw 提取密码:gaha 解压 2 打开谷歌浏览器 输入网址: chrome://extensions/ 或点击右上角的更所工具—拓展程序 打开右上角的开发者选项 3... -
利用Vue 脚手架 开发chrome 插件,太方便了
2021-12-13 20:49:37前言一个 Chrome 插件,核心就是 manifest.json 文件,manifest.json 下的属性content_scripts 指定inject的脚本列表 js,css 【 injected】browser_action 中 default_popup指定popup... -
vue浏览器本地调试扩展
2020-12-10 16:26:05vue浏览器本地调试扩展 -
X-Browser-Update-Vue-一个Vue.js浏览器更新插件。-Vue.js开发
2021-05-27 22:49:21x-browser-update一个Vue.js浏览器更新插件。 示例#安装依赖项npm install#在本地主机上热加载服务:8080 npm run dev美国x-browser-update一个Vue.js浏览器更新插件。 示例#安装依赖项npm install#可以在本地...