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分离数据逻辑的处理,把一些公共模块抽象出来。完成清单的勾选,完成和未完成任务的处理

相关文章
相关标签/搜索