@lytjs/router 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -0
- package/dist/index.mjs +1 -0
- package/dist/types/create-router.d.ts +112 -0
- package/dist/types/create-router.d.ts.map +1 -0
- package/dist/types/guards.d.ts +107 -0
- package/dist/types/guards.d.ts.map +1 -0
- package/dist/types/history.d.ts +98 -0
- package/dist/types/history.d.ts.map +1 -0
- package/dist/types/index.d.ts +15 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/matcher.d.ts +80 -0
- package/dist/types/matcher.d.ts.map +1 -0
- package/package.json +42 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var E=Object.defineProperty;var k=Object.getOwnPropertyDescriptor;var S=Object.getOwnPropertyNames;var U=Object.prototype.hasOwnProperty;var z=(e,t)=>{for(var r in t)E(e,r,{get:t[r],enumerable:!0})},K=(e,t,r,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of S(t))!U.call(e,s)&&s!==r&&E(e,s,{get:()=>t[s],enumerable:!(a=k(t,s))||a.enumerable});return e};var $=e=>K(E({},"__esModule",{value:!0}),e);var B={};z(B,{createHashHistory:()=>w,createNavigationGuards:()=>x,createRouteMatcher:()=>y,createRouter:()=>O,createWebHistory:()=>m,runAfterGuards:()=>N,runGuards:()=>v});module.exports=$(B);function A(e){let t=[],r=!1,a=e.split("/"),s=[];for(let c=0;c<a.length;c++){let n=a[c];if(n!=="")if(n==="*")s.push("(.+)"),t.push("*"),r=!0;else if(n.startsWith(":")){let i=n.slice(1);s.push("([^/]+)"),t.push(i)}else s.push(D(n))}let u="^/"+s.join("/")+"$";return{regex:new RegExp(u),paramKeys:t,isWildcard:r}}function D(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function T(e,t=""){let r=H(t,e.path),{regex:a,paramKeys:s,isWildcard:u}=A(r);if(e._regex=a,e._paramKeys=s,e._isWildcard=u,e.children)for(let c of e.children)T(c,r)}function H(e,t){let r=e.replace(/\/+$/,""),a=t.replace(/^\/+/,"");return a?r+"/"+a:r||"/"}function y(e){let t=[];function r(n,i=""){for(let o of n)if(T(o,i),t.push(o),o.children){let d=H(i,o.path);r(o.children,d)}}r(e);function a(n){let i=n.replace(/\/+$/,"")||"/";for(let o of t){if(!o._regex)continue;let d=i.match(o._regex);if(d){let g={};if(o._paramKeys)for(let f=0;f<o._paramKeys.length;f++){let p=o._paramKeys[f];g[p]=d[f+1]||""}return{record:o,params:g,matchedPath:i}}}return null}function s(n){if(T(n),t.push(n),n.children){let i=H("",n.path);r(n.children,i)}}function u(n){for(let i=t.length-1;i>=0;i--)t[i].name===n&&t.splice(i,1)}function c(){return[...t]}return{matchRoute:a,addRoute:s,removeRoute:u,getRoutes:c}}function j(e){let t={};if(!e||e==="?")return t;let a=(e.startsWith("?")?e.slice(1):e).split("&");for(let s of a){let u=s.indexOf("=");if(u===-1)t[decodeURIComponent(s)]="";else{let c=decodeURIComponent(s.slice(0,u)),n=decodeURIComponent(s.slice(u+1));t[c]=n}}return t}function q(e){let t=[];for(let r of Object.keys(e)){let a=e[r];a!=null&&t.push(encodeURIComponent(r)+"="+encodeURIComponent(a))}return t.join("&")}function I(e){let t="",r=e,a=e.indexOf("#");a!==-1&&(t=e.slice(a+1),r=e.slice(0,a));let s=r,u={},c=r.indexOf("?");return c!==-1&&(s=r.slice(0,c),u=j(r.slice(c))),{path:s,query:u,hash:t}}function h(e){return e.startsWith("/")||(e="/"+e),e.replace(/\/+/g,"/")}function m(e="/"){let t=h(e),r=[],a=u(window.location.href);function s(n){let i=u(window.location.href);i.fromPopState=!0,i.state=n.state;let o=a;a=i,c(i,o)}function u(n){let i;try{i=new URL(n)}catch(p){i=new URL(n,window.location.origin)}let o=i.pathname;t!=="/"&&o.startsWith(t)&&(o=o.slice(t.length)||"/");let{path:d,query:g,hash:f}=I(o+i.hash);return{path:h(d),fullPath:h(d)+(Object.keys(g).length?"?"+q(g):"")+(f?"#"+f:""),query:g,hash:f,state:i.state||null,fromPopState:!1}}function c(n,i){for(let o of r)o(n,i)}return window.addEventListener("popstate",s),{base:t,get location(){return a},push(n,i){let o=h(n),d=a;window.history.pushState(i||null,"",t+o),a=u(window.location.href),a.state=i||null,c(a,d)},replace(n,i){let o=h(n),d=a;window.history.replaceState(i||null,"",t+o),a=u(window.location.href),a.state=i||null,c(a,d)},go(n){window.history.go(n)},back(){window.history.back()},forward(){window.history.forward()},getCurrentRoute(){return u(window.location.href)},listen(n){return r.push(n),()=>{let i=r.indexOf(n);i!==-1&&r.splice(i,1)}},destroy(){window.removeEventListener("popstate",s),r.length=0}}}function w(){let e=[],t=a();function r(){let u=a();u.fromPopState=!0;let c=t;t=u,s(u,c)}function a(){let c=window.location.hash.slice(1)||"/",{path:n,query:i,hash:o}=I(c);return{path:h(n),fullPath:h(n)+(Object.keys(i).length?"?"+q(i):"")+(o?"#"+o:""),query:i,hash:o,state:null,fromPopState:!1}}function s(u,c){for(let n of e)n(u,c)}return window.addEventListener("hashchange",r),{base:"",get location(){return t},push(u,c){let n=h(u),i=t;window.location.hash=n,t=a(),s(t,i)},replace(u,c){let n=h(u),i=t;window.location.replace(window.location.pathname+window.location.search+"#"+n),t=a(),s(t,i)},go(u){window.history.go(u)},back(){window.history.back()},forward(){window.history.forward()},getCurrentRoute(){return a()},listen(u){return e.push(u),()=>{let c=e.indexOf(u);c!==-1&&e.splice(c,1)}},destroy(){window.removeEventListener("hashchange",r),e.length=0}}}function x(){let e=[],t=[],r=[];function a(c){return e.push(c),()=>{let n=e.indexOf(c);n!==-1&&e.splice(n,1)}}function s(c){return t.push(c),()=>{let n=t.indexOf(c);n!==-1&&t.splice(n,1)}}function u(c){return r.push(c),()=>{let n=r.indexOf(c);n!==-1&&r.splice(n,1)}}return{_beforeEachGuards:e,_beforeResolveGuards:t,_afterEachGuards:r,beforeEach:a,beforeResolve:s,afterEach:u}}function v(e,t,r){return new Promise((a,s)=>{let u=0;function c(){let i=!1;return o=>{if(i){console.warn("next() \u88AB\u591A\u6B21\u8C03\u7528\u3002\u8BF7\u786E\u4FDD\u6BCF\u4E2A\u5B88\u536B\u53EA\u8C03\u7528\u4E00\u6B21 next()\u3002");return}i=!0,o===!1?s(new Error("\u5BFC\u822A\u88AB\u5B88\u536B\u4E2D\u6B62")):typeof o=="string"?s(new Error("REDIRECT:"+o)):(u++,n())}}function n(){if(u>=e.length){a();return}let i=e[u],o=c();try{let d=i(t,r,o);d!=null&&typeof d=="object"&&typeof d.then=="function"&&d.then(()=>{}).catch(g=>{!g||typeof g.message!="string"||!g.message.startsWith("REDIRECT:")?s(new Error("\u5BFC\u822A\u88AB\u5B88\u536B\u4E2D\u6B62")):s(g)})}catch(d){s(new Error("\u5BFC\u822A\u5B88\u536B\u6267\u884C\u51FA\u9519"))}}n()})}function N(e,t,r){for(let a of e)try{a(t,r)}catch(s){console.warn("\u540E\u7F6E\u5B88\u536B\u6267\u884C\u51FA\u9519:",s)}}var b=require("@lytjs/reactivity");function Q(e,t){return{path:e.path,fullPath:e.fullPath,params:(t==null?void 0:t.params)||{},name:t==null?void 0:t.record.name,meta:(t==null?void 0:t.record.meta)||{},query:e.query,hash:e.hash}}function C(e,t){return(0,b.reactive)({path:e.path,fullPath:e.fullPath,params:(t==null?void 0:t.params)||{},name:t==null?void 0:t.record.name,meta:(t==null?void 0:t.record.meta)||{},query:e.query,hash:e.hash,matched:t?[t.record]:[]})}function O(e){let t=y(e.routes),r=e.mode==="hash"?w():m(e.base||"/"),a=x(),s=(0,b.ref)(C(r.location,t.matchRoute(r.location.path))),u=!1,c=r.listen(async(o,d)=>{await n(o.path,d,!0)});async function n(o,d,g=!1){var f,p;if(!u){u=!0;try{let _=t.matchRoute(o),M={path:o,fullPath:o,query:{},hash:"",state:null,fromPopState:g},L=Q(M,_),R=s.value,G={path:R.path,fullPath:R.fullPath,params:R.params,name:R.name,meta:R.meta,query:R.query,hash:R.hash};try{await v(a._beforeEachGuards,L,G)}catch(l){if((f=l==null?void 0:l.message)!=null&&f.startsWith("REDIRECT:")){let P=l.message.replace("REDIRECT:","");g||r.replace(P);return}return}try{await v(a._beforeResolveGuards,L,G)}catch(l){if((p=l==null?void 0:l.message)!=null&&p.startsWith("REDIRECT:")){let P=l.message.replace("REDIRECT:","");g||r.replace(P);return}return}let W=C(M,_);s.value=W,N(a._afterEachGuards,L,G)}finally{u=!1}}}let i={currentRoute:s,async push(o){r.push(o)},async replace(o){r.replace(o)},go(o){r.go(o)},back(){r.back()},forward(){r.forward()},beforeEach(o){return a.beforeEach(o)},afterEach(o){return a.afterEach(o)},beforeResolve(o){return a.beforeResolve(o)},addRoute(o){t.addRoute(o)},removeRoute(o){t.removeRoute(o)},getRoutes(){return t.getRoutes()},install(o){o.config&&o.config.globalProperties&&(o.config.globalProperties.$router=i,Object.defineProperty(o.config.globalProperties,"$route",{get(){return s.value}})),o.provide&&(o.provide("router",i),o.provide("route",s));let d=t.matchRoute(r.location.path);s.value=C(r.location,d)},destroy(){c(),r.destroy()}};return i}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function I(e){let t=[],n=!1,i=e.split("/"),c=[];for(let u=0;u<i.length;u++){let r=i[u];if(r!=="")if(r==="*")c.push("(.+)"),t.push("*"),n=!0;else if(r.startsWith(":")){let a=r.slice(1);c.push("([^/]+)"),t.push(a)}else c.push(O(r))}let s="^/"+c.join("/")+"$";return{regex:new RegExp(s),paramKeys:t,isWildcard:n}}function O(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function x(e,t=""){let n=N(t,e.path),{regex:i,paramKeys:c,isWildcard:s}=I(n);if(e._regex=i,e._paramKeys=c,e._isWildcard=s,e.children)for(let u of e.children)x(u,n)}function N(e,t){let n=e.replace(/\/+$/,""),i=t.replace(/^\/+/,"");return i?n+"/"+i:n||"/"}function b(e){let t=[];function n(r,a=""){for(let o of r)if(x(o,a),t.push(o),o.children){let d=N(a,o.path);n(o.children,d)}}n(e);function i(r){let a=r.replace(/\/+$/,"")||"/";for(let o of t){if(!o._regex)continue;let d=a.match(o._regex);if(d){let g={};if(o._paramKeys)for(let f=0;f<o._paramKeys.length;f++){let p=o._paramKeys[f];g[p]=d[f+1]||""}return{record:o,params:g,matchedPath:a}}}return null}function c(r){if(x(r),t.push(r),r.children){let a=N("",r.path);n(r.children,a)}}function s(r){for(let a=t.length-1;a>=0;a--)t[a].name===r&&t.splice(a,1)}function u(){return[...t]}return{matchRoute:i,addRoute:c,removeRoute:s,getRoutes:u}}function W(e){let t={};if(!e||e==="?")return t;let i=(e.startsWith("?")?e.slice(1):e).split("&");for(let c of i){let s=c.indexOf("=");if(s===-1)t[decodeURIComponent(c)]="";else{let u=decodeURIComponent(c.slice(0,s)),r=decodeURIComponent(c.slice(s+1));t[u]=r}}return t}function _(e){let t=[];for(let n of Object.keys(e)){let i=e[n];i!=null&&t.push(encodeURIComponent(n)+"="+encodeURIComponent(i))}return t.join("&")}function M(e){let t="",n=e,i=e.indexOf("#");i!==-1&&(t=e.slice(i+1),n=e.slice(0,i));let c=n,s={},u=n.indexOf("?");return u!==-1&&(c=n.slice(0,u),s=W(n.slice(u))),{path:c,query:s,hash:t}}function h(e){return e.startsWith("/")||(e="/"+e),e.replace(/\/+/g,"/")}function L(e="/"){let t=h(e),n=[],i=s(window.location.href);function c(r){let a=s(window.location.href);a.fromPopState=!0,a.state=r.state;let o=i;i=a,u(a,o)}function s(r){let a;try{a=new URL(r)}catch(p){a=new URL(r,window.location.origin)}let o=a.pathname;t!=="/"&&o.startsWith(t)&&(o=o.slice(t.length)||"/");let{path:d,query:g,hash:f}=M(o+a.hash);return{path:h(d),fullPath:h(d)+(Object.keys(g).length?"?"+_(g):"")+(f?"#"+f:""),query:g,hash:f,state:a.state||null,fromPopState:!1}}function u(r,a){for(let o of n)o(r,a)}return window.addEventListener("popstate",c),{base:t,get location(){return i},push(r,a){let o=h(r),d=i;window.history.pushState(a||null,"",t+o),i=s(window.location.href),i.state=a||null,u(i,d)},replace(r,a){let o=h(r),d=i;window.history.replaceState(a||null,"",t+o),i=s(window.location.href),i.state=a||null,u(i,d)},go(r){window.history.go(r)},back(){window.history.back()},forward(){window.history.forward()},getCurrentRoute(){return s(window.location.href)},listen(r){return n.push(r),()=>{let a=n.indexOf(r);a!==-1&&n.splice(a,1)}},destroy(){window.removeEventListener("popstate",c),n.length=0}}}function G(){let e=[],t=i();function n(){let s=i();s.fromPopState=!0;let u=t;t=s,c(s,u)}function i(){let u=window.location.hash.slice(1)||"/",{path:r,query:a,hash:o}=M(u);return{path:h(r),fullPath:h(r)+(Object.keys(a).length?"?"+_(a):"")+(o?"#"+o:""),query:a,hash:o,state:null,fromPopState:!1}}function c(s,u){for(let r of e)r(s,u)}return window.addEventListener("hashchange",n),{base:"",get location(){return t},push(s,u){let r=h(s),a=t;window.location.hash=r,t=i(),c(t,a)},replace(s,u){let r=h(s),a=t;window.location.replace(window.location.pathname+window.location.search+"#"+r),t=i(),c(t,a)},go(s){window.history.go(s)},back(){window.history.back()},forward(){window.history.forward()},getCurrentRoute(){return i()},listen(s){return e.push(s),()=>{let u=e.indexOf(s);u!==-1&&e.splice(u,1)}},destroy(){window.removeEventListener("hashchange",n),e.length=0}}}function P(){let e=[],t=[],n=[];function i(u){return e.push(u),()=>{let r=e.indexOf(u);r!==-1&&e.splice(r,1)}}function c(u){return t.push(u),()=>{let r=t.indexOf(u);r!==-1&&t.splice(r,1)}}function s(u){return n.push(u),()=>{let r=n.indexOf(u);r!==-1&&n.splice(r,1)}}return{_beforeEachGuards:e,_beforeResolveGuards:t,_afterEachGuards:n,beforeEach:i,beforeResolve:c,afterEach:s}}function v(e,t,n){return new Promise((i,c)=>{let s=0;function u(){let a=!1;return o=>{if(a){console.warn("next() \u88AB\u591A\u6B21\u8C03\u7528\u3002\u8BF7\u786E\u4FDD\u6BCF\u4E2A\u5B88\u536B\u53EA\u8C03\u7528\u4E00\u6B21 next()\u3002");return}a=!0,o===!1?c(new Error("\u5BFC\u822A\u88AB\u5B88\u536B\u4E2D\u6B62")):typeof o=="string"?c(new Error("REDIRECT:"+o)):(s++,r())}}function r(){if(s>=e.length){i();return}let a=e[s],o=u();try{let d=a(t,n,o);d!=null&&typeof d=="object"&&typeof d.then=="function"&&d.then(()=>{}).catch(g=>{!g||typeof g.message!="string"||!g.message.startsWith("REDIRECT:")?c(new Error("\u5BFC\u822A\u88AB\u5B88\u536B\u4E2D\u6B62")):c(g)})}catch(d){c(new Error("\u5BFC\u822A\u5B88\u536B\u6267\u884C\u51FA\u9519"))}}r()})}function E(e,t,n){for(let i of e)try{i(t,n)}catch(c){console.warn("\u540E\u7F6E\u5B88\u536B\u6267\u884C\u51FA\u9519:",c)}}import{ref as k,reactive as S}from"@lytjs/reactivity";function U(e,t){return{path:e.path,fullPath:e.fullPath,params:(t==null?void 0:t.params)||{},name:t==null?void 0:t.record.name,meta:(t==null?void 0:t.record.meta)||{},query:e.query,hash:e.hash}}function T(e,t){return S({path:e.path,fullPath:e.fullPath,params:(t==null?void 0:t.params)||{},name:t==null?void 0:t.record.name,meta:(t==null?void 0:t.record.meta)||{},query:e.query,hash:e.hash,matched:t?[t.record]:[]})}function z(e){let t=b(e.routes),n=e.mode==="hash"?G():L(e.base||"/"),i=P(),c=k(T(n.location,t.matchRoute(n.location.path))),s=!1,u=n.listen(async(o,d)=>{await r(o.path,d,!0)});async function r(o,d,g=!1){var f,p;if(!s){s=!0;try{let H=t.matchRoute(o),C={path:o,fullPath:o,query:{},hash:"",state:null,fromPopState:g},y=U(C,H),R=c.value,m={path:R.path,fullPath:R.fullPath,params:R.params,name:R.name,meta:R.meta,query:R.query,hash:R.hash};try{await v(i._beforeEachGuards,y,m)}catch(l){if((f=l==null?void 0:l.message)!=null&&f.startsWith("REDIRECT:")){let w=l.message.replace("REDIRECT:","");g||n.replace(w);return}return}try{await v(i._beforeResolveGuards,y,m)}catch(l){if((p=l==null?void 0:l.message)!=null&&p.startsWith("REDIRECT:")){let w=l.message.replace("REDIRECT:","");g||n.replace(w);return}return}let q=T(C,H);c.value=q,E(i._afterEachGuards,y,m)}finally{s=!1}}}let a={currentRoute:c,async push(o){n.push(o)},async replace(o){n.replace(o)},go(o){n.go(o)},back(){n.back()},forward(){n.forward()},beforeEach(o){return i.beforeEach(o)},afterEach(o){return i.afterEach(o)},beforeResolve(o){return i.beforeResolve(o)},addRoute(o){t.addRoute(o)},removeRoute(o){t.removeRoute(o)},getRoutes(){return t.getRoutes()},install(o){o.config&&o.config.globalProperties&&(o.config.globalProperties.$router=a,Object.defineProperty(o.config.globalProperties,"$route",{get(){return c.value}})),o.provide&&(o.provide("router",a),o.provide("route",c));let d=t.matchRoute(n.location.path);c.value=T(n.location,d)},destroy(){u(),n.destroy()}};return a}export{G as createHashHistory,P as createNavigationGuards,b as createRouteMatcher,z as createRouter,L as createWebHistory,E as runAfterGuards,v as runGuards};
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lyt.js 路由系统 — 路由创建(createRouter)
|
|
3
|
+
*
|
|
4
|
+
* 整合路由匹配器、History 管理和导航守卫,提供完整的路由实例。
|
|
5
|
+
*
|
|
6
|
+
* 核心功能:
|
|
7
|
+
* - 创建路由实例(支持 history 和 hash 两种模式)
|
|
8
|
+
* - 导航方法:push / replace / go / back / forward
|
|
9
|
+
* - 导航守卫:beforeEach / afterEach / beforeResolve
|
|
10
|
+
* - 响应式当前路由(currentRoute,基于 @lytjs/reactivity)
|
|
11
|
+
* - 插件安装(install 方法,供 app.use 调用)
|
|
12
|
+
*
|
|
13
|
+
* 集成 @lytjs/reactivity 实现响应式路由。
|
|
14
|
+
*/
|
|
15
|
+
import { type RouteRecord } from './matcher';
|
|
16
|
+
import { type NavigationGuard } from './guards';
|
|
17
|
+
import { type Ref } from '@lytjs/reactivity';
|
|
18
|
+
/** 路由模式 */
|
|
19
|
+
export type RouterMode = 'history' | 'hash';
|
|
20
|
+
/** 路由创建选项 */
|
|
21
|
+
export interface RouterOptions {
|
|
22
|
+
/** 路由模式:history(HTML5 History)或 hash */
|
|
23
|
+
mode: RouterMode;
|
|
24
|
+
/** 路由配置数组 */
|
|
25
|
+
routes: RouteRecord[];
|
|
26
|
+
/** 基础路径(仅 history 模式有效,默认 '/') */
|
|
27
|
+
base?: string;
|
|
28
|
+
}
|
|
29
|
+
/** 路由信息(对外暴露) */
|
|
30
|
+
export interface Route {
|
|
31
|
+
/** 路由路径 */
|
|
32
|
+
path: string;
|
|
33
|
+
/** 完整路径 */
|
|
34
|
+
fullPath: string;
|
|
35
|
+
/** 路由参数 */
|
|
36
|
+
params: Record<string, string>;
|
|
37
|
+
/** 路由名称 */
|
|
38
|
+
name?: string;
|
|
39
|
+
/** 路由元信息 */
|
|
40
|
+
meta?: Record<string, any>;
|
|
41
|
+
/** 查询参数 */
|
|
42
|
+
query: Record<string, string>;
|
|
43
|
+
/** hash 值 */
|
|
44
|
+
hash: string;
|
|
45
|
+
/** 匹配到的路由记录 */
|
|
46
|
+
matched: RouteRecord[];
|
|
47
|
+
}
|
|
48
|
+
/** 路由实例 */
|
|
49
|
+
export interface Router {
|
|
50
|
+
/** 当前路由信息(响应式 Ref) */
|
|
51
|
+
currentRoute: Ref<Route>;
|
|
52
|
+
/** 导航到新路径 */
|
|
53
|
+
push(path: string): Promise<void>;
|
|
54
|
+
/** 替换当前路径 */
|
|
55
|
+
replace(path: string): Promise<void>;
|
|
56
|
+
/** 前进/后退 n 步 */
|
|
57
|
+
go(n: number): void;
|
|
58
|
+
/** 后退一步 */
|
|
59
|
+
back(): void;
|
|
60
|
+
/** 前进一步 */
|
|
61
|
+
forward(): void;
|
|
62
|
+
/** 注册全局前置守卫 */
|
|
63
|
+
beforeEach(guard: NavigationGuard): () => void;
|
|
64
|
+
/** 注册全局后置守卫 */
|
|
65
|
+
afterEach(guard: (to: Route, from: Route) => void): () => void;
|
|
66
|
+
/** 注册全局解析守卫 */
|
|
67
|
+
beforeResolve(guard: NavigationGuard): () => void;
|
|
68
|
+
/** 动态添加路由 */
|
|
69
|
+
addRoute(route: RouteRecord): void;
|
|
70
|
+
/** 按名称移除路由 */
|
|
71
|
+
removeRoute(name: string): void;
|
|
72
|
+
/** 获取所有路由记录 */
|
|
73
|
+
getRoutes(): RouteRecord[];
|
|
74
|
+
/** 插件安装方法(供 app.use 调用) */
|
|
75
|
+
install(app: any): void;
|
|
76
|
+
/** 销毁路由实例 */
|
|
77
|
+
destroy(): void;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* 创建路由实例
|
|
81
|
+
*
|
|
82
|
+
* 整合匹配器、History 和守卫,提供完整的路由功能。
|
|
83
|
+
*
|
|
84
|
+
* @param options - 路由配置选项
|
|
85
|
+
* @returns 路由实例
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```ts
|
|
89
|
+
* const router = createRouter({
|
|
90
|
+
* mode: 'history',
|
|
91
|
+
* routes: [
|
|
92
|
+
* { path: '/', name: 'home', component: Home },
|
|
93
|
+
* { path: '/user/:id', name: 'user', component: User },
|
|
94
|
+
* ],
|
|
95
|
+
* base: '/app',
|
|
96
|
+
* })
|
|
97
|
+
*
|
|
98
|
+
* // 注册守卫
|
|
99
|
+
* router.beforeEach((to, from, next) => {
|
|
100
|
+
* console.log('导航到:', to.path)
|
|
101
|
+
* next()
|
|
102
|
+
* })
|
|
103
|
+
*
|
|
104
|
+
* // 编程式导航
|
|
105
|
+
* router.push('/user/123')
|
|
106
|
+
*
|
|
107
|
+
* // 作为插件安装
|
|
108
|
+
* app.use(router)
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
export declare function createRouter(options: RouterOptions): Router;
|
|
112
|
+
//# sourceMappingURL=create-router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-router.d.ts","sourceRoot":"","sources":["../../src/create-router.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAEL,KAAK,WAAW,EAGjB,MAAM,WAAW,CAAC;AASnB,OAAO,EAKL,KAAK,eAAe,EAErB,MAAM,UAAU,CAAC;AAElB,OAAO,EAGL,KAAK,GAAG,EACT,MAAM,mBAAmB,CAAC;AAM3B,WAAW;AACX,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,MAAM,CAAC;AAE5C,aAAa;AACb,MAAM,WAAW,aAAa;IAC5B,wCAAwC;IACxC,IAAI,EAAE,UAAU,CAAC;IACjB,aAAa;IACb,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,kCAAkC;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,iBAAiB;AACjB,MAAM,WAAW,KAAK;IACpB,WAAW;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW;IACX,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,WAAW;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,WAAW;IACX,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,aAAa;IACb,IAAI,EAAE,MAAM,CAAC;IACb,eAAe;IACf,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB;AAED,WAAW;AACX,MAAM,WAAW,MAAM;IACrB,sBAAsB;IACtB,YAAY,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC;IACzB,aAAa;IACb,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,aAAa;IACb,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,gBAAgB;IAChB,EAAE,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,WAAW;IACX,IAAI,IAAI,IAAI,CAAC;IACb,WAAW;IACX,OAAO,IAAI,IAAI,CAAC;IAChB,eAAe;IACf,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,IAAI,CAAC;IAC/C,eAAe;IACf,SAAS,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAC/D,eAAe;IACf,aAAa,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,IAAI,CAAC;IAClD,aAAa;IACb,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAAC;IACnC,cAAc;IACd,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,eAAe;IACf,SAAS,IAAI,WAAW,EAAE,CAAC;IAC3B,2BAA2B;IAC3B,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI,CAAC;IACxB,aAAa;IACb,OAAO,IAAI,IAAI,CAAC;CACjB;AA8CD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CAiQ3D"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lyt.js 路由系统 — 导航守卫(Guards)
|
|
3
|
+
*
|
|
4
|
+
* 提供全局导航守卫机制,在路由导航过程中执行拦截逻辑。
|
|
5
|
+
*
|
|
6
|
+
* 守卫类型:
|
|
7
|
+
* 1. beforeEach — 全局前置守卫(在导航确认前调用)
|
|
8
|
+
* 2. beforeResolve — 全局解析守卫(在导航确认后、组件渲染前调用)
|
|
9
|
+
* 3. afterEach — 全局后置守卫(在导航完成后调用)
|
|
10
|
+
*
|
|
11
|
+
* 导航控制(通过 next 函数):
|
|
12
|
+
* - next() — 确认导航
|
|
13
|
+
* - next(false) — 取消导航
|
|
14
|
+
* - next('/path') — 重定向到指定路径
|
|
15
|
+
*
|
|
16
|
+
* 纯原生零依赖实现。
|
|
17
|
+
*/
|
|
18
|
+
/** 路由目标位置(简化版) */
|
|
19
|
+
export interface NavigationTarget {
|
|
20
|
+
/** 目标路径 */
|
|
21
|
+
path: string;
|
|
22
|
+
/** 完整路径(含 query 和 hash) */
|
|
23
|
+
fullPath: string;
|
|
24
|
+
/** 路由参数 */
|
|
25
|
+
params: Record<string, string>;
|
|
26
|
+
/** 路由名称 */
|
|
27
|
+
name?: string;
|
|
28
|
+
/** 路由元信息 */
|
|
29
|
+
meta?: Record<string, any>;
|
|
30
|
+
/** 查询参数 */
|
|
31
|
+
query: Record<string, string>;
|
|
32
|
+
/** hash 值 */
|
|
33
|
+
hash: string;
|
|
34
|
+
}
|
|
35
|
+
/** 导航守卫回调函数 */
|
|
36
|
+
export type NavigationGuard = (to: NavigationTarget, from: NavigationTarget, next: NavigationGuardNext) => void;
|
|
37
|
+
/** next 函数类型 */
|
|
38
|
+
export type NavigationGuardNext = (location?: string | false | void) => void;
|
|
39
|
+
/** 导航守卫管理器 */
|
|
40
|
+
export interface NavigationGuards {
|
|
41
|
+
/** 注册全局前置守卫 */
|
|
42
|
+
beforeEach(guard: NavigationGuard): () => void;
|
|
43
|
+
/** 注册全局解析守卫 */
|
|
44
|
+
beforeResolve(guard: NavigationGuard): () => void;
|
|
45
|
+
/** 注册全局后置守卫 */
|
|
46
|
+
afterEach(guard: (to: NavigationTarget, from: NavigationTarget) => void): () => void;
|
|
47
|
+
/** 前置守卫列表(内部使用) */
|
|
48
|
+
_beforeEachGuards: NavigationGuard[];
|
|
49
|
+
/** 解析守卫列表(内部使用) */
|
|
50
|
+
_beforeResolveGuards: NavigationGuard[];
|
|
51
|
+
/** 后置守卫列表(内部使用) */
|
|
52
|
+
_afterEachGuards: Array<(to: NavigationTarget, from: NavigationTarget) => void>;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* 创建导航守卫管理器
|
|
56
|
+
*
|
|
57
|
+
* 维护三类守卫队列,提供注册和执行方法。
|
|
58
|
+
*
|
|
59
|
+
* @returns 导航守卫管理器
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```ts
|
|
63
|
+
* const guards = createNavigationGuards()
|
|
64
|
+
*
|
|
65
|
+
* // 注册前置守卫
|
|
66
|
+
* const remove = guards.beforeEach((to, from, next) => {
|
|
67
|
+
* if (to.path === '/admin' && !isLoggedIn) {
|
|
68
|
+
* next('/login') // 重定向到登录页
|
|
69
|
+
* } else {
|
|
70
|
+
* next() // 确认导航
|
|
71
|
+
* }
|
|
72
|
+
* })
|
|
73
|
+
*
|
|
74
|
+
* // 注册后置守卫
|
|
75
|
+
* guards.afterEach((to, from) => {
|
|
76
|
+
* console.log('导航完成:', to.path)
|
|
77
|
+
* })
|
|
78
|
+
*
|
|
79
|
+
* // 移除守卫
|
|
80
|
+
* remove()
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
export declare function createNavigationGuards(): NavigationGuards;
|
|
84
|
+
/**
|
|
85
|
+
* 执行导航守卫队列
|
|
86
|
+
*
|
|
87
|
+
* 按顺序执行守卫函数,支持异步守卫。
|
|
88
|
+
* 如果某个守卫调用了 next(false),中止导航。
|
|
89
|
+
* 如果某个守卫调用了 next('/path'),重定向。
|
|
90
|
+
*
|
|
91
|
+
* @param guards - 守卫函数列表
|
|
92
|
+
* @param to - 目标路由
|
|
93
|
+
* @param from - 来源路由
|
|
94
|
+
* @returns Promise,resolve 表示导航确认,reject 表示导航中止或重定向
|
|
95
|
+
*/
|
|
96
|
+
export declare function runGuards(guards: NavigationGuard[], to: NavigationTarget, from: NavigationTarget): Promise<void>;
|
|
97
|
+
/**
|
|
98
|
+
* 执行后置守卫队列
|
|
99
|
+
*
|
|
100
|
+
* 后置守卫不接受 next 函数,按顺序执行。
|
|
101
|
+
*
|
|
102
|
+
* @param guards - 后置守卫列表
|
|
103
|
+
* @param to - 目标路由
|
|
104
|
+
* @param from - 来源路由
|
|
105
|
+
*/
|
|
106
|
+
export declare function runAfterGuards(guards: Array<(to: NavigationTarget, from: NavigationTarget) => void>, to: NavigationTarget, from: NavigationTarget): void;
|
|
107
|
+
//# sourceMappingURL=guards.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guards.d.ts","sourceRoot":"","sources":["../../src/guards.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,kBAAkB;AAClB,MAAM,WAAW,gBAAgB;IAC/B,WAAW;IACX,IAAI,EAAE,MAAM,CAAC;IACb,2BAA2B;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW;IACX,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,WAAW;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,WAAW;IACX,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,aAAa;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,eAAe;AACf,MAAM,MAAM,eAAe,GAAG,CAC5B,EAAE,EAAE,gBAAgB,EACpB,IAAI,EAAE,gBAAgB,EACtB,IAAI,EAAE,mBAAmB,KACtB,IAAI,CAAC;AAEV,gBAAgB;AAChB,MAAM,MAAM,mBAAmB,GAAG,CAChC,QAAQ,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,KAC7B,IAAI,CAAC;AAEV,cAAc;AACd,MAAM,WAAW,gBAAgB;IAC/B,eAAe;IACf,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,IAAI,CAAC;IAC/C,eAAe;IACf,aAAa,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,IAAI,CAAC;IAClD,eAAe;IACf,SAAS,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,gBAAgB,EAAE,IAAI,EAAE,gBAAgB,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IACrF,mBAAmB;IACnB,iBAAiB,EAAE,eAAe,EAAE,CAAC;IACrC,mBAAmB;IACnB,oBAAoB,EAAE,eAAe,EAAE,CAAC;IACxC,mBAAmB;IACnB,gBAAgB,EAAE,KAAK,CAAC,CAAC,EAAE,EAAE,gBAAgB,EAAE,IAAI,EAAE,gBAAgB,KAAK,IAAI,CAAC,CAAC;CACjF;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,sBAAsB,IAAI,gBAAgB,CAwFzD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CACvB,MAAM,EAAE,eAAe,EAAE,EACzB,EAAE,EAAE,gBAAgB,EACpB,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,IAAI,CAAC,CAgFf;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,KAAK,CAAC,CAAC,EAAE,EAAE,gBAAgB,EAAE,IAAI,EAAE,gBAAgB,KAAK,IAAI,CAAC,EACrE,EAAE,EAAE,gBAAgB,EACpB,IAAI,EAAE,gBAAgB,GACrB,IAAI,CAQN"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lyt.js 路由系统 — History 管理
|
|
3
|
+
*
|
|
4
|
+
* 提供两种路由模式:
|
|
5
|
+
* 1. HTML5 History 模式(createWebHistory):使用 pushState/replaceState API
|
|
6
|
+
* 2. Hash 模式(createHashHistory):使用 URL hash(#)部分
|
|
7
|
+
*
|
|
8
|
+
* 两种模式都提供统一的 API:
|
|
9
|
+
* - push(path) / replace(path) / go(n) / back() / forward()
|
|
10
|
+
* - 监听 URL 变化事件
|
|
11
|
+
* - 获取当前路由信息
|
|
12
|
+
*
|
|
13
|
+
* 纯原生零依赖实现。
|
|
14
|
+
*/
|
|
15
|
+
/** 路由位置信息 */
|
|
16
|
+
export interface RouterLocation {
|
|
17
|
+
/** 当前路径 */
|
|
18
|
+
path: string;
|
|
19
|
+
/** 完整 URL(含 hash) */
|
|
20
|
+
fullPath: string;
|
|
21
|
+
/** URL 查询参数对象 */
|
|
22
|
+
query: Record<string, string>;
|
|
23
|
+
/** URL hash 值(不含 #) */
|
|
24
|
+
hash: string;
|
|
25
|
+
/** 路由状态(通过 pushState 传入的 state) */
|
|
26
|
+
state: any;
|
|
27
|
+
/** 是否来自浏览器前进/后退操作 */
|
|
28
|
+
fromPopState: boolean;
|
|
29
|
+
}
|
|
30
|
+
/** History 变化监听回调 */
|
|
31
|
+
export type HistoryChangeListener = (location: RouterLocation, from: RouterLocation) => void;
|
|
32
|
+
/** History 实例接口 */
|
|
33
|
+
export interface RouterHistory {
|
|
34
|
+
/** 基础路径(History 模式下使用) */
|
|
35
|
+
base: string;
|
|
36
|
+
/** 当前位置信息 */
|
|
37
|
+
location: RouterLocation;
|
|
38
|
+
/** 导航到新路径(新增历史记录) */
|
|
39
|
+
push(path: string, state?: any): void;
|
|
40
|
+
/** 替换当前路径(不新增历史记录) */
|
|
41
|
+
replace(path: string, state?: any): void;
|
|
42
|
+
/** 前进/后退 n 步 */
|
|
43
|
+
go(n: number): void;
|
|
44
|
+
/** 后退一步 */
|
|
45
|
+
back(): void;
|
|
46
|
+
/** 前进一步 */
|
|
47
|
+
forward(): void;
|
|
48
|
+
/** 获取当前路由位置 */
|
|
49
|
+
getCurrentRoute(): RouterLocation;
|
|
50
|
+
/** 监听路由变化 */
|
|
51
|
+
listen(callback: HistoryChangeListener): () => void;
|
|
52
|
+
/** 销毁 History 实例,移除事件监听 */
|
|
53
|
+
destroy(): void;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* 创建 HTML5 History 模式的路由管理器
|
|
57
|
+
*
|
|
58
|
+
* 使用浏览器原生的 history.pushState / history.replaceState API,
|
|
59
|
+
* 配合 popstate 事件监听浏览器前进/后退操作。
|
|
60
|
+
*
|
|
61
|
+
* @param base - 应用基础路径(默认 '/')
|
|
62
|
+
* @returns History 实例
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```ts
|
|
66
|
+
* const history = createWebHistory('/app')
|
|
67
|
+
* history.push('/user/123')
|
|
68
|
+
* history.back()
|
|
69
|
+
* history.listen((to, from) => {
|
|
70
|
+
* console.log('路由变化:', from.path, '->', to.path)
|
|
71
|
+
* })
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
export declare function createWebHistory(base?: string): RouterHistory;
|
|
75
|
+
/**
|
|
76
|
+
* 创建 Hash 模式的路由管理器
|
|
77
|
+
*
|
|
78
|
+
* 使用 URL 的 hash 部分(#)作为路由路径。
|
|
79
|
+
* 兼容性更好,不需要服务器端配置。
|
|
80
|
+
*
|
|
81
|
+
* 工作原理:
|
|
82
|
+
* - 路由路径存储在 URL 的 hash 部分,如 http://example.com/#/user/123
|
|
83
|
+
* - 通过 hashchange 事件监听 hash 变化
|
|
84
|
+
* - 通过 location.hash 修改 hash
|
|
85
|
+
*
|
|
86
|
+
* @returns History 实例
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```ts
|
|
90
|
+
* const history = createHashHistory()
|
|
91
|
+
* history.push('/user/123') // URL 变为 http://example.com/#/user/123
|
|
92
|
+
* history.listen((to, from) => {
|
|
93
|
+
* console.log('hash 路由变化:', from.path, '->', to.path)
|
|
94
|
+
* })
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
export declare function createHashHistory(): RouterHistory;
|
|
98
|
+
//# sourceMappingURL=history.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../src/history.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH,aAAa;AACb,MAAM,WAAW,cAAc;IAC7B,WAAW;IACX,IAAI,EAAE,MAAM,CAAC;IACb,qBAAqB;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB;IACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,mCAAmC;IACnC,KAAK,EAAE,GAAG,CAAC;IACX,qBAAqB;IACrB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,qBAAqB;AACrB,MAAM,MAAM,qBAAqB,GAAG,CAClC,QAAQ,EAAE,cAAc,EACxB,IAAI,EAAE,cAAc,KACjB,IAAI,CAAC;AAEV,mBAAmB;AACnB,MAAM,WAAW,aAAa;IAC5B,0BAA0B;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,aAAa;IACb,QAAQ,EAAE,cAAc,CAAC;IACzB,qBAAqB;IACrB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC;IACtC,sBAAsB;IACtB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC;IACzC,gBAAgB;IAChB,EAAE,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,WAAW;IACX,IAAI,IAAI,IAAI,CAAC;IACb,WAAW;IACX,OAAO,IAAI,IAAI,CAAC;IAChB,eAAe;IACf,eAAe,IAAI,cAAc,CAAC;IAClC,aAAa;IACb,MAAM,CAAC,QAAQ,EAAE,qBAAqB,GAAG,MAAM,IAAI,CAAC;IACpD,2BAA2B;IAC3B,OAAO,IAAI,IAAI,CAAC;CACjB;AAqHD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,GAAE,MAAY,GAAG,aAAa,CAmLlE;AAMD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,iBAAiB,IAAI,aAAa,CA4JjD"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lyt.js 路由系统 — 统一导出入口
|
|
3
|
+
*
|
|
4
|
+
* 导出所有公共 API 和类型定义。
|
|
5
|
+
* 纯原生零依赖实现。
|
|
6
|
+
*/
|
|
7
|
+
export { createRouter } from './create-router';
|
|
8
|
+
export type { Router, RouterOptions, RouterMode, Route, } from './create-router';
|
|
9
|
+
export { createRouteMatcher } from './matcher';
|
|
10
|
+
export type { RouteRecord, RouteMatchResult, RouteMatcher, } from './matcher';
|
|
11
|
+
export { createWebHistory, createHashHistory, } from './history';
|
|
12
|
+
export type { RouterHistory, RouterLocation, HistoryChangeListener, } from './history';
|
|
13
|
+
export { createNavigationGuards, runGuards, runAfterGuards, } from './guards';
|
|
14
|
+
export type { NavigationGuard, NavigationGuardNext, NavigationTarget, NavigationGuards, } from './guards';
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,YAAY,EACV,MAAM,EACN,aAAa,EACb,UAAU,EACV,KAAK,GACN,MAAM,iBAAiB,CAAC;AAMzB,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAE/C,YAAY,EACV,WAAW,EACX,gBAAgB,EAChB,YAAY,GACb,MAAM,WAAW,CAAC;AAMnB,OAAO,EACL,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,WAAW,CAAC;AAEnB,YAAY,EACV,aAAa,EACb,cAAc,EACd,qBAAqB,GACtB,MAAM,WAAW,CAAC;AAMnB,OAAO,EACL,sBAAsB,EACtB,SAAS,EACT,cAAc,GACf,MAAM,UAAU,CAAC;AAElB,YAAY,EACV,eAAe,EACf,mBAAmB,EACnB,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lyt.js 路由系统 — 路由匹配器(Matcher)
|
|
3
|
+
*
|
|
4
|
+
* 自研正则路径匹配引擎,将路由路径模式编译为正则表达式,
|
|
5
|
+
* 支持静态路径、动态参数(:param)、通配符(*)。
|
|
6
|
+
*
|
|
7
|
+
* 核心原理:
|
|
8
|
+
* 1. 将路径模式(如 /user/:id)编译为正则表达式(如 /^\/user\/([^/]+)$/)
|
|
9
|
+
* 2. 正则中的捕获组对应动态参数,匹配时自动提取参数值
|
|
10
|
+
* 3. 通配符 * 编译为 (.+),匹配任意路径
|
|
11
|
+
*
|
|
12
|
+
* 纯原生零依赖实现。
|
|
13
|
+
*/
|
|
14
|
+
/** 路由记录 */
|
|
15
|
+
export interface RouteRecord {
|
|
16
|
+
/** 路由名称(唯一标识,用于 removeRoute 等) */
|
|
17
|
+
name?: string;
|
|
18
|
+
/** 路由路径模式,如 '/user/:id' */
|
|
19
|
+
path: string;
|
|
20
|
+
/** 路由元信息(自定义数据) */
|
|
21
|
+
meta?: Record<string, any>;
|
|
22
|
+
/** 路由组件 */
|
|
23
|
+
component?: any;
|
|
24
|
+
/** 重定向路径 */
|
|
25
|
+
redirect?: string;
|
|
26
|
+
/** 子路由 */
|
|
27
|
+
children?: RouteRecord[];
|
|
28
|
+
/** 编译后的正则(内部使用) */
|
|
29
|
+
_regex?: RegExp;
|
|
30
|
+
/** 参数名列表(内部使用) */
|
|
31
|
+
_paramKeys?: string[];
|
|
32
|
+
/** 是否为通配符路由 */
|
|
33
|
+
_isWildcard?: boolean;
|
|
34
|
+
}
|
|
35
|
+
/** 路由匹配结果 */
|
|
36
|
+
export interface RouteMatchResult {
|
|
37
|
+
/** 匹配到的路由记录 */
|
|
38
|
+
record: RouteRecord;
|
|
39
|
+
/** 提取的路径参数,如 { id: '123' } */
|
|
40
|
+
params: Record<string, string>;
|
|
41
|
+
/** 匹配到的完整路径 */
|
|
42
|
+
matchedPath: string;
|
|
43
|
+
}
|
|
44
|
+
/** 路由匹配器实例 */
|
|
45
|
+
export interface RouteMatcher {
|
|
46
|
+
/** 匹配路径,返回匹配结果或 null */
|
|
47
|
+
matchRoute(path: string): RouteMatchResult | null;
|
|
48
|
+
/** 动态添加路由 */
|
|
49
|
+
addRoute(route: RouteRecord): void;
|
|
50
|
+
/** 按名称移除路由 */
|
|
51
|
+
removeRoute(name: string): void;
|
|
52
|
+
/** 获取所有路由记录 */
|
|
53
|
+
getRoutes(): RouteRecord[];
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* 创建路由匹配器
|
|
57
|
+
*
|
|
58
|
+
* 接收路由配置数组,编译所有路由路径模式为正则表达式,
|
|
59
|
+
* 提供 matchRoute、addRoute、removeRoute 等方法。
|
|
60
|
+
*
|
|
61
|
+
* @param routes - 路由配置数组
|
|
62
|
+
* @returns 路由匹配器实例
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```ts
|
|
66
|
+
* const matcher = createRouteMatcher([
|
|
67
|
+
* { path: '/', name: 'home', component: Home },
|
|
68
|
+
* { path: '/user/:id', name: 'user', component: User },
|
|
69
|
+
* { path: '/files/*', name: 'files', component: Files },
|
|
70
|
+
* ])
|
|
71
|
+
*
|
|
72
|
+
* const result = matcher.matchRoute('/user/123')
|
|
73
|
+
* // result = { record: {...}, params: { id: '123' }, matchedPath: '/user/123' }
|
|
74
|
+
*
|
|
75
|
+
* matcher.addRoute({ path: '/about', name: 'about', component: About })
|
|
76
|
+
* matcher.removeRoute('about')
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export declare function createRouteMatcher(routes: RouteRecord[]): RouteMatcher;
|
|
80
|
+
//# sourceMappingURL=matcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matcher.d.ts","sourceRoot":"","sources":["../../src/matcher.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH,WAAW;AACX,MAAM,WAAW,WAAW;IAC1B,kCAAkC;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,mBAAmB;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,WAAW;IACX,SAAS,CAAC,EAAE,GAAG,CAAC;IAChB,YAAY;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU;IACV,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;IACzB,mBAAmB;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kBAAkB;IAClB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,eAAe;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,aAAa;AACb,MAAM,WAAW,gBAAgB;IAC/B,eAAe;IACf,MAAM,EAAE,WAAW,CAAC;IACpB,8BAA8B;IAC9B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,eAAe;IACf,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,cAAc;AACd,MAAM,WAAW,YAAY;IAC3B,wBAAwB;IACxB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAAC;IAClD,aAAa;IACb,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAAC;IACnC,cAAc;IACd,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,eAAe;IACf,SAAS,IAAI,WAAW,EAAE,CAAC;CAC5B;AAoID;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,YAAY,CAwHtE"}
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lytjs/router",
|
|
3
|
+
"version": "3.1.0",
|
|
4
|
+
"description": "Lyt.js 内置路由 - 支持哈希模式、历史模式和导航守卫的前端路由",
|
|
5
|
+
"main": "./dist/index.cjs",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/types/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/types/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.cjs",
|
|
13
|
+
"default": "./dist/index.mjs"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"sideEffects": false,
|
|
17
|
+
"files": ["dist"],
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"author": "lytjs",
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "https://gitee.com/@lytjs/lytjs"
|
|
23
|
+
},
|
|
24
|
+
"homepage": "https://gitee.com/@lytjs/lytjs",
|
|
25
|
+
"keywords": [
|
|
26
|
+
"lyt",
|
|
27
|
+
"lytjs",
|
|
28
|
+
"javascript",
|
|
29
|
+
"framework",
|
|
30
|
+
"frontend",
|
|
31
|
+
"vue-like",
|
|
32
|
+
"lightweight",
|
|
33
|
+
"zero-dependency",
|
|
34
|
+
"router",
|
|
35
|
+
"routing",
|
|
36
|
+
"navigation",
|
|
37
|
+
"路由"
|
|
38
|
+
],
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"access": "public"
|
|
41
|
+
}
|
|
42
|
+
}
|