Chrome 擴展應用開發之旅(二)

本文同時發佈於知乎專欄:前端指南
轉載需提早聯繫做者,未經容許不得轉載。html

最近比較忙,這兩天終於抽時間寫了咱們系列的第二篇文章,你們有什麼意見和建議歡迎評論前端

原本是想再給你們詳細介紹一下chrome擴展的許多文檔細節和一些定義,後來考慮到這個擴展自己的意義就是在於作出應用,過多的介紹API反而會讓你們失去興趣,故而,今天給你們帶來就是一個基於Chrome的一個ToDoList的純前端小玩具。git

同窗們在跟着我把全部代碼都實現以後,會對js的ES六、基本DOM操做,事件監聽,邏輯數據分離思想以及Chrome的本地存儲都會有一個比較大的進步github

本系列課程源碼都在個人github上:miaoihan/chrome-extensionssql

前期準備chrome

項目目錄:
圖片描述數據庫

上節課已經介紹過改文件裏各個文件的做用了,此次的應用並無多出任何的文件,都是在基礎之上作的代碼的擴充。後端

  • app.js:TodoList的主文件瀏覽器

  • background.js:後臺數據通訊(後來版本中用chrome.storage替換了background的數據傳遞)服務器

  • Task.js:task類,包含task屬性和方法

在介紹代碼以前,咱們先理一下咱們的思路,咱們要實現一個能夠增刪查改的任務清單,最後實現相似於滴答清單這樣的一個效果。
圖片描述

咱們須要作的功能:

  • 在打開該應用以前,須要獲取全部task信息,並分別展示到兩個列表裏(查)

  • 在文本框能輸入須要完成的任務,回車後保存任務信息到瀏覽器中,任務跳到清單列表,狀態是未完成(增)

  • 在勾選清單列表裏的某一項後,該任務跳轉到已完成列表,狀態是已完成(改)

  • 一樣在勾選已完成列表中某項,能夠跳到清單列表。

  • 能夠修改未完成的任務內容和刪除內容(刪、改)
    這樣一個看似很簡單的應用作起來其實背後也有一套挺複雜的思想,咱們再不借用任何外部庫的狀況下獨立完成該應用。

起步

  1. 編寫todo.html 前端頁面
    頁面部分沒啥好講的,你們本身動手,先簡單佈局一個版本,相似於這樣:

圖片描述

當前版本並不支持在html頁面裏寫js代碼,不是不推薦,是不支持,因此你們必須把文件單獨出來在頁面中引入

  1. 編寫app.js 主文件
    首先咱們完成文本框回車添加的功能,代碼以下

// 監聽回車
$('task-input').addEventListener('keyup', function(event) {
    if (event.keyCode == "13") {
        let content = $('task-input').value
        let taskItemHtml = 
            `<div class="task-item">
              <input type="checkbox">
              <span class="task-content" style="font-size: 14px;">${task}</span>
            </div>`
            $('task-list').innerHTML += taskItemHtml
        $('task-input').value = ''
    }
})

這裏keyCode是是數字鍵盤的鍵碼值,13對應回車,JavaScript Event KeyCodes 這個網站你能夠找到全部的鍵盤對應值。

這裏的代碼同窗們可能會問了,你不是說不用任何庫麼,怎麼又有「$‘’了,其實這個‘’$‘’是我本身定義的簡版選擇器,只是方便id選擇的。

let $ = function(id){
    return document.getElementById(id)
}
$('task-input').addEventListener('keyup', function)

這裏的addEventListener是添加監聽器的意思,當咱們發生了'keyup'即鍵盤擡起事件後就會觸發一個function,咱們這裏暫時的思路是直接操做視圖,這裏的${}這種寫法是ES6的字面量的寫法,免去了各類加號拼接字符串了,很是方便。在咱們成功插入了一個html片斷以後,咱們再把input裏的內容給清空,最後的效果是這樣的:
圖片描述

而後咱們打開控制檯,發現div已經插入進去了
圖片描述

那麼咱們前面爲何要說是暫時的思路呢,由於現階段已經不推薦直接操做DOM了,如今的大部分框架已經不用去關係操做DOM,數據和view是實時更新的,即雙向的數據流動。

在完成了視圖操做以後,咱們添加的數據並無保存下來,在通常的應用中,這時候的數據保存是和後端服務器進行交互的,也就是剛剛添加的任務會保存在數據庫中,咱們這個應用不涉及後端部分,因此咱們使用HTML5的API localStorage進行數據的存取,可是localStorage並不直接支持對象的存取,因此在操做以前咱們須要對數據進行JSON.stringify 和 JSON.parse操做進行格式的轉換。

let task = {}; let taskList = []
task.content = content; task.isFinish = false
taskList.push(task)
// 將對象轉換成字符串後保存
localStorage.taskList = JSON.stringify(taskList)

正常狀況下咱們這樣存儲就已經能夠了,再經過taskList = JSON.parse(localStorage.taskList)就能夠獲取到task對象了,可是。。。localStroage的存儲是基於域名的,因此咱們的擴展若是直接這樣使用,在切換網頁的時候域名不同這個存儲空間就是失效了,那這樣固然不行了,那麼怎麼解決呢?

兩種方案
一種仍是用localStorage,app.js經過runtime.sendMessage和background通訊,由background讀寫擴展所在域(一般是chrome-extension://extension-id/)的localStorage,這時候域相同localStorage值有效,而後再傳遞給app.js。

app.js:

chrome.runtime.sendMessage('fetchData', function(res){
     // res.taskList 即傳回來的list
     console.log(res);
});

background.js:

chrome.runtime.onMessage.addListener(function(message, sender, sendResponse){
    if(message == 'fetchData'){
        let taskList = JSON.parse(localStorage.taskList)
        sendResponse(taskList);
    }
});

經過上面兩個文件之間的通訊,咱們就能夠完成數據的存儲。

另外一種是經過使用chrom.storage這個API完成對數據存儲的操做,他的好處有幾點:

  • 用戶數據能夠自動與Chrome同步(使用storage.sync)同步。

  • content script能夠直接訪問數據,不須要經過background中轉

  • 無痕模式,用戶數據也能保存下來

  • 由於是異步操做,因此比localStorage更快

  • 能夠直接存儲對象

說這麼多好處,其實就是讓你去用它。使用Chrome存儲API必需要在Manifest的permissions中聲明"storage",以後纔有權限調用。

{
    "name": "todo",
    ...
    "permissions": [
      "storage"
    ],
    ...
  }

對於每種儲存區域,Chrome又提供了5個方法,分別是get、getBytesInUse、set、remove和clear。

chrome.storage.sync.get('taskList', function(res){
    updateView(res.taskList)
});

Chrome存儲API提供了2種儲存區域,分別是sync和local。兩種儲存區域的區別在於,sync儲存的區域會根據用戶當前在Chrome上登錄的Google帳戶自動同步數據,當無可用網絡鏈接可用時,sync區域對數據的讀寫和local區域對數據的讀寫行爲一致。
好,那麼如今咱們的存儲邏輯就能夠寫出來了

chrome.storage.sync.get('taskList', function(res) {
    let taskList = res.taskList || []
    taskList.push(obj)
    chrome.storage.sync.set({taskList:taskList});
});

這裏咱們先get了一下,由於直接set的話,會把原數據覆蓋,這裏API並無相似sql的update操做,因此只能取出來,push進去,再set。
好了,到目前爲止,咱們已經不怎麼優雅的實現了數據的添加和視圖的展示,接下來咱們,接下來咱們。。。下一期見

下期預告:使用ES6 class分離數據邏輯的處理,把一些公共模塊抽象出來。完成清單的勾選,完成和未完成任務的處理

相關文章
相關標籤/搜索