HTML5   发布时间:2022-04-25  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了H5之「离线应用」大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

H5之「离线存储」

「离线存储」:顾名思义,在有线的环境下先缓存数据(包括静态资源,动态资源),从而在离线环境下,依旧可以正常使用应用(单页应用)

静态资源存储(ApplicationCachE)

applicationCache 是一套h5静态资源缓存方案.
利用该技术可以实现配置静态资源/转发请求,加快应用加载速度,降低服务器负载.

基本用法

  1. 引入manifest配置文件

    @H_801_19@
<!doctype html>
<html manifest="cache.manifest">
    <head>
        ...
    </head>
    <body>
        ...
    </body>
</html>
  1. 配置manifest文件

    @H_801_19@
CACHE MANIFEST
# 修改配置后,附加上下面一段js代码,才能更新缓存
# 2016972143
# 注释:需要缓存的文件,无论在线与否,均从缓存里读取
CACHE:
/dist/0.eda078350ef514670764.bundle.js
/dist/common.bundle.js?v=2016972143
/dist/df9f379beae2559b27044dcfdc0653ab.png?v=2016972143
/dist/home.bundle.js?v=2016972143
/dist/home.css?v=2016972143
uncached.js?v=2016972143

#cached.css

# 注释:不缓存的文件,无论缓存中存在与否,均从新获取
NETWORK:
*
#uncached.js
#uncached.css

# 注释:获取不到资源时的备选路径,如index.html访问失败,则返回404页面
falLBACK:
#/v1/team/dirlists mock/team_dirlists.json
#/v1/team/app_filelist?isAdd=0&source=team&page=1&pageSize=10&sort=ftime&from=hiwebapp&fid=t293 mock/team_app_filelist.json
#index.html 404.html
  1. 书写更新缓冲js

    @H_801_19@
// 每次打开页面执行该代码段,更新缓存
// !!! 注意:更新缓存后不会立即生效,需要重新加载页面
(function () {
    var cache = window.applicationCache;

    cache.addEventListener('updateready',function(E) {
        if (cache.status == cache.updatEREADY) {
            // Browser downloaded a new app cache.
            // if (confirm('A new version of this site is available. Load it?')) {
                cache.swapCache();
                window.LOCATIOn.reload();
            // }
        } else {
            // Manifest didn't changed. Nothing new to server.
        }
    },falsE);

    cache.update()

}())
  1. 服务器配置

    1. 配置manifest文件,响应 Content-Type: text/cache-manifest Cache-Control: max-age=0

      @H_801_19@
    2. 部署线上代码时更新manifest版本号与配置

      @H_801_19@

    按照以上配置,这样就能实现静态资源缓存

    @H_801_19@

H5之「离线应用」

如上图from cache的加载时间相比其他网络请求快得多!
其中的fetch/ajax请求不能够通过静态资源存储,因为响应结果是可能会变的.

那么对于异步ajax请求(动态资源)要通过什么方法才能存储起来呢?实现真正意义的离线存储.

动态资源存储(Websql/IndexedDB)

使用前端数据库可以较为灵活的控制动态资源存储,在这里我使用了indexedDB,为什么不用Websql

  1. 之前做在线聊天应用时,使用过Websql存储聊天记录

    @H_801_19@
  2. Websql已经被弃用

    @H_801_19@
  3. Websql是传统的关系数据库,indexedDB是主流的Nosql DB

    @H_801_19@

基本用法

  1. 创建一个通用的数据库访问接口

    @H_801_19@
var indexedDB = window.indexedDB || window.msIndexedDB || window.mozIndexedDB || window.webkiTindexedDB;

// memCache 内存缓冲,避免频繁的读写数据库
var req,db,memCache = {};
if(indexedDB) {
    // version:2
    req = indexedDB.open('ajax_cache',2);
    // 保证caches成功创建
    req.onsuccess = function (E) {
        db = e.target.result;
        if(!db.objectStorenames.contains('caches')){
            db.createObjectStore('caches',{keyPath: "id"});
        }
    }
    // 数据库版本改变触发
    req.onupgradeneeded=function(E){
        var db=e.target.result;
        if(!db.objectStorenames.contains('caches')){
            db.createObjectStore('caches',{keyPath: "id"});
        }
        console.log('DB version changed to ' + db.version);
    };
    req.onerror = function (err) {
        console.error('indexedDB open Failed. ',err)
    }
}

export default {
    isSupported: !!indexedDB,set: (id,data) => {
        var entity = {
            id: id,data: data
        }
        var transaction = db.transaction('caches','readwrite');
        var store = transaction.objectStore('caches');
        var req = store.put(entity);
        req.onerror = () => {
            console.error('put data Failed. ',entity)
        }
        req.onsuccess = () => {
            memCache[id] = data
            console.info('put data successed. ',entity)
        }
    },get: (id) => {
        return new Promise((resolve,reject) => {
            if(memCache[id]) {
                resolve(memCache[id]);
                return;
            }

            var transaction = db.transaction('caches','readwrite');
            var store = transaction.objectStore('caches');
            var req = store.get(id);
            req.onerror = () => {
                console.error('get data Failed. ',id)
                resolve()
            }
            req.onsuccess = (E) => {
                var rlt = e.target.result;
                console.info('get data successed. ',id,rlt)
                resolve(rlt && rlt.data)
            }
        })
    }
}
  1. 重写fetch/ajax方法

    @H_801_19@
/* reset fetch function for offline be compatible*/
var fetch = require('isomorphic-fetch')
import {parsE} from 'url'

var __fetch = fetch;
fetch = function (url) {
    var rlt = parse(url,truE);
    function generateJson(json) {
        return {
            json: function () {
                return json
            }
        }
    }
    function generateErrorJson() {
        return generateJson({
            errno: 500,errmsg: '你正处于离线状态',result: {
                files: []
            }
        })
    }
    var query = rlt.query;
    // 去掉时间戳与重复的from参数
    delete query.t;
    delete query.from;
    var id = rlt.pathname
    var key = MyUtils.jsonToUrl(query)
    if(MyUtils.isOffline()) { // 离线
        if(!id) {
            return new Promise((resolve,reject) => {
                resolve(generateErrorJson())
            })
        } else {
            if(DB.isSupported) {
                return DB.get(id).then(json => {
                    return (!json || !json[key])
                        ? generateErrorJson()
                        : generateJson(json[key])
                })
            } else {
                return new Promise((resolve,reject) => {
                    resolve(generateErrorJson())
                })
            }
        }
    } else {
        return __fetch.apply(null,[].slice.call(arguments))
            .then(res => res.json())
            .then( (resJson) => {
                if(DB.isSupported) {
                    var tmp = {};
                    tmp[key] = resJson;
                    DB.get(id).then(json => {
                        DB.set(id,Object.assign({},json,tmp))
                    })
                }
                return generateJson(resJson)
            }
        )
    }

}

可以在chrome的web tool中看到indexedDB

H5之「离线应用」

每次请求都缓存下来了

在脱离网络后!依旧可以模拟异步请求!

大佬总结

以上是大佬教程为你收集整理的H5之「离线应用」全部内容,希望文章能够帮你解决H5之「离线应用」所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。