Commit ac911538 authored by Sendya's avatar Sendya

fix: footerRender, GlobalFooter props check

parent 5f70ec85
...@@ -28,9 +28,11 @@ ...@@ -28,9 +28,11 @@
<!-- custom breadcrumb itemRender --> <!-- custom breadcrumb itemRender -->
<template #breadcrumbRender="{ route, params, routes }"> <template #breadcrumbRender="{ route, params, routes }">
<span v-if="routes.indexOf(route) === routes.length - 1"> <span v-if="routes.indexOf(route) === routes.length - 1">
<SmileOutlined />
{{ route.breadcrumbName }} {{ route.breadcrumbName }}
</span> </span>
<router-link v-else :to="{ path: route.path, params }"> <router-link v-else :to="{ path: route.path, params }">
<SmileOutlined />
{{ route.breadcrumbName }} {{ route.breadcrumbName }}
</router-link> </router-link>
</template> </template>
...@@ -54,29 +56,15 @@ ...@@ -54,29 +56,15 @@
<!-- content begin --> <!-- content begin -->
<router-view /> <router-view />
<!-- content end --> <!-- content end -->
<FooterToolbar> <template #footerRender>
<a-space> <GlobalFooter
<span :disabled="state.layout !== 'mix'"> :links="[
<span style="margin-right: 8px">SplitMenus:</span> { key: 'a link', title: 'Link1', href: 'http://www.baidu.com/', blankTarget: true },
<a-switch { key: 'b link', title: 'Link2', href: 'https://www.google.com/', blankTarget: true },
v-model:checked="state.splitMenus" ]"
:disabled="state.layout !== 'mix'" copyright="2021 &copy; Sendya"
checked-children="ON" ></GlobalFooter>
un-checked-children="OFF" </template>
/>
</span>
<a-button @click="handlePageLoadingClick">Page Loading</a-button>
<a-select v-model:value="state.navTheme" style="width: 100px">
<a-select-option value="light">Light</a-select-option>
<a-select-option value="dark">Dark</a-select-option>
</a-select>
<a-select v-model:value="state.layout" style="width: 100px">
<a-select-option value="side">Side</a-select-option>
<a-select-option value="top">Top</a-select-option>
<a-select-option value="mix">Mix</a-select-option>
</a-select>
</a-space>
</FooterToolbar>
</pro-layout> </pro-layout>
</template> </template>
...@@ -84,7 +72,13 @@ ...@@ -84,7 +72,13 @@
import { computed, defineComponent, reactive, ref, watchEffect } from 'vue'; import { computed, defineComponent, reactive, ref, watchEffect } from 'vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { Button, Switch, Select, Space, Badge, Menu } from 'ant-design-vue'; import { Button, Switch, Select, Space, Badge, Menu } from 'ant-design-vue';
import { getMenuData, clearMenuItem, FooterToolbar } from '@ant-design-vue/pro-layout'; import {
getMenuData,
clearMenuItem,
FooterToolbar,
GlobalFooter,
} from '@ant-design-vue/pro-layout';
import { SmileOutlined } from '@ant-design/icons-vue';
import type { RouteContextProps } from '@ant-design-vue/pro-layout'; import type { RouteContextProps } from '@ant-design-vue/pro-layout';
const i18n = (t: string) => t; const i18n = (t: string) => t;
...@@ -101,6 +95,9 @@ export default defineComponent({ ...@@ -101,6 +95,9 @@ export default defineComponent({
[Badge.name]: Badge, [Badge.name]: Badge,
[Menu.Item.name]: Menu.Item, [Menu.Item.name]: Menu.Item,
GlobalFooter,
SmileOutlined,
}, },
setup() { setup() {
const loading = ref(false); const loading = ref(false);
......
import { createRouter, createWebHistory } from 'vue-router'; import { createRouter, createWebHistory } from 'vue-router';
import type { RouteRecordRaw } from 'vue-router'; import type { RouteRecordRaw } from 'vue-router';
import BasicLayout from './layouts/BasicLayout.vue'; import BasicLayout from './layouts/CustomLayout.vue';
import RouteView from './layouts/RouteView.vue'; import RouteView from './layouts/RouteView.vue';
const routes: RouteRecordRaw[] = [ const routes: RouteRecordRaw[] = [
......
{ {
"name": "@ant-design-vue/pro-layout", "name": "@ant-design-vue/pro-layout",
"version": "3.1.2", "version": "3.1.3",
"license": "MIT", "license": "MIT",
"files": [ "files": [
"dist" "dist"
......
import { computed, reactive, unref, defineComponent, toRefs } from 'vue' import { computed, reactive, unref, defineComponent, toRefs } from 'vue';
import type { CSSProperties, PropType, ExtractPropTypes } from 'vue' import type { CSSProperties, PropType, ExtractPropTypes } from 'vue';
import 'ant-design-vue/es/layout/style' import 'ant-design-vue/es/layout/style';
import { Layout } from 'ant-design-vue' import { Layout } from 'ant-design-vue';
import { withInstall } from 'ant-design-vue/es/_util/type' import { withInstall } from 'ant-design-vue/es/_util/type';
import useMediaQuery from './hooks/useMediaQuery' import useMediaQuery from './hooks/useMediaQuery';
import { defaultSettingProps } from './defaultSettings' import { defaultSettingProps } from './defaultSettings';
import { import { provideRouteContext, defaultRouteContext, RouteContextProps } from './RouteContext';
provideRouteContext, import SiderMenuWrapper, { siderMenuProps } from './SiderMenu';
defaultRouteContext, import { WrapContent } from './WrapContent';
RouteContextProps, import globalHeaderProps from './GlobalHeader/headerProps';
} from './RouteContext' import { HeaderView as Header, headerViewProps } from './Header';
import SiderMenuWrapper, { siderMenuProps } from './SiderMenu' import { getPropsSlot, getPropsSlotfn, PropTypes, getMenuFirstChildren, pick } from './utils';
import { WrapContent } from './WrapContent' import type { BreadcrumbProps } from './RouteContext';
import globalHeaderProps from './GlobalHeader/headerProps' import type { CustomRender, FormatMessage, WithFalse } from './typings';
import { HeaderView as Header, headerViewProps } from './Header'
import {
getPropsSlot,
getPropsSlotfn,
PropTypes,
getMenuFirstChildren,
pick,
} from './utils'
import type { BreadcrumbProps } from './RouteContext'
import type { CustomRender, FormatMessage, WithFalse } from './typings'
import PageLoading from './PageLoading' import PageLoading from './PageLoading';
import './BasicLayout.less' import './BasicLayout.less';
export const basicLayoutProps = { export const basicLayoutProps = {
...defaultSettingProps, ...defaultSettingProps,
...@@ -40,7 +30,7 @@ export const basicLayoutProps = { ...@@ -40,7 +30,7 @@ export const basicLayoutProps = {
locale: { locale: {
type: [Function, Boolean] as PropType<WithFalse<FormatMessage>>, type: [Function, Boolean] as PropType<WithFalse<FormatMessage>>,
default() { default() {
return (s: string) => s return (s: string) => s;
}, },
}, },
/** /**
...@@ -57,15 +47,11 @@ export const basicLayoutProps = { ...@@ -57,15 +47,11 @@ export const basicLayoutProps = {
default: () => null, default: () => null,
}, },
collapsedButtonRender: { collapsedButtonRender: {
type: [Function, Object, Boolean] as PropType< type: [Function, Object, Boolean] as PropType<WithFalse<(collapsed?: boolean) => any>>,
WithFalse<(collapsed?: boolean) => any>
>,
default: () => undefined, default: () => undefined,
}, },
breadcrumbRender: { breadcrumbRender: {
type: [Object, Function, Boolean] as PropType< type: [Object, Function, Boolean] as PropType<WithFalse<BreadcrumbProps['itemRender']>>,
WithFalse<BreadcrumbProps['itemRender']>
>,
default: () => {}, default: () => {},
}, },
headerContentRender: { headerContentRender: {
...@@ -73,24 +59,18 @@ export const basicLayoutProps = { ...@@ -73,24 +59,18 @@ export const basicLayoutProps = {
default: () => undefined, default: () => undefined,
}, },
headerRender: { headerRender: {
type: [Object, Function, Boolean] as PropType< type: [Object, Function, Boolean] as PropType<WithFalse<(props: any /* HeaderProps */) => any>>,
WithFalse<(props: any /* HeaderProps */) => any>
>,
default: () => undefined, default: () => undefined,
}, },
footerRender: { footerRender: {
type: [Object, Function, Boolean] as PropType< type: [Object, Function, Boolean] as PropType<WithFalse<(props: any /* FooterProps */) => any>>,
WithFalse<(props: any /* FooterProps */) => any>
>,
default: () => undefined, default: () => undefined,
}, },
colSize: PropTypes.string, colSize: PropTypes.string,
contentStyle: PropTypes.style, contentStyle: PropTypes.style,
} };
export type BasicLayoutProps = Partial< export type BasicLayoutProps = Partial<ExtractPropTypes<typeof basicLayoutProps>>;
ExtractPropTypes<typeof basicLayoutProps>
>
const ProLayout = defineComponent({ const ProLayout = defineComponent({
name: 'ProLayout', name: 'ProLayout',
...@@ -107,49 +87,41 @@ const ProLayout = defineComponent({ ...@@ -107,49 +87,41 @@ const ProLayout = defineComponent({
'menuClick', 'menuClick',
], ],
setup(props, { emit, slots }) { setup(props, { emit, slots }) {
console.log('props', props) console.log('props', props);
const isTop = computed(() => props.layout === 'top') const isTop = computed(() => props.layout === 'top');
const hasSide = computed( const hasSide = computed(() => props.layout === 'mix' || props.layout === 'side' || false);
() => props.layout === 'mix' || props.layout === 'side' || false const hasSplitMenu = computed(() => props.layout === 'mix' && props.splitMenus);
)
const hasSplitMenu = computed(
() => props.layout === 'mix' && props.splitMenus
)
const hasFlatMenu = computed(() => { const hasFlatMenu = computed(() => {
return hasSide.value && hasSplitMenu.value return hasSide.value && hasSplitMenu.value;
}) });
const siderWidth = computed(() => const siderWidth = computed(() => (props.collapsed ? props.collapsedWidth : props.siderWidth));
props.collapsed ? props.collapsedWidth : props.siderWidth
)
// if on event and @event // if on event and @event
const onCollapse = (collapsed: boolean) => { const onCollapse = (collapsed: boolean) => {
emit('update:collapsed', collapsed) emit('update:collapsed', collapsed);
emit('collapse', collapsed) emit('collapse', collapsed);
} };
const onOpenKeys = (openKeys: string[] | false) => { const onOpenKeys = (openKeys: string[] | false) => {
emit('update:open-keys', openKeys) emit('update:open-keys', openKeys);
emit('openKeys', openKeys) emit('openKeys', openKeys);
} };
const onSelect = (selectedKeys: string[] | false) => { const onSelect = (selectedKeys: string[] | false) => {
emit('update:selected-keys', selectedKeys) emit('update:selected-keys', selectedKeys);
emit('select', selectedKeys) emit('select', selectedKeys);
} };
const onMenuHeaderClick = (e: MouseEvent) => { const onMenuHeaderClick = (e: MouseEvent) => {
emit('menuHeaderClick', e) emit('menuHeaderClick', e);
} };
const onMenuClick = (args: any) => { const onMenuClick = (args: any) => {
emit('menuClick', args) emit('menuClick', args);
} };
const colSize = useMediaQuery() const colSize = useMediaQuery();
const isMobile = computed( const isMobile = computed(
() => () => (colSize.value === 'sm' || colSize.value === 'xs') && !props.disableMobile,
(colSize.value === 'sm' || colSize.value === 'xs') && );
!props.disableMobile const baseClassName = computed(() => `${props.prefixCls}-basicLayout`);
)
const baseClassName = computed(() => `${props.prefixCls}-basicLayout`)
// gen className // gen className
const className = computed(() => { const className = computed(() => {
return { return {
...@@ -159,48 +131,45 @@ const ProLayout = defineComponent({ ...@@ -159,48 +131,45 @@ const ProLayout = defineComponent({
[`${baseClassName.value}-is-children`]: props.isChildrenLayout, [`${baseClassName.value}-is-children`]: props.isChildrenLayout,
[`${baseClassName.value}-fix-siderbar`]: props.fixSiderbar, [`${baseClassName.value}-fix-siderbar`]: props.fixSiderbar,
[`${baseClassName.value}-${props.layout}`]: props.layout, [`${baseClassName.value}-${props.layout}`]: props.layout,
} };
}) });
// siderMenuDom 为空的时候,不需要 padding // siderMenuDom 为空的时候,不需要 padding
const genLayoutStyle = reactive<CSSProperties>({ const genLayoutStyle = reactive<CSSProperties>({
position: 'relative', position: 'relative',
}) });
// if is some layout children, don't need min height // if is some layout children, don't need min height
if ( if (props.isChildrenLayout || (props.contentStyle && props.contentStyle.minHeight)) {
props.isChildrenLayout || genLayoutStyle.minHeight = 0;
(props.contentStyle && props.contentStyle.minHeight)
) {
genLayoutStyle.minHeight = 0
} }
const headerRender = ( const headerRender = (
p: BasicLayoutProps & { p: BasicLayoutProps & {
hasSiderMenu: boolean hasSiderMenu: boolean;
headerRender: WithFalse<CustomRender> headerRender: WithFalse<CustomRender>;
rightContentRender: WithFalse<CustomRender> rightContentRender: WithFalse<CustomRender>;
}, },
matchMenuKeys?: string[] matchMenuKeys?: string[],
): CustomRender | null => { ): CustomRender | null => {
if (p.headerRender === false || p.pure) { if (p.headerRender === false || p.pure) {
return null return null;
}
return <Header {...p} matchMenuKeys={matchMenuKeys || []} />
} }
return <Header {...p} matchMenuKeys={matchMenuKeys || []} />;
};
const breadcrumb = computed<BreadcrumbProps>(() => ({ const breadcrumb = computed<BreadcrumbProps>(() => ({
...props.breadcrumb, ...props.breadcrumb,
itemRender: getPropsSlotfn(slots, props, 'breadcrumbRender'), itemRender: getPropsSlotfn(slots, props, 'breadcrumbRender'),
})) }));
const flatMenuData = computed( const flatMenuData = computed(
() => () =>
(hasFlatMenu.value && (hasFlatMenu.value &&
props.selectedKeys && props.selectedKeys &&
getMenuFirstChildren(props.menuData, props.selectedKeys[0])) || getMenuFirstChildren(props.menuData, props.selectedKeys[0])) ||
[] [],
) );
const routeContext = reactive<RouteContextProps>( const routeContext = reactive<RouteContextProps>(
Object.assign( Object.assign(
...@@ -227,10 +196,10 @@ const ProLayout = defineComponent({ ...@@ -227,10 +196,10 @@ const ProLayout = defineComponent({
flatMenuData, flatMenuData,
hasSide, hasSide,
flatMenu: hasFlatMenu, flatMenu: hasFlatMenu,
} },
) ),
) );
provideRouteContext(routeContext) provideRouteContext(routeContext);
return () => { return () => {
const { const {
...@@ -240,44 +209,24 @@ const ProLayout = defineComponent({ ...@@ -240,44 +209,24 @@ const ProLayout = defineComponent({
onSelect: propsOnSelect, onSelect: propsOnSelect,
onMenuClick: propsOnMenuClick, onMenuClick: propsOnMenuClick,
...restProps ...restProps
} = props } = props;
const collapsedButtonRender = getPropsSlotfn( const collapsedButtonRender = getPropsSlotfn(slots, props, 'collapsedButtonRender');
slots, const headerContentRender = getPropsSlot(slots, props, 'headerContentRender');
props, const rightContentRender = getPropsSlot(slots, props, 'rightContentRender');
'collapsedButtonRender' const customHeaderRender = getPropsSlot(slots, props, 'headerRender');
) const menuHeaderRender = getPropsSlotfn(slots, props, 'menuHeaderRender');
const headerContentRender = getPropsSlot( const menuContentRender = getPropsSlotfn(slots, props, 'menuContentRender');
slots, const menuExtraRender = getPropsSlotfn(slots, props, 'menuExtraRender');
props, const menuFooterRender = getPropsSlotfn(slots, props, 'menuFooterRender');
'headerContentRender' const footerRender = getPropsSlotfn(slots, props, 'footerRender');
)
const rightContentRender = getPropsSlot(
slots,
props,
'rightContentRender'
)
const customHeaderRender = getPropsSlot(slots, props, 'headerRender')
const menuHeaderRender = getPropsSlotfn(slots, props, 'menuHeaderRender')
const menuContentRender = getPropsSlotfn(
slots,
props,
'menuContentRender'
)
const menuExtraRender = getPropsSlotfn(slots, props, 'menuExtraRender')
const menuFooterRender = getPropsSlotfn(slots, props, 'menuFooterRender')
const footerRender = getPropsSlot(slots, props, 'footerRender')
// menu render // menu render
const menuItemRender = getPropsSlotfn(slots, props, 'menuItemRender') const menuItemRender = getPropsSlotfn(slots, props, 'menuItemRender');
const subMenuItemRender = getPropsSlotfn( const subMenuItemRender = getPropsSlotfn(slots, props, 'subMenuItemRender');
slots,
props,
'subMenuItemRender'
)
const menuRenders = { const menuRenders = {
menuItemRender, menuItemRender,
subMenuItemRender, subMenuItemRender,
} };
const headerDom = computed(() => const headerDom = computed(() =>
headerRender( headerRender(
...@@ -297,15 +246,13 @@ const ProLayout = defineComponent({ ...@@ -297,15 +246,13 @@ const ProLayout = defineComponent({
menuContentRender: menuContentRender, menuContentRender: menuContentRender,
headerContentRender, headerContentRender,
headerRender: props.headerRender !== false ? customHeaderRender : false, headerRender: props.headerRender !== false ? customHeaderRender : false,
theme: (props.navTheme || 'dark') theme: (props.navTheme || 'dark').toLocaleLowerCase().includes('dark')
.toLocaleLowerCase()
.includes('dark')
? 'dark' ? 'dark'
: 'light', : 'light',
}, },
props.matchMenuKeys props.matchMenuKeys,
) ),
) );
return ( return (
<> <>
...@@ -334,11 +281,7 @@ const ProLayout = defineComponent({ ...@@ -334,11 +281,7 @@ const ProLayout = defineComponent({
{headerDom.value} {headerDom.value}
<WrapContent <WrapContent
isChildrenLayout={props.isChildrenLayout} isChildrenLayout={props.isChildrenLayout}
style={ style={props.disableContentMargin ? undefined : props.contentStyle}
props.disableContentMargin
? undefined
: props.contentStyle
}
> >
{props.loading ? <PageLoading /> : slots.default?.()} {props.loading ? <PageLoading /> : slots.default?.()}
</WrapContent> </WrapContent>
...@@ -348,9 +291,9 @@ const ProLayout = defineComponent({ ...@@ -348,9 +291,9 @@ const ProLayout = defineComponent({
</div> </div>
)} )}
</> </>
) );
} };
}, },
}) });
export default withInstall(ProLayout) export default withInstall(ProLayout);
...@@ -22,7 +22,10 @@ export default defineComponent({ ...@@ -22,7 +22,10 @@ export default defineComponent({
name: 'GlobalFooter', name: 'GlobalFooter',
props: { props: {
links: [Array, Boolean] as PropType<Links>, links: [Array, Boolean] as PropType<Links>,
copyright: [Object, Function] as PropType<VNodeChild | JSX.Element>, copyright: {
type: [Object, Function, Boolean] as PropType<VNodeChild | JSX.Element>,
default: () => undefined,
},
prefixCls: { prefixCls: {
type: String, type: String,
default: 'ant-pro', default: 'ant-pro',
...@@ -35,7 +38,8 @@ export default defineComponent({ ...@@ -35,7 +38,8 @@ export default defineComponent({
(Array.isArray(props.links) && props.links.length === 0)) && (Array.isArray(props.links) && props.links.length === 0)) &&
(props.copyright == null || props.copyright === false) (props.copyright == null || props.copyright === false)
) { ) {
return null; console.warn('[pro-layout]: GlobalFooter required `links` or `copyright`');
return () => null;
} }
const baseClassName = `${props.prefixCls}-global-footer`; const baseClassName = `${props.prefixCls}-global-footer`;
......
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