html5存储技术-笔记

客户端存储历程


关于浏览器缓存和本地存储我接触的时间不长,今天下午抽时间学习了一下,下面是我结合视频、文献资料整理的一些关于html本地存储的一些资料,希望大家会用到!不过我还是觉得application cache是一个很大的坑,第一次用的时候要当心!
-远古时代

  • cookies的用法和缺陷
  • userdata
  • -HTML5时代

  • localstorage
  • application cache
  • indexedDB
  • 关于存储
    存储包含:cache(缓存)、磁盘文件、数据库、内存

    h5之前

    cookies
    缺点:

  • 1.http请求头上会带着
  • 2.大小4k
  • 3.主Domain污染(主域名污染)
  • cookies在浏览器端的存储形态
    Name, Value, Dommain(域名), Path(路径), EXPIR…(过期时间), size(大小)

    UserData

  • 只有IE支持
  • XML文件
  • H5的几种存储方式

    几种存储形式

  • 本地存储(localstorage && sessionstorage)
  • 离线缓存(application cache)
  • IndexedDB和web SQL
  • API
    -locastorage && sessionstorage

    存储形式
    -key > value

    过期
    -永久存储,永不失效,除非手动删除

    大小
    -官方给出的文档是,每个域名5M

    使用案例

    //localstotage
    localstotage.setItem('test1','test1');//新建一个name为test1、value为test1的字段
    localstorage.getItem('test1');//获取第一个name为test1的字段的value
    
    localstorage.key(0);//获取第一个键值对的数据
    
    localstorage.clear();//清楚存储
    
    //sessionstorage
    sessionstorage.setItem('test1','test1');//新建一个name为test1、value为test1的字段
    
    

    使用注意事项:

  • 1.使用前要判断浏览器是否支持(ie8及其以上)!
  • 2.写数据时候,需要异常处理,避免超出容器抛错!
  • 3.避免把敏感信息存入localstorage;
  • 4.key的唯一性
  • 使用限制

  • 1.存储更新策略,过期控制;
  • 2.子域名之间不能共享存储数据;
  • 3.超出存储大小之后如何存储(LRU,FIFO);
  • 4.sercer端如何取到
  • 使用场景

  • 1.利用本地数据,减少网络传输;
  • 2.弱网络环境下,高延迟、低带宽,尽量吧数据本地化;
  • web sql和indexedDB

    一种能在浏览器中持久地存储结构化数据的数据库,并且为web应用提供了丰富的查询能力;
    浏览器支持
    chrome 11+ ,opera不支持 ,firefox 4+ ,ie10+

    打开数据库

    var request=window.indexedDB.open('testDB');
    

    除了result,IDBOpenDBRequest接口定义了几个重要属性

  • onerror: 请求失败的回调函数句柄
  • onsuccess:请求成功的回调函数句柄
  • onupgradeneeded:请求数据库版本变化句柄
  • 所谓异步API是指并不是这条指令执行完毕,我们就可以使用request.result来获取indexedDB对象了,就像使用ajax一样,语句执行完并不代表已经获取到了对象,所以我们一般在其回调函数中处理。

    创建数据库
    刚才的语句已经展示了如何打开一个indexedDB数据库,调用indexedDB.open方法就可以创建或者打开一个indexedDB。看一个完整的处理

    function openDB (name) {
                var request=window.indexedDB.open(name);
                request.onerror=function(e){
                    console.log('OPen Error!');
                };
                request.onsuccess=function(e){
                    myDB.db=e.target.result;
                };
            }
    
            var myDB={
                name:'test',
                version:1,
                db:null
            };
            openDB(myDB.name);
    

    object store
    有了数据库后我们自然希望创建一个表用来存储数据,但indexedDB中没有表的概念,而是objectStore,一个数据库中可以包含多个objectStore,objectStore是一个灵活的数据结构,可以存放多种类型数据。也就是说一个objectStore相当于一张表,里面存储的每条数据和一个键相关联。

    我们可以使用每条记录中的某个指定字段作为键值(keyPath),也可以使用自动生成的递增数字作为键值(keyGenerator),也可以不指定。选择键的类型不同,objectStore可以存储的数据结构也有差异

    键类型 存储数据
    不使用 任意值,但是没添加一条数据的时候需要指定键参数
    keyPath Javascript对象,对象必须有一属性作为键值
    keyGenerator 任意值
    都使用 Javascript对象,如果对象中有keyPath指定的属性则不生成新的键值,如果没有自动生成递增键值,填充keyPath指定属性

    事务
    在对新数据库做任何事情之前,需要开始一个事务。事务中需要指定该事务跨越哪些object store。

    事务具有三种模式

  • 只读:read,不能修改数据库数据,可以并发执行
  • 读写:readwrite,可以进行读写操作
  • 版本变更:verionchange
  • 给object store添加数据
    调用数据库实例的createObjectStore方法可以创建object store,方法有两个参数:store name和键类型。调用store的add方法添加数据。有了上面知识,我们可以向object store内添加数据了

    keyPath

    因为对新数据的操作都需要在transaction中进行,而transaction又要求指定object store,所以我们只能在创建数据库的时候初始化object store以供后面使用,这正是onupgradeneeded的一个重要作用,修改一下之前代码

    function openDB (name,version) {
                var version=version || 1;
                var request=window.indexedDB.open(name,version);
                request.onerror=function(e){
                    console.log(e.currentTarget.error.message);
                };
                request.onsuccess=function(e){
                    myDB.db=e.target.result;
                };
                request.onupgradeneeded=function(e){
                    var db=e.target.result;
                    if(!db.objectStoreNames.contains('students')){
                        db.createObjectStore('students',{keyPath:"id"});
                    }
                    console.log('DB version changed to '+version);
                };
            }
    

    这样在创建数据库的时候我们就为其添加了一个名为students的object store,准备一些数据以供添加

    var students=[{ 
                id:1001, 
                name:"Byron", 
                age:24 
            },{ 
                id:1002, 
                name:"Frank", 
                age:30 
            },{ 
                id:1003, 
                name:"Aaron", 
                age:26 
            }];
    
    function addData(db,storeName){
                var transaction=db.transaction(storeName,'readwrite'); 
                var store=transaction.objectStore(storeName); 
    
                for(var i=0;i<students.length;i++){
                    store.add(students[i]);
                }
            }
    
    
    openDB(myDB.name,myDB.version);
            setTimeout(function(){
                addData(myDB.db,'students');
            },1000);
    
    

    这样我们就在students object store里添加了三条记录,以id为键,在chrome控制台看看效果

    keyGenerate

    function openDB (name,version) {
                var version=version || 1;
                var request=window.indexedDB.open(name,version);
                request.onerror=function(e){
                    console.log(e.currentTarget.error.message);
                };
                request.onsuccess=function(e){
                    myDB.db=e.target.result;
                };
                request.onupgradeneeded=function(e){
                    var db=e.target.result;
                    if(!db.objectStoreNames.contains('students')){
                        db.createObjectStore('students',{autoIncrement: true});
                    }
                    console.log('DB version changed to '+version);
                };
            }
    

    剩下的两种方式有兴趣同学可以自己摸索一下了

    查找数据
    可以调用object store的get方法通过键获取数据,以使用keyPath做键为例

    function getDataByKey(db,storeName,value){
                var transaction=db.transaction(storeName,'readwrite'); 
                var store=transaction.objectStore(storeName); 
                var request=store.get(value); 
                request.onsuccess=function(e){ 
                    var student=e.target.result; 
                    console.log(student.name); 
                };
    }
    
    

    更新数据
    可以调用object store的put方法更新数据,会自动替换键值相同的记录,达到更新目的,没有相同的则添加,以使用keyPath做键为例

    function updateDataByKey(db,storeName,value){
                var transaction=db.transaction(storeName,'readwrite'); 
                var store=transaction.objectStore(storeName); 
                var request=store.get(value); 
                request.onsuccess=function(e){ 
                    var student=e.target.result; 
                    student.age=35;
                    store.put(student); 
                };
    }
    

    删除数据及object store

    调用object store的delete方法根据键值删除记录

    
    function deleteDataByKey(db,storeName,value){
                var transaction=db.transaction(storeName,'readwrite'); 
                var store=transaction.objectStore(storeName); 
                store.delete(value); 
            }
    

    调用object store的clear方法可以清空object store

    
    function clearObjectStore(db,storeName){
                var transaction=db.transaction(storeName,'readwrite'); 
                var store=transaction.objectStore(storeName); 
                store.clear();
    }
    

    调用数据库实例的deleteObjectStore方法可以删除一个object store,这个就得在onupgradeneeded里面调用了

    if(db.objectStoreNames.contains('students')){ 
                        db.deleteObjectStore('students'); 
    }
    

    H5离线缓存

    什么是离线缓存(offline application)
    它可以让web应用在离线的情况下继续使用,通过manifest文件指明需要缓存的资源

    检测是否在线

    navigator.onLine

    只要每次更新manifest就可以重新加载资源

    CHCHE MANIFEST
    #version n.n
    
    CACHE:
    #需要缓存的文件
    /css/sample.css
    /images/image.jpg
    
    NETWORK:
    #每次重新拉取的文件
    *
    
    FALLBACK
    #离线状况下代替文件
    /offline.html
    

    在html页面引入manifest文件

    <html manifest="sample.appcache">
    

    在服务器添加mime-type text/cache-manifest

    更新测试(Test for updates)

    做个测试来看一下是否可以通过Javascript来程序操作一个可用的更新过的缓存清单。缓存已经在检测更新的脚本使用之前被更新,脚本会时常检测window.applicationCache.status.

    function onUpdateReady(){
    
              alert('found new version!");
    
    }
    
    window.applicationCache.addEventListener('updateready', onUpdateReady);
    
    if(window.applicationCache.status == window.applicationCache.UPDATEREADY){
    
            onUpdateReady();
    
    }
    
    

    你可以使用window.applicationCache.update()手动测验一个新的清单。

    共有 2 条评论

    Top