Accidentally, I need to build a chrome plugin. This plugin require to post its data(source html) to restful api and also get data from api. In short, this blog will help u build a chrome plugin project using these tech stack:
- vue
- element ui / iview
- additionally, this plugin can get source html file from the visiting tab page
code repo: https://gitlab.com/goddy-test/public/vue-web-extesion-bp
1. init project
You can follow the official documentation steps.
$ vue init kocal/vue-web-extension tmp2
And I choose these...
? Project name tmp2
? Project description A Vue.js web extension
? Author goddy <wuchuansheng@yeah.net>
? License
? Use Mozilla's web-extension polyfill? (https://github.com/mozilla/webextension-polyfill) No
? Provide an options page? (https://developer.chrome.com/extensions/options) Yes
? Install vue-router? No
? Install vuex? No
? Install axios? Yes
? Install ESLint? No
? Install Prettier? No
? Automatically install dependencies? no
Then install the node modules.
$ cd my-extension
# In China, use cnpm is better.
$ npm install
2. build & run with hot-loading
$ npm run build:dev
$ npm run watch:dev
3. load plugin
open chrome://extensions/ use your chrome.
make sure you have open 'developer model', then click 'load unpacked plugin'. Then the plugin will alert 'Hello world!'.4. add element-ui
# you can use cnpm instead of npm
$ npm i element-ui -S
then, edit src/popup/popup.js
into this
import Vue from 'vue'
import App from './App'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)
/* eslint-disable no-new */
new Vue({
el: '#app',
render: h => h(App)
})
add some element-ui to src/popup/App.vue
<template>
<div>
<p>Hello world!</p>
<el-button type="danger" icon="el-icon-delete" circle />
<el-avatar src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png" />
</div>
</template>
<script>
export default {
data () {
return {}
}
}
</script>
<style lang="scss" scoped>
p {
font-size: 20px;
}
</style>
reload plugin, you can see this、!
you can also add iview in the same way.
5. config global axios
axios is a 'Promise based HTTP client for the browser and node.js'. I use it instead of ajax. Config a global axios may be best practice.
new build src/js/axios.js
, insert below code:
/*
* Reference:
* https://blog.csdn.net/baidu_38492440/article/details/78193766
*/
import axios from 'axios'
import qs from 'qs'
# change to yours
let _BASE_URL = 'http://118.31.52.226/chromit'
# if u r using cookies, set true
axios.defaults.withCredentials=true
// 请求方式的配置
export default {
post(url, data) { // post
return axios({
method: 'post',
baseURL: _BASE_URL,
url,
data: qs.stringify(data),
timeout: 5000,
headers: {
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
}
})
},
get(url, params) { // get
return axios({
method: 'get',
baseURL: _BASE_URL,
url,
params, // get 请求时带的参数
timeout: 5000,
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
})
}
}
For easy to import, we give an alias to the path src
, edit webpack.config.js:
resolve: {
extensions: ['.js', '.vue'],
alias: {
'@': __dirname + '/src'
}
},
add these into src/popup/popup.js
import axios from '@/js/axios.js'
Vue.prototype.$axios = axios
ok, done. When you want to request restful api,
# get
this.$axios.get('http://118.31.52.226/chromit/username')
.then(res => {
console.log(res.data)
}).catch(error => {
console.log('some error info')
})
# post
this.$axios.post('http://118.31.52.226/chromit/login', {
username: 'goddy',
password: 'something'
}).then(res => {
console.log(res.data)
}).catch(error => {
console.log('some error info')
})
6. get source html
If you don't use vue to create chrome plugin, just follow steps of this blog: https://stackoverflow.com/questions/11684454/getting-the-source-html-of-the-current-page-from-chrome-extension?answertab=votes#tab-top
But how to mix above method with vue-web-extension、? PAEz also provide a way: https://github.com/PAEz/QtTabBar-Scripts/issues/1
In my way, I create src/popup/getPagesSource.js
function DOMtoString(document_root) {
var html = '',
node = document_root.firstChild;
while (node) {
switch (node.nodeType) {
case Node.ELEMENT_NODE:
html += node.outerHTML;
break;
case Node.TEXT_NODE:
html += node.nodeValue;
break;
case Node.CDATA_SECTION_NODE:
html += '<![CDATA[' + node.nodeValue + ']]>';
break;
case Node.COMMENT_NODE:
html += '<!--' + node.nodeValue + '-->';
break;
case Node.DOCUMENT_TYPE_NODE:
// (X)HTML documents are identified by public identifiers
html += "<!DOCTYPE " + node.name + (node.publicId ? ' PUBLIC "' + node.publicId + '"' : '') + (!node.publicId && node.systemId ? ' SYSTEM' : '') + (node.systemId ? ' "' + node.systemId + '"' : '') + '>\n';
break;
}
node = node.nextSibling;
}
return html;
}
chrome.runtime.sendMessage({
action: "getSource",
source: DOMtoString(document)
});
then, edit webpack.config.js
# add it to CopyWebpackPlugin
{ from: 'popup/getPagesSource.js', to: 'popup/getPagesSource.js'},
# or change your entry into this
entry: {
'background': './background.js',
'popup/popup': './popup/popup.js',
'options/options': './options/options.js',
# add this
'getPagesSource': './popup/getPagesSource.js'
},
add these into src/popup/popup.js
function onWindowLoad() {
chrome.tabs.executeScript(null, {
file: "getPagesSource.js"
}, () => {
// If you try and inject into an extensions page or the webstore/NTP you'll get an error
if (chrome.runtime.lastError) {
console.log('There was an error injecting script : \n' + chrome.runtime.lastError.message)
}
});
}
window.onload = onWindowLoad;
edit src/manifest.json
to give plugin permissions.
"permissions": ["tabs", "<all_urls>"]
add these into src/popup/App.vue
beforeCreate() {
chrome.runtime.onMessage.addListener(function(request, sender) {
if (request.action == "getSource") {
console.log(request.source)
}
});
},
then rebuild plugin, you can see..
I seems working well now. Thanks to Kocal and PAEz.
网友评论