Unverified Commit daad9bf8 authored by Sendya's avatar Sendya

feat: slots prop

parent 1b8e4e25
<template>
<pro-layout
title="Ant Design Pro"
:menus="menus"
:collapsed="collapsed"
:theme="theme"
:layout="layout"
:contentWidth="contentWidth"
:auto-hide-header="autoHideHeader"
:mediaQuery="query"
:isMobile="isMobile"
:handleMediaQuery="handleMediaQuery"
:handleCollapse="handleCollapse"
:logo="logoRender"
:i18nRender="i18nRender"
>
<template v-slot:rightContentRender>
<div :class="['ant-pro-global-header-index-right', layout === 'topmenu' && `ant-pro-global-header-index-${theme}`]">
rightContentRender
</div>
</template>
<template v-slot:footerRender>
<div>footerRender</div>
</template>
<router-view />
</pro-layout>
</template>
<script>
import ProLayout from '@ant-design-vue/pro-layout'
import { asyncRouterMap } from '../config/router.config'
import { i18nRender } from '../locales'
import LogoSvg from '../assets/logo.svg?inline'
export default {
name: 'BasicLayout',
data () {
return {
// base
menus: [],
// 侧栏收起状态
collapsed: false,
// 自动隐藏头部栏
autoHideHeader: false,
// 媒体查询
query: {},
// 布局类型
layout: 'sidemenu', // 'sidemenu', 'topmenu'
// 定宽: true / 流式: false
contentWidth: true,
// 主题 'dark' | 'light'
theme: 'dark',
// 是否手机模式
isMobile: false
}
},
created () {
this.menus = asyncRouterMap.find(item => item.path === '/').children
},
methods: {
i18nRender,
handleMediaQuery (val) {
this.query = val
if (this.isMobile && !val['screen-xs']) {
this.isMobile = false
return
}
if (!this.isMobile && val['screen-xs']) {
this.isMobile = true
this.collapsed = false
}
},
handleCollapse (val) {
this.collapsed = val
},
logoRender () {
return <LogoSvg />
},
footerRender () {
return <div>custom footer</div>
}
},
components: {
ProLayout
}
}
</script>
<style lang="less" scoped>
@import "BasicLayout.less";
</style>
import './BasicLayout.less'
import { Layout } from 'ant-design-vue' import { Layout } from 'ant-design-vue'
import { ContainerQuery } from 'vue-container-query' import { ContainerQuery } from 'vue-container-query'
import GridContent from './components/GridContent' import GridContent from './components/GridContent'
import { SiderMenuWrapper, GlobalFooter } from './components' import { SiderMenuWrapper, GlobalFooter } from './components'
import { getComponentFormProp, isFun } from './utils/util'
import './BasicLayout.less'
import { SiderMenuProps } from './components/SiderMenu/SiderMenu' import { SiderMenuProps } from './components/SiderMenu/SiderMenu'
import HeaderView, { HeaderViewProps } from './Header' import HeaderView, { HeaderViewProps } from './Header'
...@@ -36,7 +37,6 @@ export const BasicLayoutProps = { ...@@ -36,7 +37,6 @@ export const BasicLayoutProps = {
} }
} }
// eslint-disable-next-line
const MediaQueryEnum = { const MediaQueryEnum = {
'screen-xs': { 'screen-xs': {
maxWidth: 575 maxWidth: 575
...@@ -73,11 +73,8 @@ const BasicLayout = { ...@@ -73,11 +73,8 @@ const BasicLayout = {
name: 'BasicLayout', name: 'BasicLayout',
functional: true, functional: true,
props: BasicLayoutProps, props: BasicLayoutProps,
render (h, { render (h, content) {
props, const { props, data, children, slots } = content
data,
children
}) {
const { const {
menus, menus,
layout, layout,
...@@ -86,19 +83,29 @@ const BasicLayout = { ...@@ -86,19 +83,29 @@ const BasicLayout = {
theme, theme,
collapsed, collapsed,
// eslint-disable-next-line // eslint-disable-next-line
collapsedButtonRender, autoHideHeader, autoHideHeader,
footerRender,
mediaQuery, mediaQuery,
handleMediaQuery, handleMediaQuery,
handleCollapse handleCollapse
} = props } = props
const footerRender = getComponentFormProp(content, 'footerRender')
const rightContentRender = getComponentFormProp(content, 'rightContentRender')
const collapsedButtonRender = getComponentFormProp(content, 'collapsedButtonRender')
const cdProps = {
...props,
footerRender,
rightContentRender,
collapsedButtonRender
}
return ( return (
<div> <div>
<ContainerQuery query={MediaQueryEnum} onChange={handleMediaQuery}> <ContainerQuery query={MediaQueryEnum} onChange={handleMediaQuery}>
<Layout class={{ 'basicLayout': true, ...mediaQuery }}> <Layout class={{ 'basicLayout': true, ...mediaQuery }}>
<SiderMenuWrapper <SiderMenuWrapper
{ ...{ props: props } } { ...{ props: cdProps } }
menus={menus} menus={menus}
mode={'inline'} mode={'inline'}
logo={logo} logo={logo}
...@@ -108,7 +115,7 @@ const BasicLayout = { ...@@ -108,7 +115,7 @@ const BasicLayout = {
/> />
<Layout class={[layout]} style={{ paddingLeft: '0', minHeight: '100vh' }}> <Layout class={[layout]} style={{ paddingLeft: '0', minHeight: '100vh' }}>
{headerRender(h, { {headerRender(h, {
...props, ...cdProps,
mode: 'horizontal', mode: 'horizontal',
})} })}
<Layout.Content style={{ margin: '24px 16px', padding: '24px', minHeight: '280px' }}> <Layout.Content style={{ margin: '24px 16px', padding: '24px', minHeight: '280px' }}>
...@@ -118,7 +125,7 @@ const BasicLayout = { ...@@ -118,7 +125,7 @@ const BasicLayout = {
</Layout.Content> </Layout.Content>
<Layout.Footer> <Layout.Footer>
{ footerRender && ( { footerRender && (
footerRender(h) isFun(footerRender) && footerRender(h) || footerRender
) || ( ) || (
<GlobalFooter> <GlobalFooter>
<template slot="links"> <template slot="links">
......
...@@ -5,6 +5,7 @@ import { Layout } from 'ant-design-vue' ...@@ -5,6 +5,7 @@ import { Layout } from 'ant-design-vue'
import BaseMenu from './components/RouteMenu/BaseMenu' import BaseMenu from './components/RouteMenu/BaseMenu'
import { defaultRenderLogoAntTitle, SiderMenuProps } from './components/SiderMenu/SiderMenu' import { defaultRenderLogoAntTitle, SiderMenuProps } from './components/SiderMenu/SiderMenu'
import GlobalHeader, { GlobalHeaderProps } from './components/GlobalHeader' import GlobalHeader, { GlobalHeaderProps } from './components/GlobalHeader'
import { isFun } from './utils/util'
const { Header } = Layout const { Header } = Layout
...@@ -20,21 +21,24 @@ export const HeaderViewProps = { ...@@ -20,21 +21,24 @@ export const HeaderViewProps = {
required: true required: true
}, },
logo: { logo: {
type: null, type: [Function, Object],
default: () => null required: false
}, },
autoHideHeader: { autoHideHeader: {
type: Boolean, type: Boolean,
required: true required: true
}, },
menuRender: { menuRender: {
type: null type: null,
required: false
}, },
headerRender: { headerRender: {
type: null type: null,
required: false
}, },
rightContentRender: { rightContentRender: {
type: null type: null,
required: false
}, },
siderWidth: { siderWidth: {
type: Number type: Number
...@@ -65,7 +69,7 @@ const renderContent = (h, props) => { ...@@ -65,7 +69,7 @@ const renderContent = (h, props) => {
<div class={`${baseCls}-menu`} style={{ maxWidth: `${maxWidth}px`, flex: 1 }}> <div class={`${baseCls}-menu`} style={{ maxWidth: `${maxWidth}px`, flex: 1 }}>
<BaseMenu {...{ props: props }} /> <BaseMenu {...{ props: props }} />
</div> </div>
{rightContentRender(h, rightContentProps)} {isFun(rightContentRender) && rightContentRender(h, rightContentProps) || rightContentRender}
</div> </div>
</div> </div>
) )
......
import './index.less' import './index.less'
import debounce from 'lodash/debounce' import debounce from 'lodash/debounce'
import { triggerEvent, inBrowser } from '../../utils/util' import { triggerEvent, inBrowser, isFun } from '../../utils/util'
import { Icon } from 'ant-design-vue' import { Icon } from 'ant-design-vue'
import { defaultRenderLogo } from '../SiderMenu/SiderMenu' import { defaultRenderLogo } from '../SiderMenu/SiderMenu'
...@@ -23,16 +23,15 @@ export const GlobalHeaderProps = { ...@@ -23,16 +23,15 @@ export const GlobalHeaderProps = {
default: () => null default: () => null
}, },
menuRender: { menuRender: {
type: Function, type: null,
required: false required: false
}, },
collapsedButtonRender: { collapsedButtonRender: {
type: Function, type: null,
defualt: null,
required: false required: false
}, },
rightContentRender: { rightContentRender: {
type: Function, type: null,
required: false required: false
} }
} }
...@@ -59,7 +58,7 @@ const GlobalHeader = { ...@@ -59,7 +58,7 @@ const GlobalHeader = {
if (collapsedButtonRender !== false && menuRender !== false) { if (collapsedButtonRender !== false && menuRender !== false) {
return ( return (
<span class="ant-pro-global-header-trigger" onClick={toggle}> <span class="ant-pro-global-header-trigger" onClick={toggle}>
{collapsedButtonRender(h, collapsed)} {isFun(collapsedButtonRender) && collapsedButtonRender(h, collapsed) || collapsedButtonRender}
</span> </span>
) )
} }
...@@ -78,7 +77,7 @@ const GlobalHeader = { ...@@ -78,7 +77,7 @@ const GlobalHeader = {
</a> </a>
)} )}
{renderCollapsedButton()} {renderCollapsedButton()}
{rightContentRender && rightContentRender(h, this.$props)} {isFun(rightContentRender) && rightContentRender(h, this.$props) || rightContentRender}
</div> </div>
) )
}, },
......
import triggerEvent from 'ant-design-vue/es/_util/triggerEvent' import triggerEvent from 'ant-design-vue/es/_util/triggerEvent'
import { inBrowser } from 'ant-design-vue/es/_util/env' import { inBrowser } from 'ant-design-vue/es/_util/env'
const getComponentFormProp = (instance, prop) => {
const slots = instance.slots && instance.slots()
return slots[prop] || instance.props[prop]
}
const isFun = (func) => {
return typeof func === 'function'
}
/** /**
* 触发 window.resize * 触发 window.resize
*/ */
export { export {
triggerEvent, triggerEvent,
inBrowser inBrowser,
getComponentFormProp,
isFun
} }
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