操作 localStorage


const BASETAG = '_baseInfo'; // 存储 Storage 配置信息
const INTERVAL = 7 * 24 * 60 * 60 * 1000; // 7天清理一下 localStorage

// Empty Function
function EmplyFunc() {}

// Null Function
function NullFunc() {
    return null;
}

// 空的 Storage,模拟相关接口
const EmplyStorage = {
    size: function() {
        return 0;
    },
    get: NullFunc,
    set: EmplyFunc,
    remove: EmplyFunc,
    clear: EmplyFunc
};

// 根据 type 创建 Storage 对象
function createStorage(type) {
    const storage = (type in window) && window[type];

    return storage ? {
        // 获取 Size
        size: function() {
            return storage.length;
        },
        // 通过 index 获取键值 key
        key: (function() {
            return storage.key ? function(index) {
                return storage.key(index);
            } : NullFunc;
        })(),
        // 通过键值 key 获取数据
        get: (function() {
            return storage.getItem ? function(key) {
                try {
                    return JSON.parse(storage.getItem(key));
                } catch (e) {
                    return null;
                }
            } : NullFunc;
        })(),
        // 设置键值 key 对应的数据值为 value
        set: (function() {
            return storage.setItem ? function(key, value) {
                try {
                    return storage.setItem(key, JSON.stringify(
                        value));
                } catch (e) {
                    return void 0;
                }
            } : EmplyFunc;
        })(),
        // 移除键值 key 对应的数据项
        remove: (function() {
            return storage.removeItem ? function(key) {
                return storage.removeItem(key);
            } : EmplyFunc;
        })(),
        // 清除数据
        clear: (function() {
            return storage.clear ? function() {
                return storage.clear();
            } : EmplyFunc;
        })()
    } : EmplyStorage;
}

// 获取当前时间
function now() {
    return new Date().getTime();
}

// Storage 对象 和 本地缓存
const ls = createStorage('localStorage');
const ss = createStorage('sessionStorage');
const cache = {};
let useCache = false;

// 检查数据是否超时,如果超时,删除数据。
// 同时将可用数据加入本地缓存,方面以后获取
function checkExpires() {
    let i;
    let key;
    let len;
    let time = now();
    let value;

    for (i = 0, len = ls.size(); i < len; i++) {
        key = ls.key(i);
        value = ls.get(key);
        if (value && key !== BASETAG) {
            if (value.expires > 0 && value.createTime + value.expires < time) {
                ls.remove(key);
            } else {
                cache[key] = value.data;
            }
        }
    }
}

// 主方法
const Storage = function(key, value, time) {
    const argsNum = arguments.length;
    let data = null;

    // 一个参数时,是获取数据
    if (argsNum === 1) {
        // 检查 key 是否在本地缓存里,如果在直接返回
        if (useCache && key in cache) {
            data = cache[key];
        } else {
            data = ss.get(key) || (function() {
                let tmp = ls.get(key);

                if (tmp) {
                    // 判断数据是否可用(未超时),如果可用,返回,否则删除
                    if (tmp.expires === 0 || (tmp.createTime + tmp.expires >
                            now())) {
                        return tmp.data;
                    }
                    ls.remove(key);
                }
                return null;
            })();
            cache[key] = data;
        }
        return data;
    } else if (argsNum > 1) { // 参数大于1,则肯定是变更操作
        // value值是 undefined 或者 null,都是删除此键值对
        if (value === void 0 || value === null) {
            delete cache[key];
            return ss.remove(key) || ls.remove(key);
        } else {
            // 将值存入缓存
            cache[key] = value;
            time = time || 0;
            // 时间等于 -1, 则存入 SessionStorage
            if (time === -1) {
                return ss.set(key, value);
            } else {
                // 存入 localStorage
                return ls.set(key, {
                    data: value,
                    createTime: now(),
                    expires: time
                });
            }
        }
    }
};

Storage.setCache = function(bool) {
    useCache = !!bool;
};

// 清除数据
Storage.clear = function() {
    const info = ls.get(BASETAG);

    ss.clear();
    ls.clear();
    ls.set(BASETAG, info);
};

// 初始化操作(非必须)
Storage.init = function(version) {
    const info = ls.get(BASETAG) || {};
    let culVersion = info.version;
    let lastCheckTime = info.cTime;
    let changed = false;

    // 判断版本是否相同,如果不同则清空 localStorage
    if (!culVersion || culVersion !== version) {
        changed = true;
        ls.clear();
        culVersion = version;
    }
    // 检查后一次 cheak 时间,如果超过设置时间,而进行一次 check
    if (!lastCheckTime || now() - lastCheckTime > INTERVAL) {
        changed = true;
        checkExpires();
        lastCheckTime = now();
    }
    if (changed) {
        ls.set(BASETAG, {
            version: culVersion,
            cTime: lastCheckTime
        });
    }
};

export default Storage;

推荐阅读更多精彩内容