Commit e0039d25 authored by Sendya's avatar Sendya

fix: router-context

parent 9bdab4c1
import 'ant-design-vue/dist/antd.less'; import 'ant-design-vue/dist/antd.less';
import { createApp, defineComponent, reactive } from 'vue'; import { createApp, defineComponent, watch, ref } from 'vue';
import { RouterLink } from './mock-router'; import { RouterLink } from './mock-router';
import { Button, Avatar, message } from 'ant-design-vue'; import { Button, Avatar, message } from 'ant-design-vue';
import { default as ProLayout } from '../src/'; import { default as ProLayout } from '../src/';
...@@ -12,49 +12,54 @@ const BasicLayout = defineComponent({ ...@@ -12,49 +12,54 @@ const BasicLayout = defineComponent({
name: 'BasicLayout', name: 'BasicLayout',
inheritAttrs: false, inheritAttrs: false,
setup(_, { attrs }) { setup(_, { attrs }) {
const [menuState] = useMenuState({ const [ state, RouteContextProvider ] = createRouteContext({
collapsed: false, collapsed: false,
openKeys: [],
openKeys: ['/dashboard', '/form'],
onOpenKeys: (keys: string[]) => (state.openKeys = keys),
selectedKeys: ['/welcome'], selectedKeys: ['/welcome'],
}); onSelectedKeys: (keys: string[]) => (state.selectedKeys = keys),
const [ routeContext, RouteContextProvider ] = createRouteContext({
isMobile: false, isMobile: false,
menuData: [], fixSiderbar: false,
fixedHeader: false,
menuData: menus,
sideWidth: 208, sideWidth: 208,
hasSideMenu: true, hasSideMenu: true,
hasHeader: true, hasHeader: true,
hasFooterToolbar: false, hasFooterToolbar: false,
setHasFooterToolbar: (has: boolean) => (routeContext.hasFooterToolbar = has), setHasFooterToolbar: (has: boolean) => (state.hasFooterToolbar = has),
}); });
const cacheOpenKeys = ref<string[]>([]);
watch(
() => state.collapsed,
(collapsed: boolean) => {
if (collapsed) {
cacheOpenKeys.value = state.openKeys;
state.openKeys = [];
} else {
state.openKeys = cacheOpenKeys.value;
}
}
);
return () => ( return () => (
<RouteContextProvider> <RouteContextProvider>
<ProLayout <ProLayout
{...attrs} {...attrs}
v-model={[menuState.collapsed, 'collapsed']} v-model={[state.collapsed, 'collapsed']}
title={'Pro Layout'} title={'Pro Layout'}
layout={'mix'} layout={'side'}
theme={'light'}
navTheme={'dark'} navTheme={'dark'}
i18n={(key: string) => key} i18n={(key: string) => key}
isMobile={false} isMobile={state.isMobile}
menuData={menus} fixSiderbar={state.fixSiderbar}
matchMenuKeys={[]} fixedHeader={state.fixedHeader}
contentWidth={'Fixed'} contentWidth={'Fixed'}
primaryColor={'#1890ff'} primaryColor={'#1890ff'}
contentStyle={{ minHeight: '500px' }} contentStyle={{ minHeight: '500px' }}
siderWidth={208} siderWidth={state.sideWidth}
openKeys={menuState.openKeys}
selectedKeys={menuState.selectedKeys}
{...{
'onUpdate:openKeys':$event => {
$event && (menuState.openKeys = $event);
},
'onUpdate:selectedKeys': $event => {
$event && (menuState.selectedKeys = $event);
}
}}
v-slots={{ v-slots={{
rightContentRender: () => ( rightContentRender: () => (
<div style="color: #FFF;margin-right: 16px;"> <div style="color: #FFF;margin-right: 16px;">
...@@ -64,11 +69,8 @@ const BasicLayout = defineComponent({ ...@@ -64,11 +69,8 @@ const BasicLayout = defineComponent({
menuHeaderRender: () => ( menuHeaderRender: () => (
<a> <a>
<img src="https://gw.alipayobjects.com/zos/antfincdn/PmY%24TNNDBI/logo.svg" /> <img src="https://gw.alipayobjects.com/zos/antfincdn/PmY%24TNNDBI/logo.svg" />
{menuState.collapsed ? null : (<h1>Pro Layout</h1>)} {state.collapsed ? null : (<h1>Pro Layout</h1>)}
</a> </a>
),
footerRender: () => (
<div>123</div>
) )
}} }}
> >
......
...@@ -8,7 +8,7 @@ import { default as SiderMenuWrapper, SiderMenuWrapperProps } from './SiderMenu' ...@@ -8,7 +8,7 @@ import { default as SiderMenuWrapper, SiderMenuWrapperProps } from './SiderMenu'
import { WrapContent } from './WrapContent'; import { WrapContent } from './WrapContent';
import { default as Header, HeaderViewProps } from './Header'; import { default as Header, HeaderViewProps } from './Header';
import { RenderVNodeType, WithFalse } from './typings'; import { RenderVNodeType, WithFalse } from './typings';
import { getComponentOrSlot } from './utils'; import { getComponentOrSlot, PropRenderType, PropTypes } from './utils';
import useMergedState from './hooks/useMergedState'; import useMergedState from './hooks/useMergedState';
import './BasicLayout.less'; import './BasicLayout.less';
...@@ -141,8 +141,6 @@ const ProLayout: FunctionalComponent<BasicLayoutProps> = (props, { emit, slots, ...@@ -141,8 +141,6 @@ const ProLayout: FunctionalComponent<BasicLayoutProps> = (props, { emit, slots,
{ !isTop.value && (<SiderMenuWrapper { !isTop.value && (<SiderMenuWrapper
{...props} {...props}
menuHeaderRender={menuHeaderRenderFunc || (menuHeaderRenderSlot && (() => menuHeaderRenderSlot()))} menuHeaderRender={menuHeaderRenderFunc || (menuHeaderRenderSlot && (() => menuHeaderRenderSlot()))}
onSelect={handleSelect}
onOpenChange={handleOpenChange}
onCollapse={handleCollapse} onCollapse={handleCollapse}
/>)} />)}
<Layout> <Layout>
...@@ -150,35 +148,7 @@ const ProLayout: FunctionalComponent<BasicLayoutProps> = (props, { emit, slots, ...@@ -150,35 +148,7 @@ const ProLayout: FunctionalComponent<BasicLayoutProps> = (props, { emit, slots,
<WrapContent style={props.contentStyle}> <WrapContent style={props.contentStyle}>
{slots.default?.()} {slots.default?.()}
</WrapContent> </WrapContent>
{ footerRender && footerRender || footerRender !== false && ( { footerRender !== false && (footerRender && footerRender)}
<GlobalFooter
links={[
{
key: '1',
title: 'Pro Layout',
href: 'https://www.github.com/vueComponent/pro-layout',
blankTarget: true,
},
{
key: '2',
title: 'Github',
href: 'https://www.github.com/vueComponent/ant-design-vue-pro',
blankTarget: true,
},
{
key: '3',
title: '@Sendya',
href: 'https://www.github.com/sendya/',
blankTarget: true,
},
]}
copyright={
<a href="https://github.com/vueComponent" target="_blank">
vueComponent
</a>
}
/>
)}
</Layout> </Layout>
</Layout> </Layout>
</div> </div>
...@@ -191,61 +161,80 @@ ProLayout.inheritAttrs = false; ...@@ -191,61 +161,80 @@ ProLayout.inheritAttrs = false;
ProLayout.displayName = 'ProLayout'; ProLayout.displayName = 'ProLayout';
ProLayout.emits = ['update:collapsed', 'update:openKeys', 'update:selectedKeys']; ProLayout.emits = ['update:collapsed', 'update:openKeys', 'update:selectedKeys'];
ProLayout.props = { ProLayout.props = {
prefixCls: { prefixCls: PropTypes.string.def('ant-pro'),
type: String, title: PropTypes.VNodeChild.def('Ant Design Pro'),
default: 'ant-pro', logo: PropTypes.VNodeChild,
}, /* 是否删除掉所有的自带界面 */
title: String, pure: PropTypes.bool,
colSize: String, /* layout 的加载态 */
isChildrenLayout: Boolean, loading: PropTypes.bool,
isMobile: Boolean, /* 用于生成菜单和面包屑 请从 RouterContext 注入 */
fixSiderbar: { // menuData: PropTypes.array,
type: Boolean,
default: () => false, // location: PropTypes.string,
}, // Custom render
fixedHeader: { menuHeaderRender: PropRenderType,
type: Boolean, menuFooterRender: PropRenderType,
default: () => false, menuExtraRender: PropRenderType,
}, /* 自定义头的 render 方法 (props: BasicLayoutProps) => VNode */
layout: String, headerRender: PropRenderType,
openKeys: Array, /* 自定义头标题的方法,mix 模式下生效 (props: BasicLayoutProps) => VNode */
selectedKeys: Array, headerTitleRender: PropRenderType,
collapsed: Boolean, /* 自定义头内容的方法 (props: BasicLayoutProps) => VNode */
menuData: Array, headerContentRender: PropRenderType,
contentStyle: Object, /* 自定义头右部的 render 方法 (props: HeaderViewProps) => VNode */
theme: String, rightContentRender: PropRenderType,
headerTheme: { /* 自定义 collapsed button 的方法 (collapsed: boolean) => VNode */
type: String, collapsedButtonRender: PropRenderType,
defualt: 'light', /* 自定义页脚的 render 方法 (props: BasicLayoutProps) => VNode */
}, footerRender: PropRenderType,
navTheme: { /* 自定义页面标题的显示方法 (props: BasicLayoutProps) => VNode */
type: String, pageTitleRender: PropRenderType,
default: 'light', /* 自定义菜单的 render 方法 (props: HeaderViewProps) => VNode */
}, menuRender: PropRenderType,
headerRender: { /* 自定义菜单项的 render 方法 */
type: [Function, Boolean], menuItemRender: PropRenderType,
default: () => undefined, /* 自定义拥有子菜单菜单项的 render 方法 */
}, subMenuItemRender: PropRenderType,
footerRender: { /* 自定义面包屑的数据 */
type: [Function, Boolean], breadcrumbRender: PropRenderType,
default: () => undefined,
}, // Event
menuRender: { onMenuHeaderClick: PropTypes.func,
type: [Function, Boolean], onTopMixMenuHeaderClick: PropTypes.func,
default: () => undefined,
}, // settings
menuHeaderRender: { contentStyle: PropTypes.style,
type: [Function, Boolean], layout: PropTypes.string.def('side'),
default: () => undefined, contentWidth: PropTypes.string.def('Fluid'),
}, /* 导航的主题,side 和 mix 模式下是左侧菜单的主题,top 模式下是顶部菜单 */
rightContentRender: { navTheme: PropTypes.string.def('dark'),
type: [Function, Boolean], /* 顶部导航的主题,mix 模式生效 */
default: () => undefined, headerTheme: PropTypes.string.def('dark'),
}, /* 是否固定导航 */
rightContent: { fixSiderbar: PropTypes.bool,
type: [Function, Boolean], /* 是否固定 header 到顶部 */
default: () => undefined, fixedHeader: PropTypes.bool,
}, /* 触发响应式布局的断点 https://ant.design/components/grid-cn/#Col */
breakpoint: PropTypes.string.def('lg'),
/* 关于 menu 的配置,暂时只有 locale,locale 可以关闭 menu 的自带的全球化 */
menu: PropTypes.object,
/* 传递到 antd menu 组件的 props */
menuProps: PropTypes.object,
/* 使用 IconFont 的图标配置 */
iconfontUrl: PropTypes.string,
/* 当前 layout 的语言设置 */
locale: PropTypes.func.def((key: string) => key),
// settings
/* 侧边菜单宽度 */
siderWidth: PropTypes.number.def(208),
/* 控制菜单的收起和展开 */
collapsed: PropTypes.bool,
/* 菜单的折叠收起事件 (collapsed: boolean) => void */
onCollapse: PropTypes.func,
// onPageChange // 请使用 vue-router 监听
/* 禁止自动切换到移动页面 */
disableMobile: PropTypes.bool,
} as any; } as any;
export default withInstall(ProLayout); export default withInstall(ProLayout);
...@@ -6,6 +6,7 @@ import { TopNavHeader } from '../TopNavHeader'; ...@@ -6,6 +6,7 @@ import { TopNavHeader } from '../TopNavHeader';
import { clearMenuItem } from '../utils'; import { clearMenuItem } from '../utils';
import type { HeaderViewProps } from '../Header'; import type { HeaderViewProps } from '../Header';
import './index.less'; import './index.less';
import { useProProvider } from '../ProProvider';
export interface GlobalHeaderProps extends Partial<PureSettings> { export interface GlobalHeaderProps extends Partial<PureSettings> {
collapsed?: boolean; collapsed?: boolean;
...@@ -52,8 +53,10 @@ export const GlobalHeader: FunctionalComponent<GlobalHeaderProps & PrivateSiderM ...@@ -52,8 +53,10 @@ export const GlobalHeader: FunctionalComponent<GlobalHeaderProps & PrivateSiderM
headerTheme = 'dark', headerTheme = 'dark',
splitMenus, splitMenus,
menuData, menuData,
prefixCls, prefixCls: customPrefixCls,
} = props; } = props;
const { getPrefixCls } = useProProvider();
const prefixCls = customPrefixCls || getPrefixCls();
const baseClassName = computed(() => `${prefixCls}-global-header`); const baseClassName = computed(() => `${prefixCls}-global-header`);
const className = computed(() => { const className = computed(() => {
return { return {
...@@ -89,7 +92,7 @@ export const GlobalHeader: FunctionalComponent<GlobalHeaderProps & PrivateSiderM ...@@ -89,7 +92,7 @@ export const GlobalHeader: FunctionalComponent<GlobalHeaderProps & PrivateSiderM
{isMobile && renderLogo(menuHeaderRender, logoDom)} {isMobile && renderLogo(menuHeaderRender, logoDom)}
{isMobile && collapsedButtonRender && ( {isMobile && collapsedButtonRender && (
<span <span
class={`${baseClassName.value}-collapsed-button`} class={`${baseClassName.value}-collapsed-button`}
onClick={() => { onClick={() => {
if (onCollapse) { if (onCollapse) {
onCollapse(!collapsed); onCollapse(!collapsed);
......
import { InjectionKey } from 'vue'; import { InjectionKey, VNodeChild } from 'vue';
import { createContext, useContext } from './hooks/context'; import { createContext, useContext } from './hooks/context';
import { MenuDataItem } from './typings';
import { PureSettings } from './defaultSettings'; import { PureSettings } from './defaultSettings';
export interface Route {
path: string;
breadcrumbName: string;
children?: Omit<Route, 'children'>[];
}
export interface BreadcrumbProps {
prefixCls?: string;
routes?: Route[];
params?: any;
separator?: VNodeChild;
itemRender?: (route: Route, params: any, routes: Array<Route>, paths: Array<string>) => VNodeChild;
}
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;
}
export interface RouteContextProps extends Partial<PureSettings> { export interface RouteContextProps extends Partial<PureSettings>, MenuState {
breadcrumb?: any; breadcrumb?: BreadcrumbListReturn;
menuData?: any[]; menuData?: MenuDataItem[];
isMobile?: boolean; isMobile?: boolean;
prefixCls?: string; prefixCls?: string;
collapsed?: boolean; collapsed?: boolean;
...@@ -14,6 +36,8 @@ export interface RouteContextProps extends Partial<PureSettings> { ...@@ -14,6 +36,8 @@ export interface RouteContextProps extends Partial<PureSettings> {
hasFooterToolbar?: boolean; hasFooterToolbar?: boolean;
hasFooter?: boolean; hasFooter?: boolean;
setHasFooterToolbar?: (bool: boolean) => void; setHasFooterToolbar?: (bool: boolean) => void;
/* 附加属性 */
[key: string]: any;
} }
const routeContextInjectKey: InjectionKey<RouteContextProps> = Symbol(); const routeContextInjectKey: InjectionKey<RouteContextProps> = Symbol();
...@@ -21,4 +45,5 @@ const routeContextInjectKey: InjectionKey<RouteContextProps> = Symbol(); ...@@ -21,4 +45,5 @@ const routeContextInjectKey: InjectionKey<RouteContextProps> = Symbol();
export const createRouteContext = (context: RouteContextProps) => export const createRouteContext = (context: RouteContextProps) =>
createContext<RouteContextProps>(context, routeContextInjectKey); createContext<RouteContextProps>(context, routeContextInjectKey);
export const useRouteContext = () => useContext<RouteContextProps>(routeContextInjectKey); export const useRouteContext = () =>
useContext<RouteContextProps>(routeContextInjectKey);
...@@ -9,6 +9,7 @@ import { SiderProps } from './typings'; ...@@ -9,6 +9,7 @@ import { SiderProps } from './typings';
import { MenuUnfoldOutlined, MenuFoldOutlined } from '@ant-design/icons-vue'; import { MenuUnfoldOutlined, MenuFoldOutlined } from '@ant-design/icons-vue';
import { useProProvider } from '../ProProvider'; import { useProProvider } from '../ProProvider';
import './index.less'; import './index.less';
import { useRouteContext } from '../RouteContext';
const { Sider } = Layout; const { Sider } = Layout;
...@@ -34,8 +35,8 @@ export interface SiderMenuProps ...@@ -34,8 +35,8 @@ export interface SiderMenuProps
onMenuHeaderClick?: (e: MouseEvent) => void; onMenuHeaderClick?: (e: MouseEvent) => void;
fixed?: boolean; fixed?: boolean;
hide?: boolean; hide?: boolean;
onOpenChange?: (openKeys: WithFalse<string[]>) => void; // onOpenChange?: (openKeys: WithFalse<string[]>) => void;
onSelect?: (selectedKeys: WithFalse<string[]>) => void; // onSelect?: (selectedKeys: WithFalse<string[]>) => void;
} }
export const defaultRenderLogo = (logo: RenderVNodeType): RenderVNodeType => { export const defaultRenderLogo = (logo: RenderVNodeType): RenderVNodeType => {
...@@ -84,12 +85,10 @@ export const defaultRenderCollapsedButton = (collapsed?: boolean): RenderVNodeTy ...@@ -84,12 +85,10 @@ export const defaultRenderCollapsedButton = (collapsed?: boolean): RenderVNodeTy
const SiderMenu: FunctionalComponent<SiderMenuProps> = (props: SiderMenuProps) => { const SiderMenu: FunctionalComponent<SiderMenuProps> = (props: SiderMenuProps) => {
const { const {
theme, navTheme,
menuData, // menuData,
collapsed, collapsed,
siderWidth, siderWidth,
onOpenChange,
onSelect,
onCollapse, onCollapse,
breakpoint, breakpoint,
collapsedWidth = 48, collapsedWidth = 48,
...@@ -99,42 +98,45 @@ const SiderMenu: FunctionalComponent<SiderMenuProps> = (props: SiderMenuProps) = ...@@ -99,42 +98,45 @@ const SiderMenu: FunctionalComponent<SiderMenuProps> = (props: SiderMenuProps) =
collapsedButtonRender = defaultRenderCollapsedButton, collapsedButtonRender = defaultRenderCollapsedButton,
} = props; } = props;
const { getPrefixCls } = useProProvider(); const { getPrefixCls } = useProProvider();
const context = useRouteContext();
const baseClassName = getPrefixCls('sider'); const baseClassName = getPrefixCls('sider');
// const isMix = computed(() => props.layout === 'mix'); // const isMix = computed(() => props.layout === 'mix');
const fixed = computed(() => props.fixed); // const fixed = computed(() => context.fixSiderbar);
// const runtimeTheme = computed(() => (props.layout === 'mix' && 'light') || 'dark'); // const runtimeTheme = computed(() => (props.layout === 'mix' && 'light') || 'dark');
const runtimeSideWidth = computed(() => const runtimeSideWidth = computed(() =>
props.collapsed ? props.collapsedWidth : props.siderWidth, props.collapsed ? props.collapsedWidth : props.siderWidth,
); );
const classNames = ref({ const classNames = computed(() => {
[baseClassName]: true, return {
[`${baseClassName}-${theme}`]: true, [baseClassName]: true,
[`${baseClassName}-${props.layout}`]: true, [`${baseClassName}-${navTheme}`]: true,
[`${baseClassName}-fixed`]: fixed, [`${baseClassName}-${props.layout}`]: true,
[`${baseClassName}-fixed`]: context.fixSiderbar,
}
}); });
// call menuHeaderRender // call menuHeaderRender
const headerDom = defaultRenderLogoAndTitle(props); const headerDom = defaultRenderLogoAndTitle(props);
const extraDom = menuExtraRender && menuExtraRender(props); const extraDom = menuExtraRender && menuExtraRender(props);
const defaultMenuDom = ( const defaultMenuDom = (
<BaseMenu <BaseMenu
menuData={menuData} theme={props.navTheme === 'realDark' ? 'dark' : props.navTheme}
theme={props.theme === 'realDark' ? 'dark' : props.theme}
mode="inline" mode="inline"
menuData={context.menuData}
collapsed={props.collapsed} collapsed={props.collapsed}
openKeys={props.openKeys} openKeys={context.openKeys}
selectedKeys={props.selectedKeys} selectedKeys={context.selectedKeys}
style={{ style={{
width: '100%', width: '100%',
}} }}
class={`${baseClassName}-menu`} class={`${baseClassName}-menu`}
{...{ {...{
'onUpdate:openKeys': ($event: any) => { 'onUpdate:openKeys': ($event: string[]) => {
onOpenChange && onOpenChange($event); context.onOpenKeys($event);
}, },
'onUpdate:selectedKeys': ($event: any) => { 'onUpdate:selectedKeys': ($event: string[]) => {
onSelect && onSelect($event); context.onSelectedKeys($event);
}, },
}} }}
/> />
...@@ -142,7 +144,7 @@ const SiderMenu: FunctionalComponent<SiderMenuProps> = (props: SiderMenuProps) = ...@@ -142,7 +144,7 @@ const SiderMenu: FunctionalComponent<SiderMenuProps> = (props: SiderMenuProps) =
return ( return (
<> <>
{fixed.value && ( {context.fixSiderbar && (
<div <div
style={{ style={{
width: `${runtimeSideWidth.value}px`, width: `${runtimeSideWidth.value}px`,
...@@ -174,7 +176,7 @@ const SiderMenu: FunctionalComponent<SiderMenuProps> = (props: SiderMenuProps) = ...@@ -174,7 +176,7 @@ const SiderMenu: FunctionalComponent<SiderMenuProps> = (props: SiderMenuProps) =
<Menu <Menu
class={`${baseClassName}-link-menu`} class={`${baseClassName}-link-menu`}
inlineIndent={16} inlineIndent={16}
theme={theme} theme={navTheme as 'light' | 'dark'}
selectedKeys={[]} selectedKeys={[]}
openKeys={[]} openKeys={[]}
mode="inline" mode="inline"
......
...@@ -9,6 +9,7 @@ import { GlobalHeaderProps } from '../GlobalHeader'; ...@@ -9,6 +9,7 @@ import { GlobalHeaderProps } from '../GlobalHeader';
import { default as ResizeObserver } from 'ant-design-vue/es/vc-resize-observer'; import { default as ResizeObserver } from 'ant-design-vue/es/vc-resize-observer';
import './index.less'; import './index.less';
import { useRouteContext } from "../RouteContext";
export type TopNavHeaderProps = SiderMenuProps & GlobalHeaderProps & PrivateSiderMenuProps & {}; export type TopNavHeaderProps = SiderMenuProps & GlobalHeaderProps & PrivateSiderMenuProps & {};
...@@ -52,10 +53,9 @@ export const TopNavHeader: FunctionalComponent<TopNavHeaderProps> = (props, { em ...@@ -52,10 +53,9 @@ export const TopNavHeader: FunctionalComponent<TopNavHeaderProps> = (props, { em
contentWidth, contentWidth,
rightContentRender, rightContentRender,
layout, layout,
onOpenChange,
onSelect,
...restProps ...restProps
} = props; } = props;
const context = useRouteContext();
const prefixCls = `${propPrefixCls || 'ant-pro'}-top-nav-header`; const prefixCls = `${propPrefixCls || 'ant-pro'}-top-nav-header`;
const headerDom = defaultRenderLogoAndTitle( const headerDom = defaultRenderLogoAndTitle(
{ ...props, collapsed: false }, { ...props, collapsed: false },
...@@ -79,14 +79,19 @@ export const TopNavHeader: FunctionalComponent<TopNavHeaderProps> = (props, { em ...@@ -79,14 +79,19 @@ export const TopNavHeader: FunctionalComponent<TopNavHeaderProps> = (props, { em
)} )}
<div style={{ flex: 1 }} class={`${prefixCls}-menu`}> <div style={{ flex: 1 }} class={`${prefixCls}-menu`}>
<BaseMenu <BaseMenu
{...restProps} theme={props.theme === 'realDark' ? 'dark' : props.theme}
mode={props.mode}
collapsed={props.collapsed}
menuData={context.menuData}
openKeys={context.openKeys}
selectedKeys={context.selectedKeys}
class={{ 'top-nav-menu': props.mode === 'horizontal' }} class={{ 'top-nav-menu': props.mode === 'horizontal' }}
{...{ {...{
'onUpdate:openKeys': ($event: any) => { 'onUpdate:openKeys': ($event: string[]) => {
onOpenChange && onOpenChange($event); context.onOpenKeys($event);
}, },
'onUpdate:selectedKeys': ($event: any) => { 'onUpdate:selectedKeys': ($event: any) => {
onSelect && onSelect($event); context.onSelectedKeys($event);
}, },
}} }}
/> />
......
...@@ -52,11 +52,9 @@ export interface MenuDataItem { ...@@ -52,11 +52,9 @@ export interface MenuDataItem {
/** /**
* @name 用于标定选中的值,默认是 path * @name 用于标定选中的值,默认是 path
*/ */
key?: string | symbol;
path: string; path: string;
name?: string | symbol; name?: string | symbol;
meta?: MetaRecord; meta?: MetaRecord;
hidden?: boolean;
/** /**
* @name 子菜单 * @name 子菜单
*/ */
......
import { Slots, VNodeChild } from 'vue'; import { Slots, VNodeChild } from 'vue';
import { MenuDataItem } from '../typings'; import { MenuDataItem } from '../typings';
export { getComponent } from 'ant-design-vue/es/_util/props-util'; export { getComponent } from 'ant-design-vue/es/_util/props-util';
export { default as PropTypes } from 'ant-design-vue/es/_util/vue-types';
export { default as isUrl } from './isUrl'; export { default as isUrl } from './isUrl';
export { default as isImg } from './isImg'; export { default as isImg } from './isImg';
...@@ -48,6 +49,11 @@ export function clearMenuItem(menusData: MenuDataItem[]): MenuDataItem[] { ...@@ -48,6 +49,11 @@ export function clearMenuItem(menusData: MenuDataItem[]): MenuDataItem[] {
.filter(item => item) as MenuDataItem[]; .filter(item => item) as MenuDataItem[];
} }
export const PropRenderType = {
type: [Function, Boolean],
default: () => undefined,
};
export interface Attrs { export interface Attrs {
[key: string]: string; [key: string]: string;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment