initial version of stuff
This commit is contained in:
parent
e3eabd418e
commit
dbd10b859f
5 changed files with 137 additions and 0 deletions
8
src/components/Redirect.html
Normal file
8
src/components/Redirect.html
Normal file
|
@ -0,0 +1,8 @@
|
|||
<script>
|
||||
export default {
|
||||
oncreate() {
|
||||
let { r: { router }, to, push } = this.get()
|
||||
router.go(to, !push)
|
||||
},
|
||||
}
|
||||
</script>
|
40
src/components/Route.html
Normal file
40
src/components/Route.html
Normal file
|
@ -0,0 +1,40 @@
|
|||
<div ref:mount/>
|
||||
|
||||
<script>
|
||||
import matchPath from '../utils/matchPath.js'
|
||||
|
||||
export default {
|
||||
oncreate() {
|
||||
this.observe('r', update.bind(this))
|
||||
this.observe('path', update.bind(this))
|
||||
},
|
||||
}
|
||||
|
||||
function update() {
|
||||
let {
|
||||
r: { match, pathname, router },
|
||||
path,
|
||||
exact,
|
||||
component,
|
||||
} = this.get()
|
||||
let { _r } = this
|
||||
if (path) {
|
||||
let match = matchPath(pathname, { path, exact })
|
||||
if (match) {
|
||||
if (_r) {
|
||||
_r.set({ match, r: { match, pathname, router } })
|
||||
} else {
|
||||
_r = new component({ target: this.refs.mount, data: { match, r: { match, pathname, router } } })
|
||||
}
|
||||
} else if (_r) {
|
||||
_r.destroy()
|
||||
_r = null
|
||||
}
|
||||
} else if (_r) {
|
||||
_r.set({ match, r: { match, pathname, router } })
|
||||
} else {
|
||||
_r = new component({ target: this.refs.mount, data: { match, r: { match, pathname, router } } })
|
||||
}
|
||||
this._r = _r
|
||||
}
|
||||
</script>
|
51
src/components/Router.html
Normal file
51
src/components/Router.html
Normal file
|
@ -0,0 +1,51 @@
|
|||
<div ref:mount/>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
oncreate() {
|
||||
document.addEventListener('click', clickHandler.bind(this))
|
||||
window.addEventListener('popstate', popHandler.bind(this))
|
||||
this._r = new (this.get('component'))({ target: this.refs.mount, data: { r: { router: this, pathname: document.location.pathname } } })
|
||||
},
|
||||
methods: {
|
||||
go(url, replace) {
|
||||
history[replace ? 'replaceState' : 'pushState'](null, '', location.origin + url)
|
||||
if (this._r) {
|
||||
let r = this._r.get('r')
|
||||
r.pathname = url
|
||||
this._r.set({ r })
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
function clickHandler(event) {
|
||||
if (event.ctrlKey || event.metaKey || event.shiftKey || event.which !== 1) {
|
||||
return
|
||||
}
|
||||
let elm = event.target
|
||||
while (elm.nodeName !== 'A') {
|
||||
elm = elm.parentElement
|
||||
if (!elm) {
|
||||
return
|
||||
}
|
||||
}
|
||||
if (elm.target) {
|
||||
return
|
||||
}
|
||||
let url = elm.href
|
||||
if (!url.startsWith(document.location.origin + '/')) {
|
||||
return
|
||||
}
|
||||
event.preventDefault()
|
||||
this.go(url.slice(document.location.origin.length))
|
||||
}
|
||||
|
||||
function popHandler() {
|
||||
if (this._r) {
|
||||
let r = this._r.get('r')
|
||||
r.pathname = document.location.pathname
|
||||
this._r.set({ r })
|
||||
}
|
||||
}
|
||||
</script>
|
4
src/index.js
Normal file
4
src/index.js
Normal file
|
@ -0,0 +1,4 @@
|
|||
export { default as Redirect } from './components/Redirect.html'
|
||||
export { default as Route } from './components/Route.html'
|
||||
export { default as Router } from './components/Router.html'
|
||||
export { default as matchPath } from './utils/matchPath.js'
|
34
src/utils/matchPath.js
Normal file
34
src/utils/matchPath.js
Normal file
|
@ -0,0 +1,34 @@
|
|||
let cache = new Map()
|
||||
let escapeRe = /[\\^$.*+?()[\]{}|]/g
|
||||
let paramRe = /:\w+/
|
||||
|
||||
export default function matchPath(pathname, { path, exact }) {
|
||||
let key = path + !!exact
|
||||
let regex
|
||||
let names
|
||||
if (cache.has(key)) {
|
||||
({ regex, names } = cache.get(key))
|
||||
} else {
|
||||
let rest = path
|
||||
regex = '^'
|
||||
names = []
|
||||
let match
|
||||
while ((match = rest.match(paramRe))) {
|
||||
regex += rest.slice(0, match.index).replace(escapeRe, '\\$&') + '([^/]+)'
|
||||
names.push(match[0].slice(1))
|
||||
rest = rest.slice(match.index + match[0].length)
|
||||
}
|
||||
regex += rest.replace(escapeRe, '\\$&') + (exact ? '$' : '(?=\\/|$)')
|
||||
regex = new RegExp(regex)
|
||||
cache.set(key, { regex, names })
|
||||
}
|
||||
let match = pathname.match(regex)
|
||||
if (!match) {
|
||||
return null
|
||||
}
|
||||
let params = {}
|
||||
for (let i = 0; i < names.length; i++) {
|
||||
params[names[i]] = match[i + 1]
|
||||
}
|
||||
return { path, url: match[0], params }
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue