PouchDB

PouchDB--简单的前端数据库

PouchDB的介绍,PouchDB的使用方法

2018-08-27侠课岛    初级拔高       

前端/前端/客户端存储 20     0     2135

关于客户端存储的技术,前面已经全部介绍完了。这一章并不是介绍新的技术,PouchDB 可以认为是对 IndexedDB 的一种封装。在实际工作中,这可以算是比较好的一个工具库了。

那么在开始这一章的内容之前,让我们先来回顾一下至今为止介绍过的几种客户端存储,以及他们的特点。

编号 名称 复杂度 适用场景 建议
1 Cookie 中等 用于存放 sid 之类的身份验证信息 最早也是最稳定的客户端存储手段,无浏览器兼容性的问题。储存容量很小仅 4kb 左右,且有数量限制。对于新项目,可以使用 WebStorage 进行代替。MDN 上有简化操作的工具库。
2 WebStorage 简单 用于存放非敏感信息或个性化信息 HTML5 中推出的技术,目前也基本没有浏览器兼容问题。分为 LocalStorage 和 SessionStorage。允许存储 5mb 左右的数据,基本满足目前开发的需要。使用上 API 较少且简单,唯一需要注意的是只能存储字符串类型数据。对于其他的数据需要进行如 JSON.stringify 的转换操作。有 store.js 库可以来简化操作。建议现在做项目时优先使用可以用来代替 Cookie。
3 IndexedDB 复杂 用于存放大容量数据 最新出现的客户端存储技术,用来代替 WebSQL。在 PC 端上支持性较好,移动端也基本支持。可以认为是客户端(浏览器)中的数据库,使用对象存储的方式储存数据,与 MongoDB 较类似。容量可以认为是无限的,支持索引、条件查询等操作。对于离线应用的场景用处很大,但是原生 API 比较复杂,工作中一般使用 Dexie.js 或者 PouchDB 等来代替使用。
4 WebSQL 中等 用于存放大容量数据 非 HTML5 规范,只有 Chrome 等支持。此规范已经被废弃,未来也不会再更新。在移动端上支持度较高。可以理解为客户端(浏览器)中的 MySQL,因此只要掌握 SQL 语句就能使用。与 IndexedDB 相比,没有复杂的 API,全靠手写 SQL 暴力解决。由于已经被废弃,除了已经有的项目外,不建议使用。

好了,在回顾完之前所讲的内容之后,那么让我们正式进入这一章的内容吧。

6.1 PouchDB 介绍

在上面总结的表中,我们知道目前在客户端(浏览器)中想要进行规模数据的存储就必须要使用 IndexedDB,但是 IndexedDB 由于其比较陡峭的学习曲线往往让人望而却步。为此,就诞生了许多辅助的工具库,而其中比较好用的就有 PouchDB 了。

首先,PouchDB 并不是一个数据库,也不是新的前端标准,它只是一个对于 IndexedDB 与 WebSQL (对于一些不兼容)的封装。PouchDB 参考的是 Appache 出品的 CouchDB,因此也可以支持 CouchDB。并且除了本地的创建数据库之外,PouchDB 还支持链接远程的数据库。这同样也解决了客户端存储中最大的弊端——与远程数据库的不同步问题。 注:CouchDB 是 Appache 出品的对象存储型数据库。完全兼容 JSON,并且支持 MongoDB 的查询语法。如果使用 Node.js 的话可以做到无缝对接。

除此之外,PouchDB 不仅支持全部浏览器(兼容 IndexedDB 使用 IndexedDB,不兼容的则使用 WebSQL,并且 API 完全相同使我们可以忽略环境差异),同时也支持 Node.js 是一个方位支持的库。并且其大小也非常轻便,压缩过后只有 46kb。最关键的一点就是它封装了 IndexedDB 的 API,将 IndexedDB 的短处给去掉了,语法更接近 MongoDB 或者 CouchDB 之类我们比较熟悉的风格,大大降低了学习的难度。

我们可以在 PouchDB 官网上看到相关的介绍。更详细的内容可以看 Guides 和 Learn 部分。

6.2 PouchDB 的使用方法

那么这一节我们正式介绍 PouchDB 的使用方法。在 PouchDB 中,所有的操作都是异步的,并且支持 Promise,Await/Async 操作。本教程由于篇幅有限,我们会介绍一些最基本的操作。感兴趣想了解更多的小伙伴,可以去官网查看 API 文档。目前看下来他们的文档做得还算比较仔细的,可以解决不少问题。(当然,由于全都是英文,需要具备一定的英语水平。不过做开发的小伙伴,看文档的功力那肯定是有的吧~)

数据库相关操作

在创建数据库之前,别忘记我们需要引入 PouchDB。在 Node.js 或 Vue 等工程中,我们可以直接通过 var PouchDB = require('PouchDB') 来引入。而在浏览器环境中,我们可以通过 <script src="path/to/pouchdb.js"></script> 来引入(如果在浏览器中要支持 Promise 则在 PouchDB 引入前要引入相应的库)。

那么在引入完成之后我们就可以进行数据库创建了。创建数据库只需要一句命令即可。

var db = new PouchDB(name, [opts])

其中 name 为必填参数。表示数据库的名字,当数据库不存在时,会创建对应的数据库;而如果已经存在则打开数据库。如果是要连接远程数据库的情况,这里还可以是远程数据库的 url。

opts 为选填参数,根据数据库的类型有所不同。当不指定时,在浏览器中一般以 IndexedDB 为主。

  1. 本地数据库时的参数为: 编号 名称 说明
    1 auto_compaction 是否开启自动压缩,开启后会在每次数据库发生变化后进行压缩和清理。默认为 false
    2 adapter 适配器,一般可以为 idb, leveldb, websql, memory, http 之一。
    3 revs_limit 设置保留修正的数量,与事务相关。默认为 1000。
    4 deterministic_revs 用 md5 来计算出一个确定的版本号,如果不开启的话就是随机的 UUID。默认为 true。
  2. 远程数据库时的参数为: 编号 名称 说明
    1 fetch(url, opts) 对于请求的拦截,可以在此对请求头进行编辑。
    2 auth.username + auth.password 远程数据库的用户名和密码。
    3 skip_setup 是否跳过初始的数据库检查工作,若设置为 true,则 PouchDB 不会主动检查数据库是否存在。

由于不是原生的 API,所以我们这次不能直接在 Chrome 中执行命令了。我们需要创建一个 html 文件,代码如下。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>PouchDB</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <script src="//cdn.jsdelivr.net/npm/pouchdb@7.0.0/dist/pouchdb.min.js"></script>
  <script type="text/javascript" src="http://vuejs.org/js/vue.min.js"></script>
</head>
<body>
  <script>
    var db = new PouchDB('person')
  </script>
</body>
</html>

代码的内容非常简单,引入了 PouchDB 后,我们直接创建了一个 person 数据库。打开 Chrome 的 Application 面板,可以看到数据库已经被建成了。不过由于是通过 PouchDB 帮我们生成的,可以看到还有许多其他的对象存储。不过这个我们可以不用关心,我们只要记得今后的数据在 document 对象存储中就可以了。

如果我们需要删除数据库也非常的容易。在 Chrome 中除了可以通过 Application 面板进行删除外,对于其他的浏览器我们可以通过 destory 方法进行数据库的删除。

db.destroy([options], [callback])

对象存储的创建

在创建完成了数据库之后,下一步就是对象存储的创建了。在 PouchDB 中有 putpost 两种方法创建对象存储。其中 put 既可以用来创建数据,也可以用来更新数据,而 post 只能用来创建数据。官方的建议是使用 put 因为这样我们可以设置数据的 _id,而 post 则是随机生成的 _id。在本文的例子中,我们都使用 put 来进行。注:_id 也必须是唯一的。

下面让我们来创建一个 student 的对象。在 PouchDB 中,我们在创建对象存储的时候就可以直接写入数据。这部分的代码放在上面的 <script> 中。

    var db = new PouchDB('person')
    db.put({
        _id: 'student',
        name: 'konata9',
        age: 18,
        phone: 1234567890,
        email: 'konata9@konata9.com'
    }, function (err, res) {
        if (err) {
        throw new Error(err)
        }
        console.log(`student 已经创建完成`)
        console.log(res)
    })

打开页面执行代码,可以看到 student 对象存储已经顺利创建完成。并且在创建成功后会返回给我们一个 rev。这个值是由系统生成的,作用非常重要,是这一条数据的主键,我们在更新、删除数据时必须要传入这个主键。不过也不用担心,因为我们在做查询操作时返回的数据结构中会带着这一项。

接着我们再来到 Application 面板中。点击 document-store 就可以看到我们刚才创建的 student 对象存储以及一些信息。注意查看这里的主键,内容是我们刚才设置的 _id 因为是主键,所以是不允许重复的。

相信有小伙伴会觉得奇怪,我们在创建的过程中插入的数据呢?别着急,我们点开上面的 by-sequence 在下面的 _doc_id_rev 中就可以看到我们刚才插入的数据了。

基本 CRUD 方法

上面我们在介绍对象存储创建的时候,顺便就介绍了数据的插入。那么在这一小节中,我们继续介绍剩下的 RUD(读取、更新、删除)三个方法。

读取

在 PouchDB 中,读取单条数据我们可以使用 get 方法。其中,docId 是我们必须要传入的,就是我们前面设定的 _id 的值。options 我们通常不用去填写,主要是针对 rev 值的操作。最后的回调函数则用于处理获取数据后的操作。

db.get(docId, [options], [callback])

要注意的是,PouchDB 的所有操作都是异步的,所以如果当我们的操作有先后依赖关系的话,就需要放在前一个函数的回调函数中进行处理。下面让我们来看一下获取数据的代码。由于数据库中已经有数据了,所以我们注释掉插入的代码。

  <script>
    var db = new PouchDB('person')
    // db.put({
    //   _id: 'student',
    //   name: 'konata9',
    //   age: 18,
    //   phone: 1234567890,
    //   email: 'konata9@konata9.com'
    // }, function (err, res) {
    //   if (err) {
    //     throw new Error(err)
    //   }
    //   console.log(`student 已经创建完成`)
    // })

    db.get('student', function (err, doc) {
      if (err) {
        throw new Error(err)
      }
      console.log(`student 数据获取`)
      console.dir(doc)
    })
  </script>

刷新一下页面,就可以看到控制台中输出了我们之前插入的数据。并且还给了我们 _id_rev 两个字段方便我们做后续的操作。

最后,对于批量读取,我们可以使用 db.allDocs 方法进行获取。一般情况下,我们对 options 只需要设置 include_docsattachments 两项即可。当然也允许我们做简单的范围以及分页设置。详细的设置,可以参考官网。

db.allDocs([options], [callback])

我们将上面查询的代码稍微替换一下。

    db.allDocs({
      include_docs: true,
      attachments: true
    }, function(err, docs){
      if(err){
        throw new Error(err)
      }
      console.log(`获取全部数据`)
      console.dir(docs)
    })

重新刷新页面,我们可以看到列表的结果。程序其实很贴心地给了我们 total_rowsoffset 两个参数,我们在实际的应用过程中可以利用这两个参数进行分页的设置。

更新

更新其实和数据的写入一样,用的都是 put 方法,只是在进行更新时我们需要传入 _rev 的值即可。下面让我们看一下具体更新的代码。

    db.get('student', function (err, doc) {
      if (err) {
        throw new Error(err)
      }
      console.log(`student 数据获取`)
      console.dir(doc)

      var update = Object.assign({}, doc, {name: 'Konata10'})
      console.log(update)

      db.put(update, function (err, res) {
        if (err) {
          throw new Error(err)
        }
        console.log(`数据已更新`)
        console.log(res)
      })
    })

本教程图文或视频等内容版权归侠课岛所有,任何机构、媒体、网站或个人未经本网协议授权不得转载、转贴或以其他方式复制发布或发表。

评价

20

本课评分:
  •     非常好
难易程度:
  •     适中的
|
教程
粉丝
主页

签到有礼

已签到2天,连续签到7天即可领取7天全站VIP

  • 1
    +2 金币
  • 2
    +3 金币
  • 3
    +5 金币
  • 6
    +7 金币
  • 5
    +6 金币
  • 4
    暖心福利
    自选分类VIP ×1天
  • 7
    惊喜大礼

    自选分类VIP ×3天 +20金币
  • 持续签到 +8 金币

金币可以用来做什么?