用chrome扩展撸一个todoList

1,280 阅读3分钟

因为工作的关系,每天都要处理很多的琐事,因为比较忙碌,经常会忘记一些事情。所以做一个简单的todoList的想法应运而生。大概的功能就是添加待办事项,按预设的时间周期弹出提示。

需求很简单,但是要用什么实现呢?如果做成独立的应用,一定会随着时间的推移被逐渐丢弃在角落。

所以决定做成chrome的扩展程序,依托于浏览器,随时取用。

manifest.json

每一个chrome扩展都包含一个Manifest文件,这个文件可以告诉chrome关于这个扩展的相关信息,它是整个扩展的入口,也是chrome扩展必不可少的部分。

manifest.json中我们指定扩展的名称、版本,图标以及backgroundpopup的路径等信息。

其中,popup是点击浏览器右上角的扩展图标时显示的界面,background是常驻后台的js文件,它们的具体用处下文再叙述。

{
    "name": "todoList",
    "description": "工作待办事项管理工具",
    "version": "1.0.1",
    "manifest_version": 2,
    "icons": {
        "16": "icon.png",
        "48": "icon.png",
        "128": "icon.png"
    },
    "browser_action": {
        "default_popup": "popup.html"       // 点击图标后弹出的界面
    },
    "background": {
        "scripts": [
            "background.js"     // 常驻后台的js
        ]
    },
    "permissions": [
        "contextMenus",
        "notifications"
    ]
}

popup.html

当点击浏览器上的扩展图标时,我们希望显示todoList工具的主界面,这里正常书写htmlcss即可。

需要注意的是,chrome扩展只支持外部js,所以无法在popup.html中书写任何的js逻辑。

css代码这里就不再赘述了。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 引入js -->
    <script type="text/javascript" src="popup.js"></script>
</head>

<body style="width:500px;padding-top: 20px;">
    <div class="centerView">
        <div class="title">
            <span class="title1">Todo</span><span class="title2">List</span>
        </div>
        <!-- 输入框添加栏 -->
        <div class="infoView">
            <textarea placeholder="请输入待办事项" name="inputTodoInfo"></textarea>
            <div class="pflex infoView" style="justify-content:space-between">
                <button class="addButton" id="addList">添加待办事项</button>
                <div class="mainColor">
                    提醒周期
                    <select id="selectTime" class="mainColor">
                        <option value="">15分钟</option>
                        <option value="2">10分钟</option>
                        <option value="3">5分钟</option>
                        <option value="3">1分钟</option>
                    </select>
                </div>
            </div>
        </div>
    </div>

    <div class="listDiv">
        <div class="centerView">
            <div class="title2">待办事项</div>
            <!-- 待办事项列表,渲染列表 -->
            <div id="todo">

            </div>
        </div>
    </div>
</body>
</html>

界面大概是这样的:

popup.js

每添加一个待办事项,将数据存储入localstorage中,当打开popup.html时,先尝试读取localstorage获取信息,并渲染。

popup中可以使用background中的方法,我们把添加获取方法都封装再来background中,在popup中这样调用:

var bg = chrome.extension.getBackgroundPage(); // 核心api
bg.addList(todo)

popup.js全部内容:

document.addEventListener('DOMContentLoaded', function () {
    document.getElementById("addList").addEventListener("click", handler);
});
let todoList = []
function handler() {
    let todoInfo = document.getElementsByName('inputTodoInfo')[0].value
    if (todoInfo.length > 0) {
        let selectTimeIndex = document.getElementById('selectTime').selectedIndex
        let selectTime = [15, 10, 5, 1]
        let todo = {
            info: todoInfo,
            createTime: (new Date()).getTime(),
            nextTime: (new Date()).getTime() + (selectTime[selectTimeIndex] * 60 * 1000),
            time: selectTime[selectTimeIndex]
        }
        var bg = chrome.extension.getBackgroundPage(); // 核心api
        bg.addList(todo)
        document.getElementsByName('inputTodoInfo')[0].value = ""
        getList()
    } else {
        alert("还没有输入内容哦")
    }
}
window.onload = function () {
    getList()
}

function getList() {
    let listDiv = document.getElementById("todo")
    var bg = chrome.extension.getBackgroundPage(); // 核心api
    todoList = bg.getList()
    let todoView = ``
    if (todoList.length > 0) {
        for (let i = 0; i < todoList.length; i++) {
            todoView += `
            <div class="todo infoView">
            <div class="centerView">
            <div class="todoTitle">${todoList[i].info}</div>
            <div class="infoView pflex">
                <div style="width:50%">创建时间:</div>
                <div style="width:50%">${timestampToTime(todoList[i].createTime)}</div>
            </div>
            <div class="infoView pflex">
                <div style="width:50%">提醒周期:</div>
                <div style="width:50%">${todoList[i].time}分钟</div>
            </div>
            <div class="infoView pflex" style="justify-content: flex-end;">
                <button class="finish">完成待办</button>
            </div>
        </div>
        </div>`
        }
        listDiv.innerHTML = todoView
        let finishButton = document.getElementsByClassName("finish")
        for (let i = 0; i < finishButton.length; i++) {
            console.log(finishButton[i])
            finishButton[i].onclick = function () {
                finish(i)
            };
        }
    } else {
        listDiv.innerHTML = ""
    }
}

function finish(i) {
    todoList.splice(i, 1)
    localStorage.setItem("todoList", JSON.stringify(todoList))
    getList()
}

function timestampToTime(timestamp) {
    var date = new Date(timestamp);
    var Y = date.getFullYear() + '-';
    var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
    var D = date.getDate() + ' ';
    var h = date.getHours() + ':';
    var m = date.getMinutes() + ':';
    var s = date.getSeconds();
    return Y + M + D + h + m + s;
}

background.js

在Manifest中指定background域可以使扩展常驻后台。

background.js,我们每隔20秒遍历一次待办事项数组(处于性能考虑,没有必要每秒监听,所以提示时间可能会有二十秒的误差,但是使用上影响不大)

window.setInterval(function () {
    let todoList = []
    let time = (new Date()).getTime()
    let endTime = time + (1000 * 20)
    if (localStorage.getItem("todoList")) {
        todoList = JSON.parse(localStorage.getItem("todoList"))
        console.log(todoList)
        for (let i = 0; i < todoList.length; i++) {
            console.log(time)
            if (todoList[i].nextTime <= endTime) {
                alert("别忘记哦," + todoList[i].info);
                todoList[i].nextTime += (todoList[i].time * 60 * 1000)
            }
        }
        localStorage.setItem("todoList", JSON.stringify(todoList))
    }
}, 1000 * 20);

function addList(todo) {
    let todoList = []
    if (localStorage.getItem("todoList")) {
        todoList = JSON.parse(localStorage.getItem("todoList"))
    }
    if (todoList.length >= 5) {
        alert("宝贝,最多只支持五条哦")
    } else {
        todoList.push(todo)
        console.log(todoList)
        localStorage.setItem("todoList", JSON.stringify(todoList))
    }

}

function getList() {
    return JSON.parse(localStorage.getItem("todoList"))
}

测试

至此,我们的扩展程序已经基本完成了,一个简单的todoList。

在预设的提醒周期到了之后,会alert出待办提示。且如果不完成待办的话,就会一直每隔xx分钟(预设的时间),提示一次。

安装

在浏览器扩展程序页面,打开开发者模式,将项目文件夹拖入即可。