修复Anot.ls, Anot.ss方法;路由增加history模式
parent
be25a76005
commit
9f3ded27ad
|
@ -787,7 +787,7 @@ const _Anot = (function() {
|
||||||
switch (arguments.length) {
|
switch (arguments.length) {
|
||||||
case 2:
|
case 2:
|
||||||
return window[tpye].getItem(key)
|
return window[tpye].getItem(key)
|
||||||
default:
|
case 3:
|
||||||
if ((this.type(val) == 'string' && val.trim() === '') || val === null) {
|
if ((this.type(val) == 'string' && val.trim() === '') || val === null) {
|
||||||
window[tpye].removeItem(key)
|
window[tpye].removeItem(key)
|
||||||
return
|
return
|
||||||
|
@ -797,6 +797,7 @@ const _Anot = (function() {
|
||||||
} else {
|
} else {
|
||||||
window[tpye].setItem(key, JSON.stringify(val))
|
window[tpye].setItem(key, JSON.stringify(val))
|
||||||
}
|
}
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -946,11 +947,15 @@ const _Anot = (function() {
|
||||||
* @param {[type]} val [键值,为空时删除]
|
* @param {[type]} val [键值,为空时删除]
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
ls: function(key, val) {
|
ls: function() {
|
||||||
return cacheStore('localStorage', key, val)
|
var args = aslice.call(arguments, 0)
|
||||||
|
args.unshift('localStorage')
|
||||||
|
return cacheStore.apply(this, args)
|
||||||
},
|
},
|
||||||
ss: function(key, val) {
|
ss: function() {
|
||||||
return cacheStore('sessionStorage', key, val)
|
var args = aslice.call(arguments, 0)
|
||||||
|
args.unshift('sessionStorage')
|
||||||
|
return cacheStore.apply(this, args)
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* [cookie cookie 操作 ]
|
* [cookie cookie 操作 ]
|
||||||
|
|
|
@ -802,7 +802,7 @@
|
||||||
switch (arguments.length) {
|
switch (arguments.length) {
|
||||||
case 2:
|
case 2:
|
||||||
return window[tpye].getItem(key)
|
return window[tpye].getItem(key)
|
||||||
default:
|
case 3:
|
||||||
if ((this.type(val) == 'string' && val.trim() === '') || val === null) {
|
if ((this.type(val) == 'string' && val.trim() === '') || val === null) {
|
||||||
window[tpye].removeItem(key)
|
window[tpye].removeItem(key)
|
||||||
return
|
return
|
||||||
|
@ -812,6 +812,7 @@
|
||||||
} else {
|
} else {
|
||||||
window[tpye].setItem(key, JSON.stringify(val))
|
window[tpye].setItem(key, JSON.stringify(val))
|
||||||
}
|
}
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -961,11 +962,15 @@
|
||||||
* @param {[type]} val [键值,为空时删除]
|
* @param {[type]} val [键值,为空时删除]
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
ls: function(key, val) {
|
ls: function() {
|
||||||
return cacheStore('localStorage', key, val)
|
var args = aslice.call(arguments, 0)
|
||||||
|
args.unshift('localStorage')
|
||||||
|
return cacheStore.apply(this, args)
|
||||||
},
|
},
|
||||||
ss: function(key, val) {
|
ss: function() {
|
||||||
return cacheStore('sessionStorage', key, val)
|
var args = aslice.call(arguments, 0)
|
||||||
|
args.unshift('sessionStorage')
|
||||||
|
return cacheStore.apply(this, args)
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* [cookie cookie 操作 ]
|
* [cookie cookie 操作 ]
|
||||||
|
|
|
@ -787,7 +787,7 @@ const _Anot = (function() {
|
||||||
switch (arguments.length) {
|
switch (arguments.length) {
|
||||||
case 2:
|
case 2:
|
||||||
return window[tpye].getItem(key)
|
return window[tpye].getItem(key)
|
||||||
default:
|
case 3:
|
||||||
if ((this.type(val) == 'string' && val.trim() === '') || val === null) {
|
if ((this.type(val) == 'string' && val.trim() === '') || val === null) {
|
||||||
window[tpye].removeItem(key)
|
window[tpye].removeItem(key)
|
||||||
return
|
return
|
||||||
|
@ -797,6 +797,7 @@ const _Anot = (function() {
|
||||||
} else {
|
} else {
|
||||||
window[tpye].setItem(key, JSON.stringify(val))
|
window[tpye].setItem(key, JSON.stringify(val))
|
||||||
}
|
}
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -946,11 +947,15 @@ const _Anot = (function() {
|
||||||
* @param {[type]} val [键值,为空时删除]
|
* @param {[type]} val [键值,为空时删除]
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
ls: function(key, val) {
|
ls: function() {
|
||||||
return cacheStore('localStorage', key, val)
|
var args = aslice.call(arguments, 0)
|
||||||
|
args.unshift('localStorage')
|
||||||
|
return cacheStore.apply(this, args)
|
||||||
},
|
},
|
||||||
ss: function(key, val) {
|
ss: function() {
|
||||||
return cacheStore('sessionStorage', key, val)
|
var args = aslice.call(arguments, 0)
|
||||||
|
args.unshift('sessionStorage')
|
||||||
|
return cacheStore.apply(this, args)
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* [cookie cookie 操作 ]
|
* [cookie cookie 操作 ]
|
||||||
|
|
|
@ -802,7 +802,7 @@
|
||||||
switch (arguments.length) {
|
switch (arguments.length) {
|
||||||
case 2:
|
case 2:
|
||||||
return window[tpye].getItem(key)
|
return window[tpye].getItem(key)
|
||||||
default:
|
case 3:
|
||||||
if ((this.type(val) == 'string' && val.trim() === '') || val === null) {
|
if ((this.type(val) == 'string' && val.trim() === '') || val === null) {
|
||||||
window[tpye].removeItem(key)
|
window[tpye].removeItem(key)
|
||||||
return
|
return
|
||||||
|
@ -812,6 +812,7 @@
|
||||||
} else {
|
} else {
|
||||||
window[tpye].setItem(key, JSON.stringify(val))
|
window[tpye].setItem(key, JSON.stringify(val))
|
||||||
}
|
}
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -961,11 +962,15 @@
|
||||||
* @param {[type]} val [键值,为空时删除]
|
* @param {[type]} val [键值,为空时删除]
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
ls: function(key, val) {
|
ls: function() {
|
||||||
return cacheStore('localStorage', key, val)
|
var args = aslice.call(arguments, 0)
|
||||||
|
args.unshift('localStorage')
|
||||||
|
return cacheStore.apply(this, args)
|
||||||
},
|
},
|
||||||
ss: function(key, val) {
|
ss: function() {
|
||||||
return cacheStore('sessionStorage', key, val)
|
var args = aslice.call(arguments, 0)
|
||||||
|
args.unshift('sessionStorage')
|
||||||
|
return cacheStore.apply(this, args)
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* [cookie cookie 操作 ]
|
* [cookie cookie 操作 ]
|
||||||
|
|
|
@ -9,38 +9,112 @@
|
||||||
//储存版本信息
|
//储存版本信息
|
||||||
Anot.ui.router = '0.0.1'
|
Anot.ui.router = '0.0.1'
|
||||||
|
|
||||||
function Router() {
|
//判定A标签的target属性是否指向自身
|
||||||
this.table = { get: [] }
|
//thanks https://github.com/quirkey/sammy/blob/master/lib/sammy.js#L219
|
||||||
this.errorFn = null
|
function targetIsThisWindow(targetWindow) {
|
||||||
this.history = null
|
if (
|
||||||
this.hash = ''
|
!targetWindow ||
|
||||||
this.started = false
|
targetWindow === window.name ||
|
||||||
this.init = {}
|
targetWindow === '_self' ||
|
||||||
|
(targetWindow === 'top' && window == window.top)
|
||||||
|
) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
var defaultOptions = {
|
const DEFAULT_OPTIONS = {
|
||||||
|
mode: 'hash', // hash | history
|
||||||
prefix: /^(#!|#)[\/]?/, //hash前缀正则
|
prefix: /^(#!|#)[\/]?/, //hash前缀正则
|
||||||
historyOpen: true, //是否开启hash历史
|
historyOpen: true, //是否开启hash历史
|
||||||
allowReload: true //连续点击同一个链接是否重新加载
|
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 = {
|
// 创建无new式Router实例
|
||||||
error: function(callback) {
|
static init(options = {}) {
|
||||||
this.errorFn = callback
|
if (Anot.router) {
|
||||||
},
|
throw new Error('不允许重复创建Router实例...')
|
||||||
config: function(opts) {
|
}
|
||||||
if (this.started) return console.error('Router config has been set')
|
if (!options.allowReload) {
|
||||||
|
options.historyOpen = true
|
||||||
|
}
|
||||||
|
|
||||||
this.started = true
|
Anot.router = new this(options)
|
||||||
if (!opts.allowReload) opts.historyOpen = true
|
return Anot.router
|
||||||
this.init = Anot.mix({}, defaultOptions, opts)
|
}
|
||||||
},
|
|
||||||
_getRegExp: function(rule, opts) {
|
__listen__() {
|
||||||
var re = rule.replace(ruleRegExp, function(m, p1, p2, p3, p4) {
|
let { mode, prefix } = this.options
|
||||||
var w = '([\\w.-]'
|
|
||||||
|
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) {
|
if (p1 || p2) {
|
||||||
return w + '+)'
|
return w + '+)'
|
||||||
} else {
|
} else {
|
||||||
|
@ -58,123 +132,74 @@ Router.prototype = {
|
||||||
re = '^' + re + '$'
|
re = '^' + re + '$'
|
||||||
opts.regexp = new RegExp(re)
|
opts.regexp = new RegExp(re)
|
||||||
return opts
|
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) !== '/') {
|
if (rule.charAt(0) !== '/') {
|
||||||
console.error('char "/" must be in front of router rule')
|
console.error('路由规则必须以"/"开头')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
rule = rule.replace(/^[\/]+|[\/]+$|\s+/g, '')
|
rule = rule.replace(/^[\/]+|[\/]+$|\s+/g, '')
|
||||||
var opts = {}
|
let opts = { rule, callback }
|
||||||
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
|
|
||||||
|
|
||||||
if (!init.allowReload && hash === this.history) return
|
Anot.Array.ensure(this.table, this._getRegExp(rule, opts))
|
||||||
|
}
|
||||||
|
|
||||||
if (init.historyOpen) {
|
__check__() {
|
||||||
this.history = hash
|
let { allowReload, historyOpen } = this.options
|
||||||
|
if (!allowReload && this.path === this.history) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (historyOpen) {
|
||||||
|
this.history = this.path
|
||||||
if (Anot.ls) {
|
if (Anot.ls) {
|
||||||
Anot.ls('lastHash', hash)
|
Anot.ls('lastPath', this.path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 0, obj; (obj = table[i++]); ) {
|
for (let i = 0, route; (route = this.table[i++]); ) {
|
||||||
var args = hash.match(obj.regexp)
|
let args = this.path.match(route.regexp)
|
||||||
if (args) {
|
if (args) {
|
||||||
args.shift()
|
args.shift()
|
||||||
return obj.callback.apply(obj, args)
|
return route.callback.apply(route, args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.errorFn && this.errorFn(hash)
|
this.notMatch && this.notMatch(this.path)
|
||||||
},
|
}
|
||||||
on: function(rule, callback) {
|
|
||||||
var _this = this
|
// 跳转到路由
|
||||||
|
go(path, forceCleanHash = false) {
|
||||||
|
let { mode, prefix } = this.options
|
||||||
|
|
||||||
|
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__()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 绑定路由事件
|
||||||
|
on(rule, callback) {
|
||||||
if (Array.isArray(rule)) {
|
if (Array.isArray(rule)) {
|
||||||
rule.forEach(function(it) {
|
rule.forEach(it => {
|
||||||
_this._add('get', it, callback)
|
this.__add__(it, callback)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
this._add('get', rule, callback)
|
this.__add__(rule, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Anot.bind(window, 'load', function() {
|
export default Router
|
||||||
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') {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (targetIsThisWindow(target.target)) {
|
|
||||||
if (!Anot.router.started) return
|
|
||||||
var href = target.getAttribute('href') || target.getAttribute('xlink:href'),
|
|
||||||
prefix = Anot.router.init.prefix
|
|
||||||
|
|
||||||
if (href === null || !prefix.test(href)) return
|
|
||||||
|
|
||||||
Anot.router.hash = href.replace(prefix, '').trim()
|
|
||||||
event.preventDefault()
|
|
||||||
location.hash = href
|
|
||||||
isMouseUp = false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
Anot.bind(document, 'mouseup', function() {
|
|
||||||
if (!isMouseUp) {
|
|
||||||
Anot.router._route('get', Anot.router.hash)
|
|
||||||
isMouseUp = true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
//判定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())
|
|
||||||
|
|
Reference in New Issue