zoukankan      html  css  js  c++  java
  • indexedDB入门

    localforage

    1. localStorage局限性:存储容量限制,仅支持字符串,如果是存对象还需要将使用JSON.stringify和JSON.parse方法互相转换;读取都是同步的。大多数情况ok。但如果存储数据比较大,例如一张重要图片base64格式存储了,再读可能会有可感知的延迟时间。
    2. localforage 是一个js库,通过简单类似locaStorage的异步存储来改进你的 Web 应用程序的离线体验。它能存储多种类型的数据,而不仅仅是字符串。localforage 有一个优雅降级策略,若浏览器不支持 IndexedDB 或 WebSQL,则使用 localStorage;
    3. API:

    indexedDB

    1. IndexedDB数据库使用key-value键值对储存数据;任何操作都发生在事务(transaction)中,indexedDB API提供了索引(indexes), 表(tables), 指针(cursors)等, 但是所有这些必须是依赖于某种事务的;不使用sql,而是通过索引(index)所产生的指针(cursor)来完成查询操作,从而使你可以遍历到结果;和大多数web存储解决方案相同,indexedDB也遵从同源协议;indexedDB在结果准备好之后通过DOM事件通知用户(success,error);indexedDB是websql的替代品,是非关系型数据库(nosql)的一种;
    2. indexedDB数据库必须包含名字和版本
    3. 使用indexedDB的基本模式:
      1. 打开数据库并且开始一个事务。
      2. 创建一个 object store。
      3. 构建一个请求来执行一些数据库操作,像增加或提取数据等。
      4. 通过监听正确类型的 DOM 事件以等待操作完成。
      5. 在操作结果上进行一些操作(可以在 request 对象中找到)。
    4. 打开indexedDB数据库
      var dbOpenRequest = window.indexedDB.open(dbName, version);
    5. 创建数据库的主键和字段
      // onupgradeneeded用于数据库首次创建版本,或者window.indexedDB.open传递的新版本(版本要比现在的高)
      dbOpenRequest.onupgradeneeded = function(event) {
        var db = event.target.result;
        db.onerror = function(event) {
          console.log('数据库打开失败');
        };
        // 创建一个数据库存储对象
        var objectStore = db.createObjectStore(dbname, {
          keyPath: 'id', 
          autoIncrement: true
        });
        // 定义存储对象的数据项
        objectStore.createIndex(indexName, keyPath, {unique: true});
      }
    6. 事务(可以理解为对数据库的操作,而且专指一个序列上的操作)
      原子性(Atomicity):事务中的所有操作作为一个整体提交或回滚。
      一致性(Consistemcy):事物完成时,数据必须是一致的,以保证数据的无损。
      隔离性(Isolation):对数据进行修改的多个事务是彼此隔离的。
      持久性(Durability):事务完成之后,它对于系统的影响是永久的,该修改即使出现系统故障也将一直保留。
      var transaction = db.transaction([dbName], 'readwrite');
      // 打开已存储的数据对象
      var objectStore = transaction.objectStore(dbName);
      
      // 增、删、清空、改
      var objectStoreRequest = objectStore.add();
      var objectStoreRequest = objectStore.delete();
      var objectStoreRequest = objectStore.clear();
      var objectStoreRequest = objectStore.put();
      
      // 获取存储的对应键的存储对象
      var objectStoreRequest = objectStore.get(id);
      
      objectStoreRequest.onsuccess = function(){
        // 成功处理
      }
    7. 游标
      objectStore.openCursor().onsuccess = function(event) {
        var cursor = event.target.result;
        if (cursor) {
          console.log(cusor)
          // 继续下一个游标项
          cursor.continue();
        }
        else {
          alert("No more entries!");
        }
      };
    8. 索引
      var index = objectStore.index("name");
      index.get(name).onsuccess = function(event) {
        console.log(event.target.result)
      };
      
      index.openCursor().onsuccess = function(event) {
        var cursor = event.target.result;
        if (cursor) {
          // cursor.key 是一个 name, 然后 cursor.value 是整个对象。
          cursor.continue();
        }
      };
      
      index.openKeyCursor().onsuccess = function(event) {
        var cursor = event.target.result;
        if (cursor) {
          // cursor.key 是一个 name,  然后 cursor.value 是那个主键。
          // 没有办法可以得到存储对象的其余部分。
          cursor.continue();
        }
      };
      
      // openCursor(val)可以传参数(具体的key或者范围)
    9. 如果是浏览器主窗体线程开发,同时存储数据结构简单,例如,就存个true/false,显然localStorage上上选;如果数据结构比较复杂,同时对浏览器兼容性没什么要求,可以考虑使用indexedDB;如果是在Service Workers中开发应用,只能使用indexedDB数据存储。
    10. 局限性:
      全球多种语言混合存储。国际化支持不好。需要自己处理

      和服务器端数据库同步。你得自己写同步代码

      全文搜索

      ps(在以下情况下,数据库可能被清除):

      用户请求清除数据
      浏览器处于隐私模式。最后退出浏览器的时候,数据会被清除
      硬盘等存储设备的容量到限
      不正确的
      不完整的改变
    11. 写一个demo(参考HTML5 indexedDB前端本地存储数据库实例教程),增加了查询,清空等功能;
      <!DOCTYPE html>
      <html lang="en">
      <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
      </head>
      <body>
          <form id="form">
              <p>项目名称:<input required name="name" autocomplete="off" required></p>
              <p>开始时间:<input type="date" value="2017-07-16" name="begin" required></p>
              <p>预计结束:<input type="date" value="2057-07-16" name="end" required></p>
              <p>参与人员:<input name="person" placeholder="多人空格分隔" required autocomplete="off"></p>
              <p>补充说明:<textarea rows="5" placeholder="非必填" name="remark"></textarea></p>
              <p><input type="submit" value="确定创建"></p>
          </form>
          <p>查询:<input type='text' required id='searchVal'><button id='search'>Search</button></p>
          <button id='clear'>clear</button>
          
          <div id="result" class="result">
              <table>
                  <thead>
                      <tr>
                          <th>项目名称</th>
                          <th>开始时间</th>
                          <th>结束时间</th>
                          <th>参与人员</th>
                          <th>补充说明</th>
                          <th>操作</th>
                      </tr>
                  </thead>
                  <tbody></tbody>
              </table>
              <div id="status" class="status">加载中...</div>
          </div>
          
          <!-- 列表数据模板 -->
          <script id="tplList" type="text/template">
          <tr>
              <td data-key="name" data-id="$id$" contenteditable="plaintext-only">$name$</td>
              <td data-key="begin" data-id="$id$" contenteditable="plaintext-only">$begin$</td>
              <td data-key="end" data-id="$id$" contenteditable="plaintext-only">$end$</td>
              <td data-key="person" data-id="$id$" contenteditable="plaintext-only">$person$</td>
              <td data-key="remark" data-id="$id$" contenteditable="plaintext-only">$remark$</td>
              <td><a href="javascript:" role="button" class="jsListDel" data-id="$id$">删除</a></td>
          </tr>
          </script>
          <script>
          (function () {
              // 元素们
              var eleForm = document.querySelector('#form');
              var eleTbody = document.querySelector('#result tbody');
              var eleStatus = document.getElementById('status');
              var search = document.getElementById('search');
              var searchVal = document.getElementById('searchVal');
              var clear = document.getElementById('clear');
              // 模板字符内容
              var strTplList = document.getElementById('tplList').innerHTML;
              
              var logError = function (error) {
                  eleStatus.style.display = 'block';
                  eleStatus.innerHTML = '<span class="error">'+ error +'</span>';
              }, logInfo = function (info) {
                  eleStatus.style.display = 'block';
                  eleStatus.innerHTML = '<span class="info">'+ info + '</span>';
              };
              
              // 简易模板方法
              String.prototype.temp = function(obj) {
                  return this.replace(/$w+$/gi, function(matchs) {        
                      return obj[matchs.replace(/$/g, "")] || '';
                  });
              };
              
              // 本演示使用的数据库名称
              var dbName = 'project';
              // 版本
              var version = 1;
              // 数据库数据结果
              var db;
          
              // 打开数据库
              var DBOpenRequest = window.indexedDB.open(dbName, version);
              
              // 如果数据库打开失败
              DBOpenRequest.onerror = function(event) {
                  logError('数据库打开失败');
              };
              
              DBOpenRequest.onsuccess = function(event) {        
                  // 存储数据结果
                  db = DBOpenRequest.result;
                  
                  // 显示数据
                  method.show();
              };
              
              // 下面事情执行于:数据库首次创建版本,或者window.indexedDB.open传递的新版本(版本数值要比现在的高)
              DBOpenRequest.onupgradeneeded = function(event) {
                  var db = event.target.result;
               
                  db.onerror = function(event) {
                      logError('数据库打开失败');
                  };
              
                  // 创建一个数据库存储对象
                  var objectStore = db.createObjectStore(dbName, { 
                      keyPath: 'id',
                      autoIncrement: true
                  });
              
                  // 定义存储对象的数据项
                  objectStore.createIndex('id', 'id', {
                      unique: true    
                  });
                  objectStore.createIndex('name', 'name');
                  objectStore.createIndex('begin', 'begin');
                  objectStore.createIndex('end', 'end');
                  objectStore.createIndex('person', 'person');
                  objectStore.createIndex('remark', 'remark');
              };
              
              search.addEventListener('click', function(){
                method.search(searchVal.value);
              })
              clear.addEventListener('click', function(){
                method.clear();
              })
      
              var method = {
                  add: function (newItem) {
                      var transaction = db.transaction([dbName], "readwrite");
                      // 打开已经存储的数据对象
                      var objectStore = transaction.objectStore(dbName);
                      // 添加到数据对象中
                      var objectStoreRequest = objectStore.add(newItem);        
                      objectStoreRequest.onsuccess = function(event) {
                          method.show();
                      };
                  },
                  edit: function (id, data) {
                      // 编辑数据
                      var transaction = db.transaction([dbName], "readwrite");
                      // 打开已经存储的数据对象
                      var objectStore = transaction.objectStore(dbName);
                      // 获取存储的对应键的存储对象
                      var objectStoreRequest = objectStore.get(id);
                      // 获取成功后替换当前数据
                      objectStoreRequest.onsuccess = function(event) {
                          // 当前数据
                          var myRecord = objectStoreRequest.result;
                          // 遍历替换
                          for (var key in data) {
                              if (typeof myRecord[key] != 'undefined') {
                                  myRecord[key] = data[key];
                              }
                          }
                          // 更新数据库存储数据                
                          objectStore.put(myRecord);
                      };
                  },
                  del: function (id) {
                      // 打开已经存储的数据对象
                      var objectStore = db.transaction([dbName], "readwrite").objectStore(dbName);            
                      // 直接删除            
                      var objectStoreRequest = objectStore.delete(id);
                      console.log(objectStoreRequest);
                      // 删除成功后
                      objectStoreRequest.onsuccess = function() {
                          method.show();
                      };
                  },
                  clear: function(){
                      var objectStore = db.transaction([dbName], 'readwrite').objectStore(dbName);
                      objectStore.clear();
                        method.show();lo
                  },
                  search: function(val){
                      var objectStore = db.transaction([dbName], 'readwrite').objectStore(dbName);
                      var index = objectStore.index('name');
                      var htmlProjectList = '';
                      index.openCursor(val).onsuccess = function(){
                        var cursor = event.target.result;
                        if (cursor) {
                          htmlProjectList = htmlProjectList + strTplList.temp(cursor.value);            
                          // 继续下一个游标项
                          cursor.continue();
                          // 如果全部遍历完毕
                        }else {
                          logInfo('');
                          eleTbody.innerHTML = htmlProjectList;
                          if (htmlProjectList == '') {
                              logInfo('暂无数据');    
                          }
                        }
                      };
                  },
                  show: function () {
                      // 最终要展示的HTML数据
                      var htmlProjectList = '';
                      // 打开对象存储,获得游标列表
                      var objectStore = db.transaction(dbName).objectStore(dbName);
                      objectStore.openCursor().onsuccess = function(event) {
                          var cursor = event.target.result;
                          // 如果游标没有遍历完,继续下面的逻辑
                          if (cursor) {
                              htmlProjectList = htmlProjectList + strTplList.temp(cursor.value);            
                              // 继续下一个游标项
                              cursor.continue();
                          // 如果全部遍历完毕
                          } else {
                              logInfo('');
                              eleTbody.innerHTML = htmlProjectList;
                              
                              if (htmlProjectList == '') {
                                  logInfo('暂无数据');    
                              }
                          }
                      }
                  }
              };
              
              // 表单提交新增数据
              eleForm.addEventListener('submit', function (event) {
                  event.preventDefault();    
                  
                  var formData = {};
                  
                  [].slice.call(this.querySelectorAll('input,textarea')).forEach(function (ele) {
                      if (ele.name) {
                          formData[ele.name] = ele.value;    
                      }
                  });
                      
                  // 添加新的数据
                  method.add(formData);
                  
                  this.reset();
              });
              
              // 编辑事件
              eleTbody.addEventListener('focusout', function (event) {
                  var eleTd = event.target;
                  // 获取id,也就是获得主键
                  var id = eleTd && eleTd.getAttribute('data-id');
                  if (!id || !/td/.test(eleTd.tagName)) { return; }
                  
                  // 这是要替换的数据
                  var data = {
                      id: id * 1    
                  };
                  // 获得现在的数据
                  [].slice.call(eleTd.parentElement.querySelectorAll('td[data-key]')).forEach(function (td) {
                      var key = td.getAttribute('data-key');
                      var value = td.innerText || td.textContent || '';
                      
                      data[key] = value;
                  });
                  
                  // 更新本地数据库
                  method.edit(id, data);
              });
              // 删除事件
              eleTbody.addEventListener('click', function (event) {
                  var eleBtn = event.target, id = '';
                  if (eleBtn && eleBtn.classList.contains('jsListDel') && (id = eleBtn.getAttribute('data-id'))) {
                      method.del(id * 1);    
                      event.preventDefault();        
                  }
              });
          })();
        </script>
      </body>
      </html>
      View Code
  • 相关阅读:
    天乙社区后台管理分析(一)
    [Android Webkit]JNI基础及Java层与C++层的交互
    1033
    pat 1049. Counting Ones (30)
    juce: 跨平台的C++用户界面库
    高性能MySql进化论(一):数据类型的优化_上
    url参数中有+、空格、=、%、&、#等特殊符号的处理
    带环单链表的问题
    在SQL Server 中启用 FileStream
    (2)入门指南——(2)jQuery可以做什么(What jQuery does)
  • 原文地址:https://www.cnblogs.com/colima/p/9283385.html
Copyright © 2011-2022 走看看