From 248e153995e85355ebf541ab06519568085a83ba Mon Sep 17 00:00:00 2001 From: yutent Date: Fri, 11 Aug 2023 19:19:48 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81keepAlive=E5=92=8Ctransition;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/index.js | 12 ++++++++--- src/router/hash-router.js | 41 +++++++++++++++++++++--------------- src/router/index.js | 44 +++++++++++++++++++++++++++++++++++++-- 3 files changed, 75 insertions(+), 22 deletions(-) diff --git a/src/index.js b/src/index.js index cae42dd..a325f3c 100644 --- a/src/index.js +++ b/src/index.js @@ -71,9 +71,15 @@ export function createApp({ if ($router) { App.prototype.mounted = function (...args) { let $view = window.__wkitd__.get('ROUTER_VIEW') - $view.sync($router.getViews()) - $router.init() - mounted.call(this, ...args) + if ($view) { + $view.sync($router.getViews()) + $router.init() + mounted.call(this, ...args) + } else { + throw new Error( + ` not found, "Router" works Unexpected.` + ) + } } } App.reg('app') diff --git a/src/router/hash-router.js b/src/router/hash-router.js index 40028b2..78312ab 100644 --- a/src/router/hash-router.js +++ b/src/router/hash-router.js @@ -18,16 +18,14 @@ const DEFAULT_OPTIONS = { const RULE_REGEXP = /(:id)|(\{id\})|(\{id:([A-z\d\,\[\]\{\}\-\+\*\?\!:\^\$]*)\})/g -const __ready__ = Symbol('ready') - class Router { - [__ready__] = false - #tables = new Map() #views = new Set() - #options = Object.create(null) + #targets = new Set() + #ready = false + #options = Object.create(null) #route = Object.create(null) constructor(options = {}) { @@ -42,10 +40,10 @@ class Router { #hashchange(ev) { if (ev?.type === 'load') { - if (this[__ready__]) { + if (this.#ready) { return } - this[__ready__] = true + this.#ready = true } let path = location.hash @@ -89,12 +87,6 @@ class Router { } #add(route) { - // 特殊值"!", 则自动作非匹配回调处理 - // if (route.path === '!') { - // // this.noMatch = callback - // this.#views.add(route.name) - // return - // } if (route.path !== '!' && route.path[0] !== '/') { console.error('路由规则必须以"/"开头') return @@ -102,6 +94,7 @@ class Router { route.path = route.path.replace(/^[\/]+|[\/]+$|\s+/g, '') 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)) { return } - // console.log('<><><><>') for (let [k, route] of this.#tables) { let args = path.match(route.regexp) @@ -123,16 +115,31 @@ class Router { this.#route.name = route.name this.#route.params = args 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() { this.#hashchange() } + rsync(callback) { + this.#targets.add(callback) + } + getViews() { return Array.from(this.#views) } @@ -166,7 +173,7 @@ class Router { // 因为先初始化,才开始监听路由规则 // 所以会导致wondow load的时候, 规则还没生效, 而生效之后,load已经结束 // 所以这里需要手动再触发一次load - if (this[__ready__]) { + if (this.#ready) { this.#hashchange() } else { fire(window, 'load') diff --git a/src/router/index.js b/src/router/index.js index ce9473c..66e0b56 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -14,7 +14,21 @@ export { createWebHashHistory, createWebHistory } class Router extends Component { static props = { 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 = [] @@ -28,10 +42,36 @@ class Router extends Component { } render() { + let option = { + immediate: true, + custom: [ + { transform: 'translateX(-32px)', opacity: 0 }, + { transform: 'translateX(0)', opacity: 1 } + ] + } if (this.keepAlive) { - return html`` + let template = this.#views.map(it => [ + this.transition + ? `<${it} ref="${it}" :__keep_alive__="%s" #animation="%s" style="%s">` + : `<${it} ref="${it}" :__keep_alive__="%s" style=%s>`, + [ + 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 { if (this.current) { + if (this.transition) { + return raw(`<${this.current} #animation="%s">`, [ + option + ]) + } return raw(`<${this.current}>`) } }