开发一款记录日常查看掘金的文章的历史记录的谷歌浏览器插件。完整代码放在文章结尾,可以下载安装体验
日常查看掘金的文章,没有查看访问的文章历史记录功能。如果当时在看的文章点赞或者收藏后还可以方便找到,但是有些文章当时并没有收藏,等到日后工作中突然想查看到之前查看某一文章,查找就比较费劲。虽然页可以通过浏览器的历史记录,记录的其他无效内容比较多不方便查看。
出于以上原因就想到是否可以通过开发个浏览器插件将浏览的文章数据记录下来。
准备工作,初始化项目
创建目录juejin-history。
新建manifest.json文件,该文件是谷歌插件的基础配置。
{
"manifest_version": 3,
"name": "稀土掘金浏览历史",
"version": "1.0",
"description": "稀土掘金浏览历史",
"content_scripts": [
{
"matches": ["https://juejin.cn/*"],
"js": ["./src/js/content.js"],
"css":[ "./src/content.css" ]
}
],
"permissions": ["activeTab", "tabs", "scripting", "storage"],
"host_permissions":["<all_urls>"],
"icons": {
"16": "./icon16.png",
"32": "./icon32.png",
"48": "./icon48.png",
"64": "./icon64.png",
"128": "./icon128.png",
"256": "./icon256.png"
},
"action": {
"default_popup": "./src/popup.html",
"default_icon": {
"16": "./icon16.png",
"32": "./icon32.png",
"48": "./icon48.png",
"64": "./icon64.png",
"128": "./icon128.png",
"256": "./icon256.png"
}
}
}
- manifest_version:表示开发的版本,目前最新的都是3
- name:本插件的名称,用来显示在扩展程序上
- version:插件开发迭代版本
- description:插件的功能描述
- content_scripts:content.js配置的路径以及匹配的生效的网站
- permissions:设置的权限,由于需要存放数据,需要加上storage
- icons:在扩展程序中显示的应用图标
- action:点击操作的内容,可以设置popup弹窗页面和icon显示的图标
项目主要使用到 content.js 和 popup.html文件的内容。
content.js文件会在匹配生效的网站中立即执行,在该文件中,可以通过获取页面的dom元素,修改dom的内容以及样式等。
popup.html是点击插件的图标后显示的弹窗内容。弹窗可以加载外部js库,如jquery、bootstrap等。
生成icon图标
下载设置一个png图片。 然后将图片上传至 uutool.cn/chrome-icon…
就可以方便生成需要的icon图标
创建content.js
在 ./src/js/目录下 创建文件 content.js 文件
console.log("这是contentjs文件")
创建popup.html
在 ./src 目录下创建 popup.html文件
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>弹窗</div>
</body>
</html>
完成以上内容,就可在扩展程序中添加该插件并进行调试。
选择扩展程序中的 加载已解压的扩展程序,然后选择创建的 juejin-history 目录。 加载完成就可以看到
浏览器地址栏右侧,查看扩展程序也可以看到
点击该图标,可以看到弹窗的内容。
添加数据记录
可以看到文章页面的url中都会包括 /post/ 一段内容。那么就可以通过匹配访问的url判断是否是掘金的文章页面。如果是在文章页面,就获取文件的title内容。
- 判断是否是掘金的文章页面
if(window.location.href.indexOf('/post/')>0) - 获取文件的title内容
document.querySelector('.article-title').innerText
将获取的内容存放到storage中
// 存放的数据
let storageData = {
"official_home_page_url": "https://www.juejin.cn/",
"history": [],
}
// 添加到history下
storageData.history.push({
url: window.location.href,
title: document.querySelector('.article-title').innerText,
createTime: getNowFormatDate()
})
// 使用chrome.storage.local.set API,将数据存放,存储的数据应是字符串
chrome.storage.local.set({
'storageData': JSON.stringify(storageData),
}, function() {
console.log('team_profile Data stored successfully.');
})
在popup.html获取并显示数据,引入popup.js文件
chrome.storage.local.get('storageData', function(result) {
// 获取到历史数据
const history = JSON.parse(result.storageData).history.reverse();
})
// 将数据动态添加到页面
let ulListDom = document.createElement('ul');
Array.isArray(history) && history.forEach(item=>{
ulListDom.innerHTML += `<li><a href=${item.url} target="_block">${item.title}</a><span> ${item.createTime}</span></li>`;
})
document.getElementById('container').appendChild(ulListDom);
再次调试预览,就可以看到文件记录列表。
这里除了判断url是文章页面来获取浏览数据,还可以通过点击事件时进行事件代理。发现只能点击li元素foot底部才可触发点击【点击title或者描述不能触发点击事件】,就放弃了这个方案。猜想可能是服务端渲染的问题,如果有知道的朋友可以指教下。
// 添加事件代理,然后判断点击的元素为文件列表的内容
document.querySelector('#juejin').addEventListener('click', function (e) {
// 兼容性处理
var event = e || window.event;
var target = event.target || event.srcElement;
if (target.className.includes('action-list jh-timeline-action-area')) {
console.log('the content is: ', target.href, target.outerHTML);
storageData.history.push({
url: window.location.href,
title: document.querySelector('.article-title').innerText,
createTime: getNowFormatDate()
})
chrome.storage.local.set({
'storageData': JSON.stringify(storageData),
}, function() {
console.log('team_profile Data stored successfully.');
});
}
});
添加分页处理
分页处理使用了bootstrap框架。
首先下载jquery和bootstrap的内容到lib目录。
<link rel="stylesheet" href="/lib/bootstrap.min.css" />
<script src="/lib/jquery-1.12.4.js"></script>
<script src="/lib/bootstrap.min.js"></script>
在popup.js中添加代码
let ulPageDom = document.createElement('ul');
ulPageDom.className = 'pagination pagination-sm'
let liHtml = '';
for(let i = 0; i < pageCount; i++) {
if(currentPage === i+1){
liHtml += `
<li class="active"><a href="#">${i+1}</a></li>`
} else{
liHtml += `
<li><a href="#">${i+1}</a></li>
`
}
}
liHtml += `<span aria-hidden="true" style="line-height: 28px; margin-left: 3px;">共${total}条</span>`
ulPageDom.innerHTML = `${liHtml}`
$('#container').after(ulPageDom);
添加清除所有数据功能
如果数据量非常大了,可以主动清除历史数据。另外在插件中也添加了超过500条数据,会自动清除最先记录的100条数据的逻辑处理。
在popup.html添加按钮
<button id="clearBtn" type="button" class="btn btn-danger">清除数据</button>
在popup.js中添加清除数据的事件
// 清除所有数据
document.getElementById('clearBtn').addEventListener('click', () => {
chrome.storage.local.clear(function() {
console.log('Storage cleared successfully');
document.getElementById('container').innerHTML = '暂无数据';
});
})
除了添加清除数据功能,还可以添加根据日期筛选、或者根据title筛选的功能。有兴趣的伙伴可以继续扩展开发。