一个简单的本地存储操作,直接操作模型的方式操作缓存

来源:互联网 发布:域名解析隐藏端口号 编辑:程序博客网 时间:2024/06/03 15:12

一个简单的本地存储操作,直接操作模型的方式操作缓存
eg:

   var m = store.config({model: {name: '韩没灭',age: 16,child: {name: '李磊',age: 1,books:  [1,2,3,4]}},namespace: 'test'});  m.defineProperty('bbb', {}).defineProperty('b', {a:1});  console.log(m.getProperty('bbb.b.a'));  console.log(m.bbb.b.a)  m.forEach(function(value, key){console.log(value, key)}, true)
(function (factory) {    if (typeof define === 'function' && define.amd) {        define(factory)    } else {        window.store = factory()    }})(function () {    'use strict'    var utils = {        isArray: function (obj) {            return Object.prototype.toString.call(obj) === '[object Array]'        },        isString: function (obj) {            return Object.prototype.toString.call(obj) === '[object String]'        },        isFunction: function (obj) {            return Object.prototype.toString.call(obj) === '[object Function]'        },        isUndefined: function (obj) {            return Object.prototype.toString.call(obj) === '[object Undefined]'        },        isObject: function (obj) {            return Object.prototype.toString.call(obj) === '[object Object]'        }    }    function Proxy(model) {        if (model) {            var data = clone(model),                self = this            Object.defineProperty(self, '$M', {                get: function () {                    return model                }            })            Object.defineProperty(self, '$D', {                get: function () {                    return data                }            })            if (utils.isArray(model)) {                Object.defineProperty(this, 'length', {                    get: function () {                        return this.$M.length                    }                })                new Array('forEach','map','filter','some','every','indexOf','lastIndexOf','reduce','reduceRight').forEach(function(method){                    self[method] = function (callback) {                        this.$M[method] (function(){                            callback.apply(self, Array.prototype.slice.call(arguments).slice())                        })                    }                })                this.push = function (val) {                    var len = this.$M.length                    this.$M.push(val)                    this.$P.self.listen(this.$P.$K + '.' + len, val, null)                }                this.isEmpty = function () {                    return this.$M.length === 0                }                this.set = function (i, val) {                    var self = this                    this.$M[i] = val                    this.$P.self.listen(this.$P.$K + '.' + i, val, null)                }                this.reverse = function () {                    return this.$M.slice(0).reverse()                }                this.reverseEach = function (callback) {                    this.$M.slice(0).reverse().forEach(callback)                }                this.get = function (i) {                    return i>= 0 ? this.$M[i] : self.$M[this.length  + i]                }                return this            }            Object.keys(model).forEach(function (key) {                if (utils.isObject(model[key]) || utils.isArray(model[key])) {                    data[key] = new Proxy(model[key])                    Object.defineProperty(data[key], '$P', {                        get: function () {                            return {$K: key, $D: data, self: self}                        }                    })                } else if (utils.isFunction(model[key])) {                    data[key] = new Proxy(model[key]())                    Object.defineProperty(data[key], '$P', {                        get: function () {                            return {$K: key, $D: data, self: self}                        }                    })                }                Object.defineProperty(self, key, {                    get: function () {                        return data[key]                    },                    set: function (value) {                        var oldVal = data[key], newVal = value;                        if(utils.isObject(newVal) || utils.isArray(newVal)) {                            data[key] = new Proxy(newVal)                            Object.defineProperty(data[key], '$P', {                                get: function () {                                    return {$K: key, $D: self.$D, self: self}                                }                            })                        } else {                            data[key] = newVal                        }                        self.listen(key, newVal, oldVal)                        model[key] = value                    }                })            })        }        return this    }    /**     *     * @param callback function(value, key)     * @param recursion true | false     */    Proxy.prototype.forEach = function (callback, recursion) {        console.assert(callback, 'callback is must!')        for(var prop in this.$D) {            if(this.$D[prop].forEach && recursion) {                this.$D[prop].forEach(callback)            } else {                callback.call(this, this.$M[prop], prop)            }        }    }    Proxy.prototype.size = function () {        return this.$M.length || Object.keys(this.$M).length    }    /**     *     * @param propertyName a.b.c.d     * @param proxy trye | false     */    Proxy.prototype.getProperty = function (propertyName, proxy) {        return getField(proxy ? this.$D :  this.$M, propertyName)    }    Proxy.prototype.removeProperty = function (propertyName) {        this[propertyName] = undefined    }    Proxy.prototype.defineProperty = function(propertyName, propertyVal) {        var self = this        if (utils.isObject(propertyVal) || utils.isArray(propertyVal)) {            self.$D[propertyName] = new Proxy(propertyVal)            Object.defineProperty(self.$D[propertyName], '$P', {                get: function () {                    return {$K: propertyName, $D: self.$D, self: self}                }            })        } else if (utils.isFunction(propertyVal)) {            self.$D[propertyName] = new Proxy(propertyVal())            Object.defineProperty(self.$D[propertyName], '$P', {                get: function () {                    return {$K: propertyName, $D: self.$D, self: self}                }            })        } else {            self.$D[propertyName] = propertyVal        }        if(!self[propertyName]) {            Object.defineProperty(self, propertyName, {                get: function () {                    return self.$D[propertyName]                },                set: function (value) {                    if(utils.isObject(value) || utils.isArray(value)) {                        self.$D[propertyName] = new Proxy(value)                        Object.defineProperty(self.$D[propertyName], '$P', {                            get: function () {                                return {$K: propertyName, $D: self.$D, self: self}                            }                        })                    }                    self.listen(propertyName, value, self.$D[propertyName])                    self.$M[propertyName] = value                }            })        }        self.listen(propertyName, propertyVal, self.$D[propertyName])        return self[propertyName]    }    var keys = function (proxy, prop) {        var array = [].concat(prop),            p = proxy.$P        if (p) {            array = array.concat(keys(p.self, p.$K))        }        return array    }    Proxy.prototype.listen = function (prop, newVal, oldVal) {        if (newVal instanceof Proxy) newVal = newVal.$M        setField(model, keys(this, prop).reverse().join('.'), newVal)        storage.setItem(namespace, JSON.stringify(model))    }    var storage = localStorage, model, namespace, strict    var setField = function (obj, key, val) {        if (key === "") return obj        obj = obj || {}        var dot = key.indexOf('.')        if (dot != -1) {            var k = key.substring(0, dot)            if (utils.isArray(obj)) {                k = k.match(/\d+/)[0]            }            obj[k] = setField(obj[k], key.substring(dot + 1), val)        } else {            if (utils.isArray(obj)) {                key = key.match(/\d+/)[0]            }            obj[key] = val        }        return obj    }    var getField = function (obj, key) {        if (!obj || obj === null) return        if (utils.isString(obj) && obj.indexOf('{') != -1) {            obj = (0, eval)('(' + obj + ')')        }        if (utils.isUndefined(key) || key === '' || key === null) return obj        var keys = []        if (key.indexOf('.') != -1) {            keys = key.split('.')        } else {            keys.push(key)        }        var val        if (utils.isObject(obj)) {            for (var i = 0;i < keys.length;i++) {                var ak = keys[i]                if (utils.isArray(obj)) {                    ak = ak.match(/\d+/)[0]                }                obj = obj[ak]                if (!obj) return            }            val = obj        }        return val    }    function parseKey(key) {        var spiltIndex = key.indexOf(':')        if (spiltIndex === -1) return key        namespace = key.substring(0, spiltIndex)        return key.substring(spiltIndex + 1)    }    function init() {        if (storage.getItem(namespace) === null) {            model = model || {}            storage.setItem(namespace, JSON.stringify(model))        } else {            model = JSON.parse(storage.getItem(namespace))        }    }    function clone(obj) {        if (null === obj || 'object' !== typeof obj) return obj        if (obj instanceof Date) {            var copy = new Date()            copy.setTime(obj.getTime())            return copy        }        if (obj instanceof Array) {            var copy = []            for (var i = 0, len = obj.length;i < len;++i) {                copy[i] = clone(obj[i])            }            return copy        }        if (obj instanceof Object) {            var copy = {}            for (var attr in obj) {                if (obj.hasOwnProperty(attr)) copy[attr] = clone(obj[attr])            }            return copy        }        throw new Error('Unable to copy obj! Its type isn\'t supported.')    }    return {        setStorage: function (store) {            storage = store || localStorage        },        /**         * @param options {namespace:'', model:'', strict: false, storage: localStorage}         */        config: function (options) {            options = options || {}            namespace = options.namespace || 'DEFAULT_STORE_KEY'            strict = options.strict || false //如果开启 则无法存储model中不存在的属性            this.setStorage(options.store || localStorage)            model = clone(options.model)            init.call(this)            return new Proxy(model)        },        refresh: function () {            storage.setItem(namespace, JSON.stringify(model))        },        set: function (key, value) {            key = parseKey(key)            init.call(this)            if (strict && !model[key]) {                throw new Error('Can not insert under strict mode')            }            setField(model, key, value)            this.refresh()        },        get: function (key) {            key = parseKey(key)            init.call(this)            return getField(model, key)        },        remove: function (key) {            init.call(this)            delete model[key]            this.refresh()        },        each: function (callback) {            init.call(this)            if (!callback || typeof callback !== 'function') {                throw new Error('callback must!')            }            for (var prop in this.model) {                callback.call(this, model[prop], prop)            }        },        keys: function () {            init.call(this)            return Object.keys(model)        },        pretty: function () {            init.call(this)            var pretty = JSON.stringify(model, null, '  ')            console.log(pretty)            return pretty        },        clear: function () {           if(namespace) storage.removeItem(namespace)            else storage.clear()        }    }})
0 0
原创粉丝点击