支持keepAlive和transition;

master
yutent 2023-08-11 19:19:48 +08:00
parent 0c42d793fa
commit 248e153995
3 changed files with 75 additions and 22 deletions

View File

@ -71,9 +71,15 @@ export function createApp({
if ($router) { if ($router) {
App.prototype.mounted = function (...args) { App.prototype.mounted = function (...args) {
let $view = window.__wkitd__.get('ROUTER_VIEW') let $view = window.__wkitd__.get('ROUTER_VIEW')
if ($view) {
$view.sync($router.getViews()) $view.sync($router.getViews())
$router.init() $router.init()
mounted.call(this, ...args) mounted.call(this, ...args)
} else {
throw new Error(
`<router-view /> not found, "Router" works Unexpected.`
)
}
} }
} }
App.reg('app') App.reg('app')

View File

@ -18,16 +18,14 @@ const DEFAULT_OPTIONS = {
const RULE_REGEXP = const RULE_REGEXP =
/(:id)|(\{id\})|(\{id:([A-z\d\,\[\]\{\}\-\+\*\?\!:\^\$]*)\})/g /(:id)|(\{id\})|(\{id:([A-z\d\,\[\]\{\}\-\+\*\?\!:\^\$]*)\})/g
const __ready__ = Symbol('ready')
class Router { class Router {
[__ready__] = false
#tables = new Map() #tables = new Map()
#views = new Set() #views = new Set()
#options = Object.create(null) #targets = new Set()
#ready = false
#options = Object.create(null)
#route = Object.create(null) #route = Object.create(null)
constructor(options = {}) { constructor(options = {}) {
@ -42,10 +40,10 @@ class Router {
#hashchange(ev) { #hashchange(ev) {
if (ev?.type === 'load') { if (ev?.type === 'load') {
if (this[__ready__]) { if (this.#ready) {
return return
} }
this[__ready__] = true this.#ready = true
} }
let path = location.hash let path = location.hash
@ -89,12 +87,6 @@ class Router {
} }
#add(route) { #add(route) {
// 特殊值"!", 则自动作非匹配回调处理
// if (route.path === '!') {
// // this.noMatch = callback
// this.#views.add(route.name)
// return
// }
if (route.path !== '!' && route.path[0] !== '/') { if (route.path !== '!' && route.path[0] !== '/') {
console.error('路由规则必须以"/"开头') console.error('路由规则必须以"/"开头')
return return
@ -102,6 +94,7 @@ class Router {
route.path = route.path.replace(/^[\/]+|[\/]+$|\s+/g, '') route.path = route.path.replace(/^[\/]+|[\/]+$|\s+/g, '')
this.#tables.set(route.path, this.#parseRule(route)) this.#tables.set(route.path, this.#parseRule(route))
this.#views.add(route.name)
} }
// 路由检测 // 路由检测
@ -112,7 +105,6 @@ class Router {
if (!$view || (!allowReload && path === this.#route.path)) { if (!$view || (!allowReload && path === this.#route.path)) {
return return
} }
// console.log('<><><><>')
for (let [k, route] of this.#tables) { for (let [k, route] of this.#tables) {
let args = path.match(route.regexp) let args = path.match(route.regexp)
@ -123,16 +115,31 @@ class Router {
this.#route.name = route.name this.#route.name = route.name
this.#route.params = args this.#route.params = args
this.#route.query = {} this.#route.query = {}
break this.#rsync()
return
} }
} }
// this.noMatch && this.noMatch(this.path) if (this.#tables.get('!')) {
route = this.#tables.get('!')
$view.current = route.name
this.#route = { path, name: route.name, params: {}, query: {} }
}
}
#rsync() {
for (let callback of this.#targets) {
callback(this.route)
}
} }
init() { init() {
this.#hashchange() this.#hashchange()
} }
rsync(callback) {
this.#targets.add(callback)
}
getViews() { getViews() {
return Array.from(this.#views) return Array.from(this.#views)
} }
@ -166,7 +173,7 @@ class Router {
// 因为先初始化,才开始监听路由规则 // 因为先初始化,才开始监听路由规则
// 所以会导致wondow load的时候, 规则还没生效, 而生效之后,load已经结束 // 所以会导致wondow load的时候, 规则还没生效, 而生效之后,load已经结束
// 所以这里需要手动再触发一次load // 所以这里需要手动再触发一次load
if (this[__ready__]) { if (this.#ready) {
this.#hashchange() this.#hashchange()
} else { } else {
fire(window, 'load') fire(window, 'load')

View File

@ -14,7 +14,21 @@ export { createWebHashHistory, createWebHistory }
class Router extends Component { class Router extends Component {
static props = { static props = {
keepAlive: false, keepAlive: false,
current: 'str!' transition: false,
current: {
type: String,
default: '',
attribute: false,
observer(v, old) {
if (this.keepAlive && v) {
if (old && this.$refs[old]) {
this.$refs[old].deactivated()
}
this.$refs[v]?.$animate()
this.$refs[v]?.activated()
}
}
}
} }
#views = [] #views = []
@ -28,10 +42,36 @@ class Router extends Component {
} }
render() { render() {
let option = {
immediate: true,
custom: [
{ transform: 'translateX(-32px)', opacity: 0 },
{ transform: 'translateX(0)', opacity: 1 }
]
}
if (this.keepAlive) { if (this.keepAlive) {
return html`` let template = this.#views.map(it => [
this.transition
? `<${it} ref="${it}" :__keep_alive__="%s" #animation="%s" style="%s"></${it}>`
: `<${it} ref="${it}" :__keep_alive__="%s" style=%s></${it}>`,
[
this.current === it,
{ ...option, immediate: this.current === it },
this.current === it ? '' : 'display:none'
]
])
return raw(
template.map(it => it[0]).join(''),
template.map(it => it[1]).flat()
)
} else { } else {
if (this.current) { if (this.current) {
if (this.transition) {
return raw(`<${this.current} #animation="%s"></${this.current}>`, [
option
])
}
return raw(`<${this.current}></${this.current}>`) return raw(`<${this.current}></${this.current}>`)
} }
} }