Skip to content

Commit

Permalink
refactor: route context
Browse files Browse the repository at this point in the history
  • Loading branch information
sendya committed Dec 16, 2020
1 parent dfab7a6 commit a7380c6
Show file tree
Hide file tree
Showing 9 changed files with 201 additions and 99 deletions.
14 changes: 14 additions & 0 deletions examples/demoBox.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.browser-nav {
padding: 2px 6px;
background-color: #ebedf1;

&::before {
content: '';
display: inline-block;
width: 12px;
height: 12px;
border-radius: 50%;
background-color: #fd6458;
box-shadow: 20px 0 0 #ffbf2b, 40px 0 0 #24cc3d;
}
}
64 changes: 64 additions & 0 deletions examples/demoBox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { createApp, defineComponent, ref, h, onMounted } from 'vue';
import { RouterLink } from './mock-router';
import * as Icon from '@ant-design/icons-vue';
import './demoBox.less';

export const DemoBox = defineComponent({
setup(_, { slots }) {
const instance = ref();
const frameRef = ref();

const content = (): void => {
const children = slots?.default();
console.log('frameRef.value', frameRef.value);
const body = frameRef.value.contentDocument.body;
const head = frameRef.value.contentDocument.head;
const el = document.createElement('div');
el.className = 'demoBox'
body.appendChild(el);

// const styleLink = document.createElement('link');
// styleLink.rel = 'stylesheet';
// styleLink.type = 'text/css';
// styleLink.href = './index.css';
head.innerHTML = `
<link href="/node_modules/normalize.css/normalize.css" type="text/css" rel="stylesheet">
<link href="./index.css" type="text/css" rel="stylesheet">
`

const box = createApp({
render() {
return children;
},
}).use(RouterLink);

const filterIcons = ['default', 'createFromIconfontCN', 'getTwoToneColor', 'setTwoToneColor'];
Object.keys(Icon)
.filter(k => !filterIcons.includes(k))
.forEach(k => {
box.component(Icon[k].displayName, Icon[k]);
});

box.mount(el);

instance.value = box;
}

onMounted(() => {
content();
})
return {
frameRef,
content,
}
},
render () {
return (
<div class="browser-mockup with-url">
<div class="browser-nav">
</div>
<iframe ref="frameRef" height="450px" width="100%" style="border: 0;" />
</div>
)
}
});
27 changes: 15 additions & 12 deletions examples/index.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
import 'ant-design-vue/dist/antd.less';
import { createApp, defineComponent, watch, ref } from 'vue';
import { createApp, defineComponent, onMounted, watch, ref, reactive } from 'vue';
import { RouterLink } from './mock-router';
import { Button, Avatar, message } from 'ant-design-vue';
import { default as ProLayout } from '../src/';
import { menus } from './menus';
import * as Icon from '@ant-design/icons-vue';
import { createRouteContext } from '../src/RouteContext';
import { createRouteContext, RouteContextProps } from '../src/RouteContext';
import { DemoBox } from './demoBox';

const BasicLayout = defineComponent({
name: 'BasicLayout',
inheritAttrs: false,
setup(_, { attrs }) {
const [ state, RouteContextProvider ] = createRouteContext({
setup() {
const state = reactive<RouteContextProps>({
collapsed: false,

openKeys: ['/dashboard', '/form'],
onOpenKeys: (keys: string[]) => (state.openKeys = keys),
openKeys: ['/dashboard'],
setOpenKeys: (keys: string[]) => (state.openKeys = keys),
selectedKeys: ['/welcome'],
onSelectedKeys: (keys: string[]) => (state.selectedKeys = keys),
setSelectedKeys: (keys: string[]) => (state.selectedKeys = keys),

isMobile: false,
fixSiderbar: false,
Expand All @@ -28,7 +29,8 @@ const BasicLayout = defineComponent({
hasHeader: true,
hasFooterToolbar: false,
setHasFooterToolbar: (has: boolean) => (state.hasFooterToolbar = has),
});
})
const [ RouteContextProvider ] = createRouteContext();

const cacheOpenKeys = ref<string[]>([]);
watch(
Expand All @@ -44,9 +46,8 @@ const BasicLayout = defineComponent({
);

return () => (
<RouteContextProvider>
<RouteContextProvider value={state}>
<ProLayout
{...attrs}
v-model={[state.collapsed, 'collapsed']}
title={'Pro Layout'}
layout={'side'}
Expand All @@ -57,7 +58,7 @@ const BasicLayout = defineComponent({
fixedHeader={state.fixedHeader}
contentWidth={'Fixed'}
primaryColor={'#1890ff'}
contentStyle={{ minHeight: '500px' }}
contentStyle={{ minHeight: '200px' }}
siderWidth={state.sideWidth}
v-slots={{
rightContentRender: () => (
Expand Down Expand Up @@ -91,7 +92,9 @@ const SimpleDemo = {
return () => (
<div class="components">
<h2># BasicLayout</h2>
<BasicLayout />
<DemoBox>
<BasicLayout />
</DemoBox>
</div>
);
},
Expand Down
23 changes: 12 additions & 11 deletions examples/route-context.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createApp, defineComponent, ref, reactive, toRaw, onMounted } from 'vue';
import { Card, Space, Button } from 'ant-design-vue';
import { createRouteContext, useRouteContext } from '../src/RouteContext';
import { createRouteContext, useRouteContext, RouteContextProps } from '../src/RouteContext';

import 'ant-design-vue/dist/antd.less';

Expand All @@ -9,14 +9,15 @@ const DemoComponent = {
const state = reactive({
name: 'value',
});

const [ routeContext, RouteContextProvider ] = createRouteContext({
hasSideMenu: true,
collapsed: true,
isMobile: false,
menuData: []
const context = reactive<RouteContextProps>({
menuData: [],
selectedKeys: [],
openKeys: [],
collapsed: false,
});

const [ RouteContextProvider ] = createRouteContext();

return () => (
<div class="components">
<h2># Template</h2>
Expand All @@ -26,8 +27,8 @@ const DemoComponent = {
type="primary"
onClick={() => {
state.name = new Date().getTime().toString()
routeContext.collapsed = !routeContext.collapsed
routeContext.menuData = [
context.collapsed = !context.collapsed
context.menuData = [
{
path: `/dashboard/${state.name}`,
name: `${state.name}`,
Expand All @@ -42,11 +43,11 @@ const DemoComponent = {
<div style={{ margin: '12px 0' }}>
<p>state.name: { JSON.stringify(state.name) }</p>
routeContext:
<pre>{ JSON.stringify(routeContext, null, 4) }</pre>
<pre>{ JSON.stringify(context, null, 4) }</pre>
</div>
</Card>
<div class="demo" style="background: rgb(244,244,244);">
<RouteContextProvider>
<RouteContextProvider value={context}>
<TestChildComponent />
</RouteContextProvider>
</div>
Expand Down
118 changes: 68 additions & 50 deletions examples/side-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,76 +4,94 @@ import 'ant-design-vue/dist/antd.less';
import './side-menu.less';
import { Layout, Input, Space, Switch, message } from 'ant-design-vue';
import { menus } from './menus';
import { RouterLink } from './mock-router';
import { default as SiderMenuWrapper } from '../src/SiderMenu';
import { useMenu } from '../src/hooks/useMenu';
import { createRouteContext, RouteContextProps } from '../src/RouteContext';
import * as Icon from '@ant-design/icons-vue';
import { MenuTheme } from '../src/typings';

const DemoComponent = {
setup() {
const [menuState] = useMenu({
const state = reactive<RouteContextProps>({
collapsed: false,
openKeys: [''],

openKeys: ['/dashboard', '/form'],
setOpenKeys: (keys: string[]) => (state.openKeys = keys),
selectedKeys: ['/welcome'],
});
const state = reactive({
setSelectedKeys: (keys: string[]) => (state.selectedKeys = keys),

isMobile: false,
fixSiderbar: false,
fixedHeader: false,
menuData: [...menus],
sideWidth: 208,
hasSideMenu: true,
hasHeader: true,
hasFooterToolbar: false,
setHasFooterToolbar: (has: boolean) => (state.hasFooterToolbar = has),
})
const [ RouteContextProvider ] = createRouteContext();

const myState = reactive({
theme: 'light',
});
const handleCollapse = (collapsed: boolean) => {
menuState.collapsed = collapsed;
state.collapsed = collapsed;
}
return () => (
<div class="components">
<h2># SideMenu</h2>
<div>
<div style="margin: 16px;">
<Space>
<Switch checked-children="dark" un-checked-children="light" checked={state.theme === 'dark'} onChange={() => { (state.theme = state.theme === 'dark' ? 'light' : 'dark')}} />
<Switch checked-children="dark" un-checked-children="light" checked={state.theme === 'dark'} onChange={() => { (myState.theme = myState.theme === 'dark' ? 'light' : 'dark')}} />
</Space>
</div>
<div class="demo" style="background: rgb(244,244,244); min-height: 400px;">
<div class="container side-menu-demo">
<Layout class="ant-pro-basicLayout">
<SiderMenuWrapper
title={'Pro Layout'}
layout={'side'}
theme={state.theme as MenuTheme}
isMobile={false}
collapsed={menuState.collapsed}
menuData={menus}
// openKeys={menuState.openKeys}
// selectedKeys={menuState.selectedKeys}
onCollapse={handleCollapse}
matchMenuKeys={[]}
contentWidth={'Fixed'}
primaryColor={'#1890ff'}
siderWidth={208}
menuExtraRender={(props) => !props.collapsed ? (
<div>
<Input.Search placeholder="Search.." style={{ width: '100%' }} onSearch={(value: string) => {
message.info(`Search click: ${value}`)
}} />
</div>
) : null}
// menuFooterRender={(props) => props.collapsed ? undefined : (
// <div style="color: #fff; padding: 8px 16px; overflow: hidden;">
// <span>自定义页脚</span>
// </div>
// )}
/>
<Layout>
<Layout.Header style="background: #fff; padding: 0; height: 48px; line-height: 48px;"></Layout.Header>
<Layout.Content
style={{
margin: '24px 16px',
padding: '24px',
background: '#fff',
minHeight: '280px',
}}
>
<div>Context</div>
</Layout.Content>
<RouteContextProvider value={state}>
<Layout class="ant-pro-basicLayout">
<SiderMenuWrapper
title={'Pro Layout'}
layout={'side'}
navTheme={myState.theme as MenuTheme}
isMobile={false}
collapsed={state.collapsed}
// openKeys={menuState.openKeys}
// selectedKeys={menuState.selectedKeys}
onCollapse={handleCollapse}
matchMenuKeys={[]}
contentWidth={'Fixed'}
primaryColor={'#1890ff'}
siderWidth={208}
menuExtraRender={(props) => !props.collapsed ? (
<div>
<Input.Search placeholder="Search.." style={{ width: '100%' }} onSearch={(value: string) => {
message.info(`Search click: ${value}`)
}} />
</div>
) : null}
// menuFooterRender={(props) => props.collapsed ? undefined : (
// <div style="color: #fff; padding: 8px 16px; overflow: hidden;">
// <span>自定义页脚</span>
// </div>
// )}
/>
<Layout>
<Layout.Header style="background: #fff; padding: 0; height: 48px; line-height: 48px;"></Layout.Header>
<Layout.Content
style={{
margin: '24px 16px',
padding: '24px',
background: '#fff',
minHeight: '280px',
}}
>
<div>Context</div>
</Layout.Content>
</Layout>
</Layout>
</Layout>
</RouteContextProvider>

</div>
</div>
</div>
Expand All @@ -90,4 +108,4 @@ Object.keys(Icon)
app.component(Icon[k].displayName, Icon[k]);
});

app.mount('#__vue-content>div');
app.use(RouterLink).mount('#__vue-content>div');
14 changes: 8 additions & 6 deletions src/RouteContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ import { InjectionKey, VNodeChild } from 'vue';
import { createContext, useContext } from './hooks/context';
import { MenuDataItem } from './typings';
import { PureSettings } from './defaultSettings';

export interface Route {
path: string;
breadcrumbName: string;
children?: Omit<Route, 'children'>[];
}

export interface BreadcrumbProps {
prefixCls?: string;
routes?: Route[];
Expand All @@ -18,10 +20,10 @@ export interface BreadcrumbProps {
export type BreadcrumbListReturn = Pick<BreadcrumbProps, Extract<keyof BreadcrumbProps, 'routes' | 'itemRender'>>;

export interface MenuState {
selectedKeys?: string[];
openKeys?: string[];
onSelectedKeys: (key: string[]) => void;
onOpenKeys: (key: string[]) => void;
selectedKeys: string[];
openKeys: string[];
setSelectedKeys?: (key: string[]) => void;
setOpenKeys?: (key: string[]) => void;
}

export interface RouteContextProps extends Partial<PureSettings>, MenuState {
Expand All @@ -42,8 +44,8 @@ export interface RouteContextProps extends Partial<PureSettings>, MenuState {

const routeContextInjectKey: InjectionKey<RouteContextProps> = Symbol();

export const createRouteContext = (context: RouteContextProps) =>
createContext<RouteContextProps>(context, routeContextInjectKey);
export const createRouteContext = () =>
createContext<RouteContextProps>(routeContextInjectKey);

export const useRouteContext = () =>
useContext<RouteContextProps>(routeContextInjectKey);
Loading

0 comments on commit a7380c6

Please sign in to comment.