持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第11天,点击查看活动详情
相关简介
-
前言 之前已经简单了解了谷歌扩展的基础知识点,现在就通过利用这些基础的知识点,编写一个简单的谷歌扩展。通过练习来,再次回忆这些谷歌扩展的特性。
-
介绍 这个谷歌扩展的需求是:扫描页面中的
a
标签后,插入样式和脚本,当鼠标移入a
标签时,显示是从当前页面打开或者是从新标签页面中打开的信息,然后根据设置的不同状态进行不同的打开方式。
开始
思路
- 通过使用
popup.html
弹窗页面来进行打开方式的配置; - 通过使用
storage
缓存API
来保存设置好的打开方式信息; - 通过
content_scripts
来实现页面打开的脚本逻辑和样式修改。
实现
先来看看manifest.json
文件配置(名字随便取了),主要是配置action
(弹窗界面)和权限申请还有content_scripts
的配置,代码如下:
{
"name": "易跳转",
"description": "让页面中的链接跳转更加便捷",
"version": "0.0.1",
"manifest_version": 3,
"action": {
"default_title": "易跳转",
"default_icon": "logo.jpeg",
"default_popup": "popup.html"
},
"permissions": ["storage"],
"content_scripts": [
{
"matches": ["http://*/*", "https://*/*"],
"css": ["static/css/index.css"],
"js": ["static/js/content.js"]
}
]
}
对于popup
页面,设计一个按钮,通过监听点击按钮事件,对样式和缓存的打开方式值进行修改,代码分别如下所示:
<div class="app">
<div class="app-item">
<p>默认跳转方式:</p>
<div class="app-btn">
<div class="self">当前页打开</div>
</div>
</div>
</div>
(async () => {
const btn = document.querySelector('.app-btn')
const childEl = btn.querySelector('div')
const classList = childEl.classList
const storage = await chrome.storage.sync.get('type')
const type = storage.type
if (type === 'self') {
classList.remove('blank')
classList.add('self')
childEl.innerText = '当前页打开'
} else {
classList.remove('self')
classList.add('blank')
childEl.innerText = '新标签打开'
}
btn.addEventListener('click', () => {
if (classList.contains('self')) {
classList.remove('self')
classList.add('blank')
childEl.innerText = '新标签打开'
chrome.storage.sync.set({ type: 'blank' })
} else {
classList.remove('blank')
classList.add('self')
childEl.innerText = '当前页打开'
chrome.storage.sync.set({ type: 'self' })
}
})
})()
以上通过读取缓存中的type
值(打开方式的类型),然后根据不同的type
来设置文案和类名,然后通过content_scripts
注入的CSS
来修改不同的样式,这样就能完成切换状态的功能了。
如果代码一切顺利没有Bug
的话,就应该有类似如下图的功能了:
设计好popup
后,就是完成关键的content_scripts
了,设计思路就是:通过读取缓存的打开方式的状态,然后进行不同状态对应的处理,代码如下:
// static/js/content.js
(async () => {
const storage = await chrome.storage.sync.get('type')
const type = storage.type || 'self'
const links = document.querySelectorAll('a')
links.forEach(link => {
const types = Array.from(link.childNodes).map(node => node.nodeName)
const blackList = ['IMG']
const isFailed = types.some(type => blackList.includes(type))
if (!isFailed) {
link.classList.add('v_link_')
link.target = type === 'self' ? '_blank' : '_self'
const el = document.createElement('div')
el.classList.add('v_link_right')
el.innerHTML = `
<a class="v_link_btn" target="${type === 'self' ? '_self' : '_blank'}" href="${link.href}">${type === 'self' ? '当前页打开' : '新标签打开'}</a>
`
link.appendChild(el)
}
})
})()
注意
上面可以通过设置一个黑名单的方式,来操作希望不被插件重新修改的元素类型,例如IMG
以上通过querySelectorAll
查询所有的a
标签,通过缓存的type
值,动态修改标签中的内容,并且追加一个新的子元素,进行显示另一种打开方式的内容。
例如:当前设置的打开方式是_blank
(新标签中打开),那么页面中原始的a
标签的target
就要设置为_self
,然后移入a
标签后显示另一个为_blank
的打开方式界面。
完成content_scripts
的脚本编写顺利的话,就可以看到下图的结果了:
可以看到,当移入a
标签时,弹出了一个可以选择打开方式的界面,即通过popup
设置的打开方式,例如为新标签打开方式,那么原始的链接就是当前页打开的方式了。
至此,就已经完成一个简单的谷歌扩展了:)