Skip to content

Commit 5bddea7

Browse files
committed
fix: Menu, BasicLayout, VNodeType
1 parent ec3c712 commit 5bddea7

File tree

16 files changed

+243
-105
lines changed

16 files changed

+243
-105
lines changed

README.md

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ Ant Design Pro Layout
1313

1414
```bash
1515
# yarn
16-
yarn add @ant-design-vue/pro-layout
16+
yarn add @ant-design-vue/pro-layout@next
1717
# npm
18-
npm i @ant-design-vue/pro-layout -S
18+
npm i @ant-design-vue/pro-layout@next -S
1919
```
2020

2121
## Basic Usage
@@ -46,7 +46,7 @@ After that, you can use pro-layout in your Vue components as simply as this:
4646
4747
<script>
4848
import { defineComponent, reactive } from 'vue';
49-
import ProLayout, { createRouteContext } from '@ant-design-vue/pro-layout';
49+
import { createRouteContext } from '@ant-design-vue/pro-layout';
5050
5151
const [ RouteContextProvider ] = createRouteContext();
5252
@@ -56,9 +56,7 @@ export default defineComponent({
5656
collapsed: false,
5757
5858
openKeys: ['/dashboard'],
59-
setOpenKeys: (keys) => (state.openKeys = keys),
6059
selectedKeys: ['/welcome'],
61-
setSelectedKeys: (keys) => (state.selectedKeys = keys),
6260
6361
isMobile: false,
6462
fixSiderbar: false,
@@ -76,7 +74,6 @@ export default defineComponent({
7674
}
7775
},
7876
components: {
79-
ProLayout,
8077
RouteContextProvider,
8178
}
8279
});
@@ -95,9 +92,7 @@ export default defineComponent({
9592
collapsed: false,
9693

9794
openKeys: ['/dashboard'],
98-
setOpenKeys: (keys: string[]) => (state.openKeys = keys),
9995
selectedKeys: ['/welcome'],
100-
setSelectedKeys: (keys: string[]) => (state.selectedKeys = keys),
10196

10297
isMobile: false,
10398
fixSiderbar: false,

babel.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module.exports = {
33
test: {
44
presets: [['@babel/preset-env', { targets: { node: true } }]],
55
plugins: [
6-
'@vue/babel-plugin-jsx',
6+
['@vue/babel-plugin-jsx', { mergeProps: false }],
77
'@babel/plugin-proposal-optional-chaining',
88
'@babel/plugin-transform-object-assign',
99
'@babel/plugin-proposal-object-rest-spread',

examples/menus.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
import { RouteProps } from '../src/typings';
2-
3-
export const menus: RouteProps[] = [
1+
export const menus = [
42
{
53
path: '/welcome',
64
name: 'welcome',

examples/test.html

Whitespace-only changes.

examples/test.tsx

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { createApp, reactive } from 'vue';
2+
import { default as ProLayout, createRouteContext, RouteContextProps } from '../src/';
3+
4+
import { RouterLink } from './mock-router';
5+
import { menus } from './menus';
6+
import registerIcons from './_util/icons';
7+
8+
const SimpleDemo = {
9+
setup() {
10+
const [RouteContextProvider] = createRouteContext();
11+
12+
const appState = reactive<RouteContextProps>({
13+
selectedKeys: [],
14+
openKeys: [],
15+
collapsed: true,
16+
menuData: menus,
17+
});
18+
return () => (
19+
<RouteContextProvider value={appState}>
20+
<ProLayout
21+
title="Pro Tests"
22+
logo="https://alicdn.antdv.com/v2/assets/logo.1ef800a8.svg"
23+
layout="side"
24+
navTheme="light"
25+
contentWidth="Fluid"
26+
contentStyle={{ minHeight: '300px' }}
27+
collapsed={appState.collapsed}
28+
onCollapse={collapsed => {
29+
appState.collapsed = collapsed;
30+
}}
31+
onSelect={(selectedKeys: string[] | false) => {
32+
selectedKeys && (appState.selectedKeys = selectedKeys);
33+
}}
34+
onOpenKeys={(openKeys: string[] | false) => {
35+
console.log('onOpenKeys', openKeys);
36+
openKeys && (appState.openKeys = openKeys);
37+
}}
38+
footerRender={() => <div>custom-footer</div>}
39+
v-slots={{
40+
rightContentRender: props => (
41+
<div class="custom-header-right-content">
42+
<span>custom-right-content</span>
43+
</div>
44+
),
45+
}}
46+
>
47+
<div>content</div>
48+
</ProLayout>
49+
</RouteContextProvider>
50+
);
51+
},
52+
};
53+
54+
const app = createApp(SimpleDemo);
55+
56+
app.use(ProLayout);
57+
app.use(RouterLink);
58+
app.use(registerIcons);
59+
app.mount('#__vue-content>div');

src/BasicLayout.tsx

Lines changed: 36 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
import { computed, FunctionalComponent, CSSProperties, VNodeChild, VNode, unref } from 'vue';
1+
import { computed, FunctionalComponent, CSSProperties, unref } from 'vue';
22
import 'ant-design-vue/es/layout/style';
33
import Layout from 'ant-design-vue/es/layout';
44
import { withInstall } from 'ant-design-vue/es/_util/type';
55
import { default as ProProvider, ProProviderData } from './ProProvider';
66
import { default as SiderMenuWrapper, SiderMenuWrapperProps } from './SiderMenu';
77
import { WrapContent } from './WrapContent';
88
import { default as Header, HeaderViewProps } from './Header';
9-
import { RenderVNodeType, WithFalse } from './typings';
10-
import { getComponentOrSlot, PropRenderType, PropTypes } from './utils';
9+
import { VNodeType, CustomRender, WithFalse } from './typings';
10+
import { getCustomRender, PropRenderType, PropTypes } from './utils';
1111
import useMediaQuery from './hooks/useMediaQuery';
1212
import './BasicLayout.less';
1313

@@ -19,7 +19,7 @@ export type BasicLayoutProps = SiderMenuWrapperProps &
1919
/**
2020
*@name logo url
2121
*/
22-
logo?: string | RenderVNodeType | WithFalse<string | RenderVNodeType>;
22+
logo?: VNodeType;
2323

2424
loading?: boolean;
2525

@@ -29,11 +29,9 @@ export type BasicLayoutProps = SiderMenuWrapperProps &
2929

3030
onCollapse?: (collapsed: boolean) => void;
3131

32-
footerRender?: WithFalse<
33-
(props: any /* FooterProps */, defaultDom: RenderVNodeType) => RenderVNodeType
34-
>;
32+
footerRender?: WithFalse<(props: any /* FooterProps */) => VNodeType>;
3533

36-
headerRender?: WithFalse<(props: any /* HeaderProps */) => RenderVNodeType>;
34+
headerRender?: WithFalse<(props: any /* HeaderProps */) => VNodeType>;
3735

3836
colSize?: string;
3937
/**
@@ -68,19 +66,16 @@ const ProLayout: FunctionalComponent<BasicLayoutProps> = (props, { emit, slots }
6866
const isTop = computed(() => layout === 'top');
6967
// const isSide = computed(() => layout === 'side');
7068
// const isMix = computed(() => layout === 'mix');
71-
72-
const handleCollapse = (collapsed: boolean) => {
73-
propsOnCollapse && propsOnCollapse(collapsed);
74-
emit('update:collapsed', collapsed);
75-
};
76-
const handleOpenKeys = (openKeys: string[] | false): void => {
77-
propsOnOpenKeys && propsOnOpenKeys(openKeys);
78-
emit('update:open-keys', openKeys);
79-
};
80-
const handleSelect = (selectedKeys: string[] | false): void => {
81-
propsOnSelect && propsOnSelect(selectedKeys);
82-
emit('update:selected-keys', selectedKeys);
83-
};
69+
// if on event and @event
70+
const onCollapse =
71+
(propsOnCollapse && propsOnCollapse) ||
72+
((collapsed: boolean) => emit('update:collapsed', collapsed));
73+
const onOpenKeys =
74+
(propsOnOpenKeys && propsOnOpenKeys) ||
75+
((openKeys: string[] | false) => emit('update:open-keys', openKeys));
76+
const onSelect =
77+
(propsOnSelect && propsOnSelect) ||
78+
((selectedKeys: string[] | false) => emit('update:selected-keys', selectedKeys));
8479
const colSize = useMediaQuery();
8580
const isMobile = computed(
8681
() => (colSize.value === 'sm' || colSize.value === 'xs') && !props.disableMobile,
@@ -115,42 +110,39 @@ const ProLayout: FunctionalComponent<BasicLayoutProps> = (props, { emit, slots }
115110
const headerRender = (
116111
props: BasicLayoutProps & {
117112
hasSiderMenu: boolean;
118-
customHeaderRender: VNodeChild | false;
119-
rightContentRender: VNodeChild | VNode | false;
113+
customHeaderRender: WithFalse<CustomRender>;
114+
rightContentRender: WithFalse<CustomRender>;
120115
},
121116
matchMenuKeys: string[],
122-
): RenderVNodeType => {
117+
): VNodeType => {
123118
if (props.headerRender === false || props.pure) {
124119
return null;
125120
}
126121
return <Header matchMenuKeys={matchMenuKeys} {...props} headerHeight={48} />;
127122
};
128-
const rightContentRender = getComponentOrSlot(props, slots, 'rightContentRender') as any;
129-
const customHeaderRender = getComponentOrSlot(props, slots, 'headerRender');
130-
const menuHeaderRenderFunc = props['menuHeaderRender'];
131-
const menuHeaderRenderSlot = slots['menuHeaderRender'];
123+
const rightContentRender = getCustomRender(props, slots, 'rightContentRender');
124+
const customHeaderRender = getCustomRender(props, slots, 'headerRender');
125+
const menuHeaderRender = getCustomRender(props, slots, 'menuHeaderRender');
126+
const footerRender = getCustomRender(props, slots, 'footerRender');
127+
// const menuRender = getCustomRender(props, slots, 'menuRender');
128+
132129
const headerDom = headerRender(
133130
{
134131
...props,
135132
hasSiderMenu: !isTop.value,
136133
menuData,
137134
isMobile: unref(isMobile),
138-
onCollapse: handleCollapse,
139-
onSelect: handleSelect,
140-
onOpenKeys: handleOpenKeys,
135+
onCollapse,
136+
onOpenKeys,
137+
onSelect,
141138
customHeaderRender,
142139
rightContentRender,
143-
headerTitleRender:
144-
menuHeaderRenderFunc || (menuHeaderRenderSlot && (() => menuHeaderRenderSlot())),
140+
headerTitleRender: menuHeaderRender,
145141
theme: (navTheme || 'dark').toLocaleLowerCase().includes('dark') ? 'dark' : 'light',
146142
},
147143
matchMenuKeys,
148144
);
149145

150-
const footerRender = getComponentOrSlot(props, slots, 'footerRender');
151-
// const menuRender = getComponentOrSlot(props, slots, 'menuRender');
152-
// const menuHeaderRender = getComponentOrSlot(props, slots, 'menuHeaderRender');
153-
154146
return (
155147
<ProProvider i18n={defaultI18nRender}>
156148
{props.pure ? (
@@ -162,12 +154,10 @@ const ProLayout: FunctionalComponent<BasicLayoutProps> = (props, { emit, slots }
162154
<SiderMenuWrapper
163155
{...props}
164156
isMobile={isMobile.value}
165-
menuHeaderRender={
166-
menuHeaderRenderFunc || (menuHeaderRenderSlot && (() => menuHeaderRenderSlot()))
167-
}
168-
onCollapse={handleCollapse}
169-
onSelect={handleSelect}
170-
onOpenKeys={handleOpenKeys}
157+
menuHeaderRender={menuHeaderRender}
158+
onCollapse={onCollapse}
159+
onSelect={onSelect}
160+
onOpenKeys={onOpenKeys}
171161
/>
172162
)}
173163
<Layout style={genLayoutStyle}>
@@ -178,7 +168,7 @@ const ProLayout: FunctionalComponent<BasicLayoutProps> = (props, { emit, slots }
178168
>
179169
{slots.default?.()}
180170
</WrapContent>
181-
{footerRender !== false && footerRender && footerRender}
171+
{footerRender && footerRender(props)}
182172
</Layout>
183173
</Layout>
184174
</div>
@@ -266,6 +256,8 @@ ProLayout.props = {
266256
collapsed: PropTypes.bool,
267257
/* 菜单的折叠收起事件 (collapsed: boolean) => void */
268258
onCollapse: PropTypes.func,
259+
onSelect: PropTypes.func,
260+
onOpenKeys: PropTypes.func,
269261
// onPageChange // 请使用 vue-router 监听
270262
/* 禁止自动切换到移动页面 */
271263
disableMobile: PropTypes.bool,

src/GlobalHeader/index.tsx

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { computed, CSSProperties, FunctionalComponent } from 'vue';
22
import { PureSettings } from '../defaultSettings';
3-
import { RenderVNodeType, MenuDataItem, WithFalse } from '../typings';
3+
import { VNodeType, MenuDataItem, WithFalse } from '../typings';
44
import {
55
SiderMenuProps,
66
PrivateSiderMenuProps,
@@ -18,9 +18,9 @@ export interface GlobalHeaderProps extends Partial<PureSettings> {
1818
collapsed?: boolean;
1919
onCollapse?: (collapsed: boolean) => void;
2020
isMobile?: boolean;
21-
logo?: RenderVNodeType;
22-
menuRender?: WithFalse<(props: HeaderViewProps, defaultDom: RenderVNodeType) => RenderVNodeType>;
23-
rightContentRender?: WithFalse<(props: HeaderViewProps) => RenderVNodeType>;
21+
logo?: VNodeType;
22+
menuRender?: WithFalse<(props: HeaderViewProps, defaultDom: VNodeType) => VNodeType>;
23+
rightContentRender?: WithFalse<(props: HeaderViewProps) => VNodeType>;
2424
className?: string;
2525
prefixCls?: string;
2626
menuData?: MenuDataItem[];
@@ -33,10 +33,7 @@ export interface GlobalHeaderProps extends Partial<PureSettings> {
3333
onSelect?: (selectedKeys: WithFalse<string[]>) => void;
3434
}
3535

36-
const renderLogo = (
37-
menuHeaderRender: SiderMenuProps['menuHeaderRender'],
38-
logoDom: RenderVNodeType,
39-
) => {
36+
const renderLogo = (menuHeaderRender: SiderMenuProps['menuHeaderRender'], logoDom: VNodeType) => {
4037
if (menuHeaderRender === false) {
4138
return null;
4239
}

src/Header.tsx

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import Layout from 'ant-design-vue/es/layout';
55
import { GlobalHeader, GlobalHeaderProps } from './GlobalHeader';
66
import { TopNavHeader } from './TopNavHeader';
77
import { useRouteContext } from './RouteContext';
8-
import { RenderVNodeType, WithFalse } from './typings';
8+
import { VNodeType, WithFalse } from './typings';
99
import { clearMenuItem } from './utils';
1010
import './Header.less';
1111

@@ -18,15 +18,11 @@ interface HeaderViewState {
1818
export type HeaderViewProps = GlobalHeaderProps & {
1919
isMobile?: boolean;
2020
collapsed?: boolean;
21-
logo?: RenderVNodeType;
21+
logo?: VNodeType;
2222

23-
headerRender?: WithFalse<
24-
(props: HeaderViewProps, defaultDom: RenderVNodeType) => RenderVNodeType
25-
>;
26-
headerTitleRender?: WithFalse<
27-
(props: HeaderViewProps, defaultDom: RenderVNodeType) => RenderVNodeType
28-
>;
29-
headerContentRender?: WithFalse<(props: HeaderViewProps) => RenderVNodeType>;
23+
headerRender?: WithFalse<(props: HeaderViewProps, defaultDom: VNodeType) => VNodeType>;
24+
headerTitleRender?: WithFalse<(props: HeaderViewProps, defaultDom: VNodeType) => VNodeType>;
25+
headerContentRender?: WithFalse<(props: HeaderViewProps) => VNodeType>;
3026
siderWidth?: number;
3127
hasSiderMenu?: boolean;
3228
};
@@ -66,8 +62,6 @@ export const HeaderView = defineComponent({
6662
setup(props: HeaderViewProps) {
6763
const {
6864
prefixCls,
69-
headerRender,
70-
headerContentRender,
7165
isMobile,
7266
fixedHeader,
7367
hasSiderMenu,
@@ -96,7 +90,7 @@ export const HeaderView = defineComponent({
9690
const renderContent = () => {
9791
let defaultDom = (
9892
<GlobalHeader {...props} onCollapse={onCollapse.value} menuData={clearMenuData.value}>
99-
{headerContentRender && headerContentRender.value && headerContentRender.value(props)}
93+
{props.headerContentRender && props.headerContentRender(props)}
10094
</GlobalHeader>
10195
);
10296
if (isTop.value && !isMobile.value) {
@@ -110,8 +104,8 @@ export const HeaderView = defineComponent({
110104
/>
111105
);
112106
}
113-
if (headerRender.value && typeof headerRender.value === 'function') {
114-
return headerRender.value(props, defaultDom);
107+
if (props.headerRender) {
108+
return props.headerRender(props, defaultDom);
115109
}
116110
return defaultDom;
117111
};

src/SiderMenu/BaseMenu.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,6 @@ class MenuUtil {
117117

118118
constructor(props: BaseMenuProps) {
119119
this.props = props;
120-
console.log('MenuUtil constructor', new Date());
121120
}
122121

123122
getNavMenuItems = (menusData: MenuDataItem[] = [], isChildren: boolean) => {

0 commit comments

Comments
 (0)