@oinone/kunlun-vue-router 6.2.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/README.md ADDED
@@ -0,0 +1 @@
1
+ 默认layout
@@ -0,0 +1,15 @@
1
+ import{SPI as e}from"@oinone/kunlun-spi";import{VueWidget as t,genToken as r,Widget as o,ViewWidget as n}from"@oinone/kunlun-vue-widget";import{inject as u,computed as l,provide as a,toRefs as i,getCurrentInstance as c,onMounted as s,Fragment as d,isVNode as p,ref as g,watch as v,cloneVNode as f,shallowRef as m}from"vue";import{_useMatched as h,matchPath as w,getRouterInstance as R}from"@oinone/kunlun-router";export{useMatched}from"@oinone/kunlun-router";
2
+ /*! *****************************************************************************
3
+ Copyright (c) Microsoft Corporation.
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted.
7
+
8
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
9
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
13
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14
+ PERFORMANCE OF THIS SOFTWARE.
15
+ ***************************************************************************** */let b=class BaseRouterWidget extends t{};b=function(e,t,r,o){var n,u=arguments.length,l=u<3?t:null===o?o=Object.getOwnPropertyDescriptor(t,r):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)l=Reflect.decorate(e,t,r,o);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(l=(u<3?n(l):u>3?n(t,r,l):n(t,r))||l);return u>3&&l&&Object.defineProperty(t,r,l),l}([e.Base("Router",["widget"])],b);class RouterWidget extends b{}const M=r("router view location matched"),y=r("parent_segment_group"),S=e=>{const t=u(M),r=u(y,l((()=>t.value.root))),o=l((()=>{if(!(null==r?void 0:r.value))return;const{children:t}=r.value;return e?t[e]:t.primary}));e&&a(y,o);return{currentSegmentGroup:l((()=>{if(!o.value)return;const{children:e}=o.value;return Object.keys(e).length?e.primary:o.value}))}},W=r("root widget token"),k=e=>{const t=o.select(e);return a(W,t),t},j=()=>u(W),O=e=>{const t=j();if(!t)throw new Error("Need a root widget in Match tag");t.children.forEach((e=>e.dispose())),Object.entries(e).forEach((([e,r])=>{"default"===e&&t.createWidget(r),t.createWidget(r,e),t.forceUpdate()}))},E=()=>({setRootWidget:k,getRootWidget:j,registerWidgets:O}),N="Route",P={name:N,inheritAttrs:!1,props:{path:String,slotName:{type:String,required:!0},namespace:String,computedMatched:Object,widgets:Object,widget:String},setup(e,{slots:t}){const{widget:r,widgets:o}=e,{path:u,namespace:l,computedMatched:a}=i(e),{currentSegmentGroup:c}=S(null==l?void 0:l.value),{matched:s,setMatched:d}=h(),{registerWidgets:p}=E();let g={};if(r){const t=b.Selector({widget:r})||n.Selector({widget:r});if(!t||!e.slotName)throw new Error(`路由${u}对应的页面:${r}匹配异常`);g={[e.slotName]:t},p(g)}return o&&p(o),()=>{var e;if(!t.default||!c.value)return!c.value&&t.default?t.default():null;let r;const o=t.default();return r=(null==a?void 0:a.value)?a.value:u.value?w(null===(e=c.value)||void 0===e?void 0:e.segments,{path:u.value}):s,r&&d(r),r?o:null}}},$=P,x=()=>{const e=c();if(!e)throw new Error("No vue instance in current component.");return{router:e.appContext.config.globalProperties.$router}},G=()=>x().router,A="Redirect",B={name:A,props:{to:String},setup(e){const{router:t}=x();s((()=>{t.navigate(e.to,{replaceUrl:!0})}))}},C=[N,A],T=e=>e.reduce(((e,t)=>[...e,...t.type===d?T(t.children):[t]]),[]),U={name:"Match",props:{namespace:String,rootToken:String},setup(e,{slots:t}){const{rootToken:r}=e,{namespace:o}=i(e),{currentSegmentGroup:n}=S(null==o?void 0:o.value),{matched:u,setMatched:a}=h();let c;if(r){const{setRootWidget:e}=E(),t=e(r);c=t.getNodeCodeRef()}const s=l((()=>{if(!t.default)return null;let e,r=[];n.value&&(r=n.value.segments);let o=null;return T(t.default()).forEach((t=>{if(o||!p(t))return;const n=t.type,{name:l}=n;if(!C.includes(l))return;e=t;const{path:a}=t.props;o=a?w(r,{path:a}):u})),o?(a(o),{currentMatched:o,element:e}):null})),d=g(null);return v([s],(([e],[t])=>{d.value&&(null==e?void 0:e.currentMatched.path)===(null==t?void 0:t.currentMatched.path)||(d.value=e)}),{immediate:!0}),()=>{if(d.value&&c.value)return f(d.value.element,{key:d.value.element,computedMatched:d.value.currentMatched})}}},_=U,q=()=>{const e=R(),t=m(null);return e.activatedRoute.subscribe((e=>{t.value=e})),{install:r=>{if(r.config.globalProperties.$router)return void console.warn("Already install vue router: ",r.config.globalProperties.$router);r.config.globalProperties.$router=e,r.component("Route",$),r.component("Match",_),r.component("Redirect",B);const o=l((()=>t.value));r.provide(M,o),e.ignite()}}};export{b as BaseRouterWidget,_ as Match,A as REDIRECT_COMPONENT_NAME,N as ROUTE_COMPONENT_NAME,B as Redirect,$ as Route,RouterWidget,q as createVueRouter,G as getRouter,x as useRouter};
@@ -0,0 +1 @@
1
+ export * from './src';
@@ -0,0 +1,8 @@
1
+ import { VNodeProps } from 'vue';
2
+ export interface MatchProps {
3
+ namespace?: string;
4
+ rootToken?: string;
5
+ }
6
+ export declare const Match: new () => {
7
+ $props: VNodeProps & MatchProps;
8
+ };
@@ -0,0 +1,8 @@
1
+ import { VNodeProps } from 'vue';
2
+ export interface RedirectProps {
3
+ to: string;
4
+ }
5
+ export declare const REDIRECT_COMPONENT_NAME = "Redirect";
6
+ export declare const Redirect: new () => {
7
+ $props: VNodeProps & RedirectProps;
8
+ };
@@ -0,0 +1,15 @@
1
+ import { Matched } from '@oinone/kunlun-router';
2
+ import { VNodeProps } from 'vue';
3
+ import { Widgets } from './useWidget';
4
+ export interface RouteProps {
5
+ path: string;
6
+ slotName: string;
7
+ namespace?: string;
8
+ computedMatched?: Matched;
9
+ widgets?: Widgets;
10
+ widget?: string;
11
+ }
12
+ export declare const ROUTE_COMPONENT_NAME = "Route";
13
+ export declare const Route: new () => {
14
+ $props: VNodeProps & RouteProps;
15
+ };
@@ -0,0 +1,3 @@
1
+ import { BaseRouterWidget } from './token';
2
+ export declare abstract class RouterWidget extends BaseRouterWidget {
3
+ }
@@ -0,0 +1,2 @@
1
+ export * from './token';
2
+ export * from './RouterWidget';
@@ -0,0 +1,10 @@
1
+ import { Constructor } from '@oinone/kunlun-shared';
2
+ import { SPIOptions, SPISingleSelector, SPITokenFactory } from '@oinone/kunlun-spi';
3
+ import { VueWidget } from '@oinone/kunlun-vue-widget';
4
+ export interface BaseRouterOptions extends SPIOptions {
5
+ widget?: string;
6
+ }
7
+ export declare class BaseRouterWidget extends VueWidget {
8
+ static Token: SPITokenFactory<BaseRouterOptions>;
9
+ static Selector: SPISingleSelector<BaseRouterOptions, Constructor<BaseRouterWidget>>;
10
+ }
@@ -0,0 +1 @@
1
+ export * from './BaseRouterWidget';
@@ -0,0 +1,9 @@
1
+ import { Router } from '@oinone/kunlun-router';
2
+ export declare const useRouter: () => {
3
+ router: Router;
4
+ };
5
+ /**
6
+ * 该方法只能在beforeCreated、created、mounted生命周期中调用才会生效。
7
+ * 如果想全局使用,请调用 @see {@link getRouterInstance}
8
+ */
9
+ export declare const getRouter: () => Router;
@@ -0,0 +1,6 @@
1
+ import { UrlSegmentGroup } from '@oinone/kunlun-router';
2
+ import { ComputedRef } from 'vue';
3
+ export declare const PARENT_SEGMENT_GROUP_TOKEN: import("vue").InjectionKey<ComputedRef<UrlSegmentGroup | undefined>>;
4
+ export declare const useSegmentGroup: (namespace?: string | undefined) => {
5
+ currentSegmentGroup: ComputedRef<UrlSegmentGroup | undefined>;
6
+ };
@@ -0,0 +1,7 @@
1
+ export * from './basic';
2
+ export * from './router';
3
+ export * from './Route';
4
+ export * from './Match';
5
+ export * from './Redirect';
6
+ export * from './helpers/useRouter';
7
+ export { useMatched } from '@oinone/kunlun-router';
@@ -0,0 +1,5 @@
1
+ import { App } from 'vue';
2
+ declare const createVueRouter: () => {
3
+ install: (app: App) => void;
4
+ };
5
+ export { createVueRouter };
@@ -0,0 +1,3 @@
1
+ import { ComputedRef } from 'vue';
2
+ import { ActivatedRoute } from '@oinone/kunlun-router';
3
+ export declare const ACTIVATED_ROUTE_TOKEN: import("vue").InjectionKey<ComputedRef<ActivatedRoute>>;
@@ -0,0 +1,13 @@
1
+ import { VueWidget } from '@oinone/kunlun-vue-widget';
2
+ export interface Widgets {
3
+ [namespace: string]: VueWidget;
4
+ }
5
+ declare const setRootWidget: (token: string) => VueWidget;
6
+ declare const getRootWidget: () => VueWidget | undefined;
7
+ declare const registerWidgets: (widgets: Widgets) => void;
8
+ export declare const useWidgetService: () => {
9
+ setRootWidget: typeof setRootWidget;
10
+ getRootWidget: typeof getRootWidget;
11
+ registerWidgets: typeof registerWidgets;
12
+ };
13
+ export {};
package/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './src';
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@oinone/kunlun-vue-router",
3
+ "version": "6.2.0",
4
+ "main": "index.ts",
5
+ "scripts": {
6
+ "prebuild": "rimraf dist",
7
+ "build": "rollup -c",
8
+ "dist": "npm run prepublishOnly",
9
+ "index": "npm run postpublish",
10
+ "x-prepublishOnly": "node ../../scripts/prepublish-only.js",
11
+ "x-postpublish": "node ../../scripts/postpublish.js",
12
+ "doc": "typedoc --out docs src/index.ts"
13
+ },
14
+ "dependencies": {
15
+ "@oinone/kunlun-vue-widget": "6.2.0"
16
+ },
17
+ "devDependencies": {
18
+ "@oinone/kunlun-router": "~6.2.0",
19
+ "@oinone/kunlun-shared": "~6.2.0",
20
+ "@oinone/kunlun-spi": "~6.2.0",
21
+ "@rollup/plugin-json": "4.1.0",
22
+ "@rollup/plugin-node-resolve": "11.2.1",
23
+ "@rollup/plugin-replace": "2.4.2",
24
+ "@types/lodash": "4.14.182",
25
+ "@types/lodash-es": "4.17.6",
26
+ "lodash": "4.17.21",
27
+ "lodash-es": "4.17.21"
28
+ },
29
+ "peerDependencies": {
30
+ "vue": "3.2.40"
31
+ },
32
+ "gitHead": "b65bbf1d649da1017810c5608473d5daa1a41f94"
33
+ }
@@ -0,0 +1,8 @@
1
+ import pkg from './package.json';
2
+ import rollupConfig from '../../scripts/build.config.js';
3
+
4
+ export default rollupConfig(
5
+ pkg.name,
6
+ ['@oinone/kunlun-router', '@oinone/kunlun-spi', '@oinone/kunlun-vue-widget', 'lodash', 'lodash-es', 'vue'],
7
+ false
8
+ );
package/src/Match.ts ADDED
@@ -0,0 +1,130 @@
1
+ import {
2
+ cloneVNode,
3
+ SetupContext,
4
+ VNodeProps,
5
+ isVNode,
6
+ VNode,
7
+ RendererNode,
8
+ RendererElement,
9
+ ConcreteComponent,
10
+ toRefs,
11
+ Fragment,
12
+ computed,
13
+ ref,
14
+ watch
15
+ } from 'vue';
16
+ import { UrlSegment, matchPath, Matched, _useMatched } from '@oinone/kunlun-router';
17
+
18
+ import { RouteProps, ROUTE_COMPONENT_NAME } from './Route';
19
+ import { REDIRECT_COMPONENT_NAME } from './Redirect';
20
+ import { useSegmentGroup } from './helpers/useSegmentGroup';
21
+ import { useWidgetService } from './useWidget';
22
+
23
+ export interface MatchProps {
24
+ namespace?: string;
25
+ rootToken?: string;
26
+ }
27
+
28
+ const MATCH_COMPONENTS = [ROUTE_COMPONENT_NAME, REDIRECT_COMPONENT_NAME];
29
+
30
+ const unwrapFragment = (
31
+ children: VNode<RendererNode, RendererElement, RouteProps>[]
32
+ ): VNode<RendererNode, RendererElement, RouteProps>[] => {
33
+ return children.reduce(
34
+ (prev, child) => [...prev, ...(child.type === Fragment ? unwrapFragment(child.children as any) : [child])],
35
+ [] as any
36
+ );
37
+ };
38
+
39
+ const MatchImpl = {
40
+ name: 'Match',
41
+ props: {
42
+ namespace: String,
43
+ rootToken: String
44
+ },
45
+ setup(props: MatchProps, { slots }: SetupContext) {
46
+ const { rootToken } = props;
47
+ const { namespace } = toRefs(props);
48
+ const { currentSegmentGroup } = useSegmentGroup(namespace?.value);
49
+ const { matched, setMatched } = _useMatched();
50
+
51
+ // widgets
52
+ let nodeCodeRef: any;
53
+ if (rootToken) {
54
+ const { setRootWidget } = useWidgetService();
55
+ const rootWidget = setRootWidget(rootToken);
56
+ nodeCodeRef = rootWidget.getNodeCodeRef();
57
+ }
58
+
59
+ const computedMatched = computed(() => {
60
+ if (!slots.default) {
61
+ return null;
62
+ }
63
+
64
+ let segments: UrlSegment[] = [];
65
+ if (currentSegmentGroup.value) {
66
+ segments = currentSegmentGroup.value.segments;
67
+ }
68
+
69
+ let element!: VNode;
70
+ let currentMatched: Matched = null as any;
71
+ const children = unwrapFragment(slots.default() as VNode<RendererNode, RendererElement, RouteProps>[]);
72
+ children.forEach((child) => {
73
+ if (currentMatched || !isVNode(child)) {
74
+ return;
75
+ }
76
+ const comp = child.type as ConcreteComponent;
77
+ const { name } = comp;
78
+ if (!MATCH_COMPONENTS.includes(name as string)) {
79
+ return;
80
+ }
81
+
82
+ // 这样能匹配到 redirect
83
+ element = child;
84
+
85
+ const { path: childPath } = child.props!;
86
+
87
+ currentMatched = childPath ? matchPath(segments, { path: childPath })! : matched;
88
+ });
89
+
90
+ if (!currentMatched) {
91
+ return null;
92
+ }
93
+
94
+ setMatched(currentMatched);
95
+
96
+ return { currentMatched, element };
97
+ });
98
+
99
+ const cacheMatched: any = ref(null);
100
+
101
+ watch(
102
+ [computedMatched],
103
+ ([cm], [prevCm]) => {
104
+ if (cacheMatched.value && cm?.currentMatched.path === prevCm?.currentMatched.path) {
105
+ return;
106
+ }
107
+ cacheMatched.value = cm;
108
+ },
109
+ { immediate: true }
110
+ );
111
+
112
+ return () => {
113
+ if (!cacheMatched.value || !nodeCodeRef.value) {
114
+ return;
115
+ }
116
+
117
+ // TODO: 不使用 key 來觸发 vnode 更新
118
+ return cloneVNode(cacheMatched.value!.element, {
119
+ key: cacheMatched.value!.element! as any,
120
+ computedMatched: cacheMatched.value!.currentMatched
121
+ });
122
+ };
123
+ }
124
+ };
125
+
126
+ export const Match = (MatchImpl as any) as {
127
+ new (): {
128
+ $props: VNodeProps & MatchProps;
129
+ };
130
+ };
@@ -0,0 +1,29 @@
1
+ import { VNodeProps, onMounted } from 'vue';
2
+
3
+ import { useRouter } from './helpers/useRouter';
4
+
5
+ export interface RedirectProps {
6
+ to: string;
7
+ }
8
+
9
+ export const REDIRECT_COMPONENT_NAME = 'Redirect';
10
+
11
+ const RedirectImpl = {
12
+ name: REDIRECT_COMPONENT_NAME,
13
+ props: {
14
+ to: String
15
+ },
16
+ setup(props: RedirectProps) {
17
+ const { router } = useRouter();
18
+
19
+ onMounted(() => {
20
+ router.navigate(props.to, { replaceUrl: true });
21
+ });
22
+ }
23
+ };
24
+
25
+ export const Redirect = (RedirectImpl as any) as {
26
+ new (): {
27
+ $props: VNodeProps & RedirectProps;
28
+ };
29
+ };
package/src/Route.ts ADDED
@@ -0,0 +1,83 @@
1
+ import { _useMatched, Matched, matchPath } from '@oinone/kunlun-router';
2
+ import { ViewWidget } from '@oinone/kunlun-vue-widget';
3
+ import { SetupContext, toRefs, VNodeProps } from 'vue';
4
+ import { BaseRouterWidget } from './basic';
5
+ import { useSegmentGroup } from './helpers/useSegmentGroup';
6
+ import { useWidgetService, Widgets } from './useWidget';
7
+
8
+ export interface RouteProps {
9
+ path: string;
10
+ slotName: string;
11
+ namespace?: string;
12
+ computedMatched?: Matched;
13
+ widgets?: Widgets;
14
+ widget?: string;
15
+ }
16
+
17
+ export const ROUTE_COMPONENT_NAME = 'Route';
18
+
19
+ const RouteImpl = {
20
+ name: ROUTE_COMPONENT_NAME,
21
+ inheritAttrs: false,
22
+ props: {
23
+ path: String,
24
+ slotName: {
25
+ type: String,
26
+ required: true
27
+ },
28
+ namespace: String,
29
+ computedMatched: Object,
30
+ widgets: Object,
31
+ widget: String
32
+ },
33
+ setup(props: RouteProps, { slots }: SetupContext) {
34
+ const { widget, widgets } = props;
35
+ const { path, namespace, computedMatched } = toRefs(props);
36
+ const { currentSegmentGroup } = useSegmentGroup(namespace?.value);
37
+ const { matched, setMatched } = _useMatched();
38
+ const { registerWidgets } = useWidgetService();
39
+ let widgetClass = {};
40
+ if (widget) {
41
+ const constructor = BaseRouterWidget.Selector({ widget }) || ViewWidget.Selector({ widget });
42
+ if (constructor && props.slotName) {
43
+ widgetClass = { [props.slotName]: constructor };
44
+ } else {
45
+ throw new Error(`路由${path}对应的页面:${widget}匹配异常`);
46
+ }
47
+ registerWidgets(widgetClass);
48
+ }
49
+ if (widgets) {
50
+ registerWidgets(widgets);
51
+ }
52
+ return () => {
53
+ if (!slots.default || !currentSegmentGroup.value) {
54
+ if (!currentSegmentGroup.value && slots.default) {
55
+ return slots.default();
56
+ }
57
+ return null;
58
+ }
59
+
60
+ let currentMatched: Matched | null;
61
+ const children = slots.default();
62
+
63
+ if (computedMatched?.value) {
64
+ currentMatched = computedMatched.value;
65
+ } else {
66
+ // 有配置路由 path 則去匹配 matched 結構,沒有配置路由 path 則使用上下文的 matched 結構
67
+ currentMatched = path.value ? matchPath(currentSegmentGroup.value?.segments, { path: path.value }) : matched;
68
+ }
69
+
70
+ if (currentMatched) {
71
+ setMatched(currentMatched);
72
+ }
73
+
74
+ return currentMatched ? children : null;
75
+ };
76
+ }
77
+ };
78
+
79
+ export const Route = RouteImpl as any as {
80
+ new (): {
81
+ $props: VNodeProps & RouteProps;
82
+ };
83
+ };
@@ -0,0 +1,3 @@
1
+ import { BaseRouterWidget } from './token';
2
+
3
+ export abstract class RouterWidget extends BaseRouterWidget {}
@@ -0,0 +1,2 @@
1
+ export * from './token';
2
+ export * from './RouterWidget';
@@ -0,0 +1,14 @@
1
+ import { Constructor } from '@oinone/kunlun-shared';
2
+ import { SPI, SPIOptions, SPISingleSelector, SPITokenFactory } from '@oinone/kunlun-spi';
3
+ import { VueWidget } from '@oinone/kunlun-vue-widget';
4
+
5
+ export interface BaseRouterOptions extends SPIOptions {
6
+ widget?: string;
7
+ }
8
+
9
+ @SPI.Base('Router', ['widget'])
10
+ export class BaseRouterWidget extends VueWidget {
11
+ public static Token: SPITokenFactory<BaseRouterOptions>;
12
+
13
+ public static Selector: SPISingleSelector<BaseRouterOptions, Constructor<BaseRouterWidget>>;
14
+ }
@@ -0,0 +1 @@
1
+ export * from './BaseRouterWidget';
@@ -0,0 +1,21 @@
1
+ import { getCurrentInstance } from 'vue';
2
+ import { Router } from '@oinone/kunlun-router';
3
+
4
+ // export type Router = Omit<ReturnType<typeof createRouter>, '_instance' | 'ignite' | 'activatedRoute'>;
5
+ export const useRouter = (): { router: Router } => {
6
+ const instance = getCurrentInstance();
7
+ if (!instance) {
8
+ throw new Error(`No vue instance in current component.`);
9
+ }
10
+ const router: any = instance.appContext.config.globalProperties.$router;
11
+
12
+ return { router };
13
+ };
14
+
15
+ /**
16
+ * 该方法只能在beforeCreated、created、mounted生命周期中调用才会生效。
17
+ * 如果想全局使用,请调用 @see {@link getRouterInstance}
18
+ */
19
+ export const getRouter = (): Router => {
20
+ return useRouter().router;
21
+ };
@@ -0,0 +1,38 @@
1
+ import { UrlSegmentGroup } from '@oinone/kunlun-router';
2
+ import { genToken } from '@oinone/kunlun-vue-widget';
3
+ import { computed, ComputedRef, inject, provide } from 'vue';
4
+ import { ACTIVATED_ROUTE_TOKEN } from '../token';
5
+
6
+ export const PARENT_SEGMENT_GROUP_TOKEN = genToken<ComputedRef<UrlSegmentGroup | undefined>>('parent_segment_group');
7
+
8
+ export const useSegmentGroup = (namespace?: string) => {
9
+ const activatedRoute = inject(ACTIVATED_ROUTE_TOKEN)!;
10
+ const parentSegmentGroup = inject(
11
+ PARENT_SEGMENT_GROUP_TOKEN,
12
+ computed(() => activatedRoute.value.root)
13
+ );
14
+
15
+ const currentSegmentGroupRef = computed(() => {
16
+ if (!parentSegmentGroup?.value) {
17
+ return;
18
+ }
19
+ const { children } = parentSegmentGroup.value;
20
+ return namespace ? children[namespace] : children.primary;
21
+ });
22
+
23
+ if (namespace) {
24
+ provide(PARENT_SEGMENT_GROUP_TOKEN, currentSegmentGroupRef);
25
+ }
26
+
27
+ // 如果没有 children 的话 SegmentGroup 信息会在当前 group 下
28
+ // 如果有 children,SegmentGroup 信息会被移到 children.primary 下
29
+ const currentSegmentGroup = computed(() => {
30
+ if (!currentSegmentGroupRef.value) {
31
+ return;
32
+ }
33
+ const { children } = currentSegmentGroupRef.value;
34
+ return Object.keys(children).length ? children.primary : currentSegmentGroupRef.value;
35
+ });
36
+
37
+ return { currentSegmentGroup };
38
+ };
package/src/index.ts ADDED
@@ -0,0 +1,9 @@
1
+ export * from './basic';
2
+ export * from './router';
3
+
4
+ export * from './Route';
5
+ export * from './Match';
6
+ export * from './Redirect';
7
+
8
+ export * from './helpers/useRouter';
9
+ export { useMatched } from '@oinone/kunlun-router';
package/src/router.ts ADDED
@@ -0,0 +1,36 @@
1
+ import { App, shallowRef, computed } from 'vue';
2
+ import { getRouterInstance, ActivatedRoute } from '@oinone/kunlun-router';
3
+
4
+ import { ACTIVATED_ROUTE_TOKEN } from './token';
5
+ import { Route } from './Route';
6
+ import { Match } from './Match';
7
+ import { Redirect } from './Redirect';
8
+
9
+ const createVueRouter = () => {
10
+ const router = getRouterInstance();
11
+ const currentRoute = shallowRef<ActivatedRoute | null>(null);
12
+
13
+ router.activatedRoute.subscribe((activatedRoute) => {
14
+ currentRoute.value = activatedRoute;
15
+ });
16
+
17
+ return {
18
+ install: (app: App) => {
19
+ if (app.config.globalProperties.$router) {
20
+ console.warn(`Already install vue router: `, app.config.globalProperties.$router);
21
+ return;
22
+ }
23
+ app.config.globalProperties.$router = router;
24
+ app.component('Route', Route);
25
+ app.component('Match', Match);
26
+ app.component('Redirect', Redirect);
27
+
28
+ const reactiveRoute = computed(() => currentRoute.value);
29
+ app.provide(ACTIVATED_ROUTE_TOKEN, reactiveRoute);
30
+
31
+ router.ignite();
32
+ }
33
+ };
34
+ };
35
+
36
+ export { createVueRouter };
package/src/token.ts ADDED
@@ -0,0 +1,10 @@
1
+ import { ComputedRef } from 'vue';
2
+ import { ActivatedRoute } from '@oinone/kunlun-router';
3
+
4
+ import { genToken } from '@oinone/kunlun-vue-widget';
5
+
6
+ const __DEV__ = process.env.NODE_ENV === 'development';
7
+
8
+ export const ACTIVATED_ROUTE_TOKEN = genToken<ComputedRef<ActivatedRoute>>(
9
+ __DEV__ ? 'router view location matched' : 'rvlm'
10
+ );
@@ -0,0 +1,47 @@
1
+ import { genToken, VueWidget, Widget } from '@oinone/kunlun-vue-widget';
2
+ import { inject, provide } from 'vue';
3
+
4
+ export interface Widgets {
5
+ [namespace: string]: VueWidget;
6
+ }
7
+
8
+ const ROOT_WIDGET_TOKEN = genToken<VueWidget>('root widget token');
9
+
10
+ const setRootWidget = (token: string): VueWidget => {
11
+ const rootWidget = Widget.select(token) as VueWidget;
12
+ provide(ROOT_WIDGET_TOKEN, rootWidget);
13
+ return rootWidget;
14
+ };
15
+
16
+ const getRootWidget = (): VueWidget | undefined => {
17
+ return inject(ROOT_WIDGET_TOKEN);
18
+ };
19
+
20
+ const registerWidgets = (widgets: Widgets): void => {
21
+ const rootWidget = getRootWidget();
22
+ if (!rootWidget) {
23
+ throw new Error(`Need a root widget in Match tag`);
24
+ }
25
+
26
+ (rootWidget as unknown as { children: Widget[] }).children.forEach((c) => c.dispose());
27
+
28
+ Object.entries(widgets).forEach(([k, w]) => {
29
+ if (k === 'default') {
30
+ rootWidget.createWidget(w);
31
+ }
32
+ rootWidget.createWidget(w, k);
33
+ rootWidget.forceUpdate();
34
+ });
35
+ };
36
+
37
+ export const useWidgetService = (): {
38
+ setRootWidget: typeof setRootWidget;
39
+ getRootWidget: typeof getRootWidget;
40
+ registerWidgets: typeof registerWidgets;
41
+ } => {
42
+ return {
43
+ setRootWidget,
44
+ getRootWidget,
45
+ registerWidgets
46
+ };
47
+ };