删除多余文件;修复hash路由默认值;优化router-link样式
parent
8519bfd4ef
commit
285e64bbed
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "wkitd",
|
||||
"version": "1.1.0",
|
||||
"version": "1.1.1",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"files": [
|
||||
|
|
|
@ -16,6 +16,7 @@ class App extends Component {}
|
|||
|
||||
export function createApp({
|
||||
data = {},
|
||||
styles = [],
|
||||
methods = {},
|
||||
mounted = noop,
|
||||
render
|
||||
|
@ -24,6 +25,7 @@ export function createApp({
|
|||
|
||||
return new (function () {
|
||||
App.props = data
|
||||
App.styles = styles
|
||||
Object.assign(App.prototype, methods, { mounted })
|
||||
|
||||
this.use = function (plugin = noop, ...args) {
|
||||
|
|
|
@ -1,219 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* @authors yutent (yutent@doui.cc)
|
||||
* @date 2017-04-14 21:04:50
|
||||
*
|
||||
*/
|
||||
import { bind, fire } from 'wkit'
|
||||
import {
|
||||
noop,
|
||||
targetIsThisWindow,
|
||||
query2object,
|
||||
object2query
|
||||
} from '../utils.js'
|
||||
|
||||
//hash前缀正则
|
||||
const PREFIX_REGEXP = /^(#!|#)[\/]+?/
|
||||
const RULE_REGEXP = /(\/[^/]*)(:[A-Za-z0-9_]+)(\?)?/g
|
||||
|
||||
class Router {
|
||||
type = 'history'
|
||||
|
||||
#tables = new Map()
|
||||
#views = new Set()
|
||||
|
||||
#targets = new Map()
|
||||
|
||||
#ready = false
|
||||
#route = Object.create(null)
|
||||
|
||||
#beforeEach
|
||||
|
||||
constructor() {
|
||||
// bind(window, 'popstate', this.#hashchange.bind(this))
|
||||
}
|
||||
|
||||
// 事件监听
|
||||
__listen__() {
|
||||
let { mode } = this.options
|
||||
|
||||
bind(window, 'load, popstate', ev => {
|
||||
if (ev.type === 'load') {
|
||||
if (this.ready) {
|
||||
return
|
||||
}
|
||||
this.ready = true
|
||||
}
|
||||
|
||||
let path = mode === 'hash' ? location.hash : location.pathname
|
||||
|
||||
path = path.replace(PREFIX_REGEXP, '').trim()
|
||||
path = path.replace(TRIM_REGEXP, '')
|
||||
|
||||
if (ev.type === 'load') {
|
||||
this.go(path)
|
||||
// hash模式要手动触发一下路由检测
|
||||
if (mode === 'hash') {
|
||||
this.__check__(path)
|
||||
}
|
||||
} else {
|
||||
// 因为pushState不会触发popstate事件,
|
||||
// 所以这里只在hash模式或有ev.state的情况下才会主动触发路由检测
|
||||
if (mode === 'hash' || ev.state) {
|
||||
this.__check__(path)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
//劫持页面上所有点击事件,如果事件源来自链接或其内部,
|
||||
//并且它不会跳出本页,并且以"#/"或"#!/"开头,那么触发go方法
|
||||
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')
|
||||
|
||||
if (
|
||||
!href ||
|
||||
/^(http[s]?:|ftp:)?\/\//.test(href) ||
|
||||
/^javascript:/.test(href)
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
// hash地址,只管修正前缀即可, 会触发popstate事件,所以这里只处理非hash的情况
|
||||
if (!PREFIX_REGEXP.test(href)) {
|
||||
// 非hash地址,则需要阻止默认事件
|
||||
// 并主动触发跳转, 同时强制清除hash
|
||||
ev.preventDefault()
|
||||
this.go(href, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
__parseRule__(rule, opts) {
|
||||
let re = rule.replace(RULE_REGEXP, function (m, p1, p2, p3, p4) {
|
||||
let w = '([\\w.-]'
|
||||
if (p1 || p2) {
|
||||
return w + '+)'
|
||||
} else {
|
||||
if (!/^\{[\d\,]+\}$/.test(p4)) {
|
||||
w = '('
|
||||
}
|
||||
return w + p4 + ')'
|
||||
}
|
||||
})
|
||||
re = re
|
||||
.replace(/(([^\\])([\/]+))/g, '$2\\/')
|
||||
.replace(/(([^\\])([\.]+))/g, '$2\\.')
|
||||
.replace(/(([^\\])([\-]+))/g, '$2\\-')
|
||||
.replace(/(\(.*)(\\[\-]+)(.*\))/g, '$1-$3')
|
||||
re = '^' + re + '$'
|
||||
opts.regexp = new RegExp(re)
|
||||
return opts
|
||||
}
|
||||
|
||||
__add__(rule, callback) {
|
||||
// 特殊值"!", 则自动作非匹配回调处理
|
||||
if (rule === '!') {
|
||||
this.noMatch = callback
|
||||
return
|
||||
}
|
||||
if (rule.charAt(0) !== '/') {
|
||||
console.error('路由规则必须以"/"开头')
|
||||
return
|
||||
}
|
||||
rule = rule.replace(/^[\/]+|[\/]+$|\s+/g, '')
|
||||
let opts = { rule, callback }
|
||||
|
||||
Anot.Array.ensure(this.table, this.__parseRule__(rule, opts))
|
||||
}
|
||||
|
||||
// 路由检测
|
||||
__check__(path) {
|
||||
let { allowReload } = this.options
|
||||
if (!allowReload && path === this.last) {
|
||||
return
|
||||
}
|
||||
|
||||
this.last = this.path
|
||||
this.path = path
|
||||
this.pathArr = path.split('/')
|
||||
LINKS.forEach(vm => {
|
||||
if (vm.rule.test(this.path)) {
|
||||
vm.active = true
|
||||
} else {
|
||||
vm.active = false
|
||||
}
|
||||
})
|
||||
for (let i = 0, route; (route = this.table[i++]); ) {
|
||||
let args = path.match(route.regexp)
|
||||
if (args) {
|
||||
args.shift()
|
||||
return route.callback.apply(route, args)
|
||||
}
|
||||
}
|
||||
this.noMatch && this.noMatch(this.path)
|
||||
}
|
||||
|
||||
// 跳转到路由
|
||||
go2(path, forceCleanHash = false) {
|
||||
path = path.trim().replace(TRIM_REGEXP, '')
|
||||
let { mode } = this.options
|
||||
|
||||
if (mode === 'hash') {
|
||||
// 页面刷新时, 不主动添加空hash, 避免执行2次noMatch回调
|
||||
if (!path && path === location.hash) {
|
||||
return
|
||||
}
|
||||
location.hash = '!/' + path
|
||||
} else {
|
||||
let hash = forceCleanHash ? '' : location.hash
|
||||
let search = forceCleanHash ? '' : location.search
|
||||
if (forceCleanHash) {
|
||||
window.history.pushState({ path }, null, `/${path + search + hash}`)
|
||||
} else {
|
||||
window.history.replaceState({ path }, null, `/${path + search + hash}`)
|
||||
}
|
||||
// pushState不会触发popstate事件,所以要手动触发路由检测
|
||||
this.__check__(path)
|
||||
}
|
||||
}
|
||||
|
||||
// 绑定路由事件
|
||||
addRoute(routes) {
|
||||
// if (Array.isArray(routes)) {
|
||||
// routes.forEach(it => {
|
||||
// this.#add(it)
|
||||
// })
|
||||
// } else {
|
||||
// this.#add(routes)
|
||||
// }
|
||||
// // 初始化后再添加路由, 手动执行一次回调
|
||||
// if (this.#ready) {
|
||||
// this.#hashchange()
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
export default function () {
|
||||
return () => new Router()
|
||||
}
|
|
@ -24,6 +24,12 @@ class RouterView extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
`
|
||||
|
||||
#views = []
|
||||
|
||||
created() {
|
||||
|
@ -80,10 +86,15 @@ class RouterLink extends Component {
|
|||
static styles = css`
|
||||
:host {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: inherit;
|
||||
text-decoration: inherit;
|
||||
cursor: pointer;
|
||||
|
|
|
@ -97,9 +97,9 @@ class Router {
|
|||
#check() {
|
||||
let isHash = this.type === MODE_HASH
|
||||
let $view = window.wkitd.get(__ROUTER_VIEW__)
|
||||
let hash = location.hash
|
||||
let hash = location.hash || '#/'
|
||||
let path = isHash
|
||||
? location.hash
|
||||
? hash
|
||||
: location.href.replace(location.origin, '').replace(hash, '')
|
||||
let query
|
||||
|
||||
|
|
Loading…
Reference in New Issue