diff --git a/src/js/anot-touch.js b/src/js/anot-touch.js index c9c5d6d..4258fe6 100644 --- a/src/js/anot-touch.js +++ b/src/js/anot-touch.js @@ -787,7 +787,7 @@ const _Anot = (function() { switch (arguments.length) { case 2: return window[tpye].getItem(key) - default: + case 3: if ((this.type(val) == 'string' && val.trim() === '') || val === null) { window[tpye].removeItem(key) return @@ -797,6 +797,7 @@ const _Anot = (function() { } else { window[tpye].setItem(key, JSON.stringify(val)) } + break } } @@ -946,11 +947,15 @@ const _Anot = (function() { * @param {[type]} val [键值,为空时删除] * @return */ - ls: function(key, val) { - return cacheStore('localStorage', key, val) + ls: function() { + var args = aslice.call(arguments, 0) + args.unshift('localStorage') + return cacheStore.apply(this, args) }, - ss: function(key, val) { - return cacheStore('sessionStorage', key, val) + ss: function() { + var args = aslice.call(arguments, 0) + args.unshift('sessionStorage') + return cacheStore.apply(this, args) }, /** * [cookie cookie 操作 ] diff --git a/src/js/anot-touch.shim.js b/src/js/anot-touch.shim.js index a26ab24..c8ff95c 100644 --- a/src/js/anot-touch.shim.js +++ b/src/js/anot-touch.shim.js @@ -802,7 +802,7 @@ switch (arguments.length) { case 2: return window[tpye].getItem(key) - default: + case 3: if ((this.type(val) == 'string' && val.trim() === '') || val === null) { window[tpye].removeItem(key) return @@ -812,6 +812,7 @@ } else { window[tpye].setItem(key, JSON.stringify(val)) } + break } } @@ -961,11 +962,15 @@ * @param {[type]} val [键值,为空时删除] * @return */ - ls: function(key, val) { - return cacheStore('localStorage', key, val) + ls: function() { + var args = aslice.call(arguments, 0) + args.unshift('localStorage') + return cacheStore.apply(this, args) }, - ss: function(key, val) { - return cacheStore('sessionStorage', key, val) + ss: function() { + var args = aslice.call(arguments, 0) + args.unshift('sessionStorage') + return cacheStore.apply(this, args) }, /** * [cookie cookie 操作 ] diff --git a/src/js/anot.js b/src/js/anot.js index c274486..8466b3c 100644 --- a/src/js/anot.js +++ b/src/js/anot.js @@ -787,7 +787,7 @@ const _Anot = (function() { switch (arguments.length) { case 2: return window[tpye].getItem(key) - default: + case 3: if ((this.type(val) == 'string' && val.trim() === '') || val === null) { window[tpye].removeItem(key) return @@ -797,6 +797,7 @@ const _Anot = (function() { } else { window[tpye].setItem(key, JSON.stringify(val)) } + break } } @@ -946,11 +947,15 @@ const _Anot = (function() { * @param {[type]} val [键值,为空时删除] * @return */ - ls: function(key, val) { - return cacheStore('localStorage', key, val) + ls: function() { + var args = aslice.call(arguments, 0) + args.unshift('localStorage') + return cacheStore.apply(this, args) }, - ss: function(key, val) { - return cacheStore('sessionStorage', key, val) + ss: function() { + var args = aslice.call(arguments, 0) + args.unshift('sessionStorage') + return cacheStore.apply(this, args) }, /** * [cookie cookie 操作 ] diff --git a/src/js/anot.shim.js b/src/js/anot.shim.js index a667ac8..3a44037 100644 --- a/src/js/anot.shim.js +++ b/src/js/anot.shim.js @@ -802,7 +802,7 @@ switch (arguments.length) { case 2: return window[tpye].getItem(key) - default: + case 3: if ((this.type(val) == 'string' && val.trim() === '') || val === null) { window[tpye].removeItem(key) return @@ -812,6 +812,7 @@ } else { window[tpye].setItem(key, JSON.stringify(val)) } + break } } @@ -961,11 +962,15 @@ * @param {[type]} val [键值,为空时删除] * @return */ - ls: function(key, val) { - return cacheStore('localStorage', key, val) + ls: function() { + var args = aslice.call(arguments, 0) + args.unshift('localStorage') + return cacheStore.apply(this, args) }, - ss: function(key, val) { - return cacheStore('sessionStorage', key, val) + ss: function() { + var args = aslice.call(arguments, 0) + args.unshift('sessionStorage') + return cacheStore.apply(this, args) }, /** * [cookie cookie 操作 ] diff --git a/src/js/router/index.js b/src/js/router/index.js index 15626a8..d3247d6 100644 --- a/src/js/router/index.js +++ b/src/js/router/index.js @@ -9,38 +9,112 @@ //储存版本信息 Anot.ui.router = '0.0.1' -function Router() { - this.table = { get: [] } - this.errorFn = null - this.history = null - this.hash = '' - this.started = false - this.init = {} +//判定A标签的target属性是否指向自身 +//thanks https://github.com/quirkey/sammy/blob/master/lib/sammy.js#L219 +function targetIsThisWindow(targetWindow) { + if ( + !targetWindow || + targetWindow === window.name || + targetWindow === '_self' || + (targetWindow === 'top' && window == window.top) + ) { + return true + } + return false } -var defaultOptions = { +const DEFAULT_OPTIONS = { + mode: 'hash', // hash | history prefix: /^(#!|#)[\/]?/, //hash前缀正则 historyOpen: true, //是否开启hash历史 allowReload: true //连续点击同一个链接是否重新加载 } -var isMouseUp = true +const RULE_REGEXP = /(:id)|(\{id\})|(\{id:([A-z\d\,\[\]\{\}\-\+\*\?\!:\^\$]*)\})/g -var ruleRegExp = /(:id)|(\{id\})|(\{id:([A-z\d\,\[\]\{\}\-\+\*\?\!:\^\$]*)\})/g +class Router { + constructor(options) { + this.table = [] + this.history = null + this.path = '' + this.options = Object.assign({}, DEFAULT_OPTIONS, options) + this.__listen__() + } -Router.prototype = { - error: function(callback) { - this.errorFn = callback - }, - config: function(opts) { - if (this.started) return console.error('Router config has been set') + // 创建无new式Router实例 + static init(options = {}) { + if (Anot.router) { + throw new Error('不允许重复创建Router实例...') + } + if (!options.allowReload) { + options.historyOpen = true + } - this.started = true - if (!opts.allowReload) opts.historyOpen = true - this.init = Anot.mix({}, defaultOptions, opts) - }, - _getRegExp: function(rule, opts) { - var re = rule.replace(ruleRegExp, function(m, p1, p2, p3, p4) { - var w = '([\\w.-]' + Anot.router = new this(options) + return Anot.router + } + + __listen__() { + let { mode, prefix } = this.options + + Anot.bind(window, 'load, popstate', ev => { + let path = mode === 'hash' ? location.hash : location.pathname + + path = path.replace(prefix, '').trim() + + if (ev.type === 'load') { + this.go(path) + if (mode === 'hash') { + this.__check__() + } + } else { + this.path = path.replace(/^[/]+?/, '') + if (mode === 'hash' || ev.state) { + this.__check__() + } + } + }) + + //劫持页面上所有点击事件,如果事件源来自链接或其内部, + //并且它不会跳出本页,并且以"#/"或"#!/"开头,那么触发go方法 + Anot.bind(document, 'click', ev => { + let prevented = + 'defaultPrevented' in ev + ? ev.defaultPrevented + : ev.returnValue === false + + if (prevented || ev.ctrlKey || ev.metaKey || ev.which === 2) { + return + } + + let target = ev.target + while (target.nodeName !== 'A') { + target = target.parentNode + if (!target || target.tagName === 'BODY') { + return + } + } + if (mode === 'history') { + if (targetIsThisWindow(target.target)) { + let href = + target.getAttribute('href') || target.getAttribute('xlink:href') + + // hash地址,只管修正前缀即可, 会触发popstate事件 + if (prefix.test(href)) { + this.path = href.replace(prefix, '').trim() + } else { + // 非hash地址,则阻止默认事件, 产并主动触发跳转 + // 并强制清除hash + ev.preventDefault() + this.go(href, true) + } + } + } + }) + } + + _getRegExp(rule, opts) { + let re = rule.replace(RULE_REGEXP, function(m, p1, p2, p3, p4) { + let w = '([\\w.-]' if (p1 || p2) { return w + '+)' } else { @@ -58,123 +132,74 @@ Router.prototype = { re = '^' + re + '$' opts.regexp = new RegExp(re) return opts - }, - _add: function(method, rule, callback) { - if (!this.started) this.config({}) + } - var table = this.table[method.toLowerCase()] + __add__(rule, callback) { + // 特殊值"!", 则自动作非匹配回调处理 + if (rule === '!') { + this.notMatch = callback + return + } if (rule.charAt(0) !== '/') { - console.error('char "/" must be in front of router rule') + console.error('路由规则必须以"/"开头') return } rule = rule.replace(/^[\/]+|[\/]+$|\s+/g, '') - var opts = {} - opts.rule = rule - opts.callback = callback - Anot.Array.ensure(table, this._getRegExp(rule, opts)) - }, - _route: function(method, hash) { - var hash = hash.trim() - var table = this.table[method] - var init = this.init + let opts = { rule, callback } - if (!init.allowReload && hash === this.history) return - - if (init.historyOpen) { - this.history = hash - if (Anot.ls) { - Anot.ls('lastHash', hash) - } - } - - for (var i = 0, obj; (obj = table[i++]); ) { - var args = hash.match(obj.regexp) - if (args) { - args.shift() - return obj.callback.apply(obj, args) - } - } - this.errorFn && this.errorFn(hash) - }, - on: function(rule, callback) { - var _this = this - if (Array.isArray(rule)) { - rule.forEach(function(it) { - _this._add('get', it, callback) - }) - } else { - this._add('get', rule, callback) - } + Anot.Array.ensure(this.table, this._getRegExp(rule, opts)) } -} -Anot.bind(window, 'load', function() { - if (!Anot.router.started) return - var prefix = Anot.router.init.prefix - var hash = location.hash - hash = hash.replace(prefix, '').trim() - Anot.router._route('get', hash) -}) - -if ('onhashchange' in window) { - window.addEventListener('hashchange', function(event) { - if (!isMouseUp) return - var prefix = Anot.router.init.prefix - var hash = location.hash.replace(prefix, '').trim() - Anot.router._route('get', hash) - }) -} - -//劫持页面上所有点击事件,如果事件源来自链接或其内部, -//并且它不会跳出本页,并且以"#/"或"#!/"开头,那么触发updateLocation方法 -Anot.bind(document, 'mousedown', function(event) { - var defaultPrevented = - 'defaultPrevented' in event - ? event['defaultPrevented'] - : event.returnValue === false - if (defaultPrevented || event.ctrlKey || event.metaKey || event.which === 2) - return - var target = event.target - while (target.nodeName !== 'A') { - target = target.parentNode - if (!target || target.tagName === 'BODY') { + __check__() { + let { allowReload, historyOpen } = this.options + if (!allowReload && this.path === this.history) { return } + + if (historyOpen) { + this.history = this.path + if (Anot.ls) { + Anot.ls('lastPath', this.path) + } + } + + for (let i = 0, route; (route = this.table[i++]); ) { + let args = this.path.match(route.regexp) + if (args) { + args.shift() + return route.callback.apply(route, args) + } + } + this.notMatch && this.notMatch(this.path) } - if (targetIsThisWindow(target.target)) { - if (!Anot.router.started) return - var href = target.getAttribute('href') || target.getAttribute('xlink:href'), - prefix = Anot.router.init.prefix + // 跳转到路由 + go(path, forceCleanHash = false) { + let { mode, prefix } = this.options - if (href === null || !prefix.test(href)) return - - Anot.router.hash = href.replace(prefix, '').trim() - event.preventDefault() - location.hash = href - isMouseUp = false + if (mode === 'hash') { + path = path.trim().replace(prefix, '') + location.hash = '!/' + path + this.path = path + } else { + let hash = forceCleanHash ? '' : location.hash + path = path.replace(/^[/]+?/, '') + window.history.pushState({ path }, null, `/${path + hash}`) + this.path = path + this.__check__() + } } -}) -Anot.bind(document, 'mouseup', function() { - if (!isMouseUp) { - Anot.router._route('get', Anot.router.hash) - isMouseUp = true + // 绑定路由事件 + on(rule, callback) { + if (Array.isArray(rule)) { + rule.forEach(it => { + this.__add__(it, callback) + }) + } else { + this.__add__(rule, callback) + } } -}) - -//判定A标签的target属性是否指向自身 -//thanks https://github.com/quirkey/sammy/blob/master/lib/sammy.js#L219 -function targetIsThisWindow(targetWindow) { - if ( - !targetWindow || - targetWindow === window.name || - targetWindow === '_self' || - (targetWindow === 'top' && window == window.top) - ) { - return true - } - return false } -export default (Anot.router = new Router()) +export default Router