-
-
Notifications
You must be signed in to change notification settings - Fork 3.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(App): add App component (#6735)
* feat(App): add App component * docs: modification error * docs: doucment update docs: doucment update
- Loading branch information
Showing
12 changed files
with
535 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`renders ./components/app/demo/basic.vue correctly 1`] = ` | ||
<div class="ant-app"> | ||
<!--teleport start--> | ||
<!--teleport end--> | ||
<!--teleport start--> | ||
<!--teleport end--> | ||
<div class="ant-space ant-space-horizontal ant-space-align-center"> | ||
<div class="ant-space-item" style="margin-right: 8px;"><button class="ant-btn ant-btn-primary" type="button"> | ||
<!----><span>Open message</span> | ||
</button></div> | ||
<!----> | ||
<div class="ant-space-item" style="margin-right: 8px;"><button class="ant-btn ant-btn-primary" type="button"> | ||
<!----><span>Open modal</span> | ||
</button></div> | ||
<!----> | ||
<div class="ant-space-item"><button class="ant-btn ant-btn-primary" type="button"> | ||
<!----><span>Open notification</span> | ||
</button></div> | ||
<!----> | ||
</div> | ||
</div> | ||
`; | ||
|
||
exports[`renders ./components/app/demo/myPage.vue correctly 1`] = ` | ||
<div class="ant-space ant-space-horizontal ant-space-align-center"> | ||
<div class="ant-space-item" style="margin-right: 8px;"><button class="ant-btn ant-btn-primary" type="button"> | ||
<!----><span>Open message</span> | ||
</button></div> | ||
<!----> | ||
<div class="ant-space-item" style="margin-right: 8px;"><button class="ant-btn ant-btn-primary" type="button"> | ||
<!----><span>Open modal</span> | ||
</button></div> | ||
<!----> | ||
<div class="ant-space-item"><button class="ant-btn ant-btn-primary" type="button"> | ||
<!----><span>Open notification</span> | ||
</button></div> | ||
<!----> | ||
</div> | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import demoTest from '../../../tests/shared/demoTest'; | ||
|
||
demoTest('app'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import { provide, inject, reactive } from 'vue'; | ||
import type { InjectionKey } from 'vue'; | ||
import type { MessageInstance, ConfigOptions as MessageConfig } from '../message/interface'; | ||
import type { NotificationInstance, NotificationConfig } from '../notification/interface'; | ||
import type { ModalStaticFunctions } from '../modal/confirm'; | ||
|
||
export type AppConfig = { | ||
message?: MessageConfig; | ||
notification?: NotificationConfig; | ||
}; | ||
|
||
export const AppConfigContextKey: InjectionKey<AppConfig> = Symbol('appConfigContext'); | ||
|
||
export const useProvideAppConfigContext = (appConfigContext: AppConfig) => { | ||
return provide(AppConfigContextKey, appConfigContext); | ||
}; | ||
|
||
export const useInjectAppConfigContext = () => { | ||
return inject(AppConfigContextKey, {}); | ||
}; | ||
|
||
type ModalType = Omit<ModalStaticFunctions, 'warn'>; | ||
|
||
export interface useAppProps { | ||
message: MessageInstance; | ||
notification: NotificationInstance; | ||
modal: ModalType; | ||
} | ||
|
||
export const AppContextKey: InjectionKey<useAppProps> = Symbol('appContext'); | ||
|
||
export const useProvideAppContext = (appContext: useAppProps) => { | ||
return provide(AppContextKey, appContext); | ||
}; | ||
|
||
const defaultAppContext: useAppProps = reactive({ | ||
message: {}, | ||
notification: {}, | ||
modal: {}, | ||
} as useAppProps); | ||
|
||
export const useInjectAppContext = () => { | ||
return inject(AppContextKey, defaultAppContext); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
<docs> | ||
--- | ||
order: 0 | ||
title: | ||
zh-CN: 基本使用 | ||
en-US: Basic Usage | ||
--- | ||
|
||
## zh-CN | ||
|
||
获取 `message`、`notification`、`modal` 静态方法。 | ||
|
||
## en-US | ||
|
||
Static method for `message`, `notification`, `modal`. | ||
</docs> | ||
|
||
<template> | ||
<a-app> | ||
<my-page /> | ||
</a-app> | ||
</template> | ||
|
||
<script lang="ts" setup> | ||
import myPage from './myPage.vue'; | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<template> | ||
<demo-sort :cols="1"> | ||
<basic /> | ||
</demo-sort> | ||
</template> | ||
|
||
<script lang="ts"> | ||
import Basic from './basic.vue'; | ||
import CN from '../index.zh-CN.md'; | ||
import US from '../index.en-US.md'; | ||
import { defineComponent } from 'vue'; | ||
export default defineComponent({ | ||
CN, | ||
US, | ||
components: { | ||
Basic, | ||
}, | ||
}); | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<template> | ||
<a-space> | ||
<a-button type="primary" @click="showMessage">Open message</a-button> | ||
<a-button type="primary" @click="showModal">Open modal</a-button> | ||
<a-button type="primary" @click="showNotification">Open notification</a-button> | ||
</a-space> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
import { App } from 'ant-design-vue'; | ||
const { message, modal, notification } = App.useApp(); | ||
const showMessage = () => { | ||
message.success('Success!'); | ||
}; | ||
const showModal = () => { | ||
modal.warning({ | ||
title: 'This is a warning message', | ||
content: 'some messages...some messages...', | ||
}); | ||
}; | ||
const showNotification = () => { | ||
notification.info({ | ||
message: `Notification topLeft`, | ||
description: 'Hello, Ant Design Vue!!', | ||
placement: 'topLeft', | ||
}); | ||
}; | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
--- | ||
category: Components | ||
cols: 1 | ||
type: Other | ||
title: App | ||
cover: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*TBTSR4PyVmkAAAAAAAAAAAAADrJ8AQ/original | ||
coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*JGb3RIzyOCkAAAAAAAAAAAAADrJ8AQ/original | ||
--- | ||
|
||
Application wrapper for some global usages. | ||
|
||
## When To Use | ||
|
||
- Provide reset styles based on `.ant-app` element. | ||
- You could use static methods of `message/notification/Modal` form `useApp` without writing `contextHolder` manually. | ||
|
||
## API | ||
|
||
### App | ||
|
||
| Property | Description | Type | Default | Version | | ||
| --- | --- | --- | --- | --- | | ||
| message | Global config for Message | [MessageConfig](/components/message/#messageconfig) | - | 4.x | | ||
| notification | Global config for Notification | [NotificationConfig](/components/notification/#notificationconfig) | - | 4.x | | ||
|
||
## How to use | ||
|
||
### Basic usage | ||
|
||
App provides upstream and downstream method calls through `provide/inject`, because useApp needs to be used as a subcomponent, we recommend encapsulating App at the top level in the application. | ||
|
||
```html | ||
/*myPage.vue*/ | ||
<template> | ||
<a-space> | ||
<a-button type="primary" @click="showMessage">Open message</a-button> | ||
<a-button type="primary" @click="showModal">Open modal</a-button> | ||
<a-button type="primary" @click="showNotification">Open notification</a-button> | ||
</a-space> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
import { App } from 'ant-design-vue'; | ||
const { message, modal, notification } = App.useApp(); | ||
const showMessage = () => { | ||
message.success('Success!'); | ||
}; | ||
const showModal = () => { | ||
modal.warning({ | ||
title: 'This is a warning message', | ||
content: 'some messages...some messages...', | ||
}); | ||
}; | ||
const showNotification = () => { | ||
notification.info({ | ||
message: `Notification topLeft`, | ||
description: 'Hello, Ant Design Vue!!', | ||
placement: 'topLeft', | ||
}); | ||
}; | ||
</script> | ||
``` | ||
|
||
Note: App.useApp must be available under App. | ||
|
||
#### Embedded usage scenarios (if not necessary, try not to do nesting) | ||
|
||
```html | ||
<a-app> | ||
<a-space> | ||
... | ||
<a-app>...</a-app> | ||
</a-space> | ||
</a-app> | ||
``` | ||
|
||
#### Sequence with ConfigProvider | ||
|
||
The App component can only use the token in the `ConfigProvider`, if you need to use the Token, the ConfigProvider and the App component must appear in pairs. | ||
|
||
```html | ||
<a-config-provider theme="{{ ... }}"> | ||
<a-app>...</a-app> | ||
</a-config-provider> | ||
``` | ||
|
||
#### Global scene (pinia scene) | ||
|
||
```ts | ||
import { App } from 'ant-design-vue'; | ||
import type { MessageInstance } from 'ant-design-vue/es/message/interface'; | ||
import type { ModalStaticFunctions } from 'ant-design-vue/es/modal/confirm'; | ||
import type { NotificationInstance } from 'ant-design-vue/es/notification/interface'; | ||
|
||
export const useGloablStore = defineStore('global', () => { | ||
const message: MessageInstance = ref(); | ||
const notification: NotificationInstance = ref(); | ||
const modal: Omit<ModalStaticFunctions, 'warn'> = ref(); | ||
(() => { | ||
const staticFunction = App.useApp(); | ||
message.value = staticFunction.message; | ||
modal.value = staticFunction.modal; | ||
notification.value = staticFunction.notification; | ||
})(); | ||
|
||
return { message, notification, modal }; | ||
}); | ||
``` | ||
|
||
```html | ||
// sub page | ||
<template> | ||
<a-space> | ||
<a-button type="primary" @click="showMessage">Open message</a-button> | ||
</a-space> | ||
</template> | ||
|
||
<script setup> | ||
import { useGlobalStore } from '@/stores/global'; | ||
const global = useGlobalStore(); | ||
const showMessage = () => { | ||
global.message.success('Success!'); | ||
}; | ||
</script> | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import { defineComponent, computed } from 'vue'; | ||
import type { App as TypeApp, Plugin } from 'vue'; | ||
import { initDefaultProps } from '../_util/props-util'; | ||
import classNames from '../_util/classNames'; | ||
import { objectType } from '../_util/type'; | ||
import useConfigInject from '../config-provider/hooks/useConfigInject'; | ||
import useMessage from '../message/useMessage'; | ||
import useModal from '../modal/useModal'; | ||
import useNotification from '../notification/useNotification'; | ||
import type { AppConfig } from './context'; | ||
import { | ||
useProvideAppConfigContext, | ||
useInjectAppConfigContext, | ||
useProvideAppContext, | ||
useInjectAppContext, | ||
} from './context'; | ||
import useStyle from './style'; | ||
|
||
export const AppProps = () => { | ||
return { | ||
rootClassName: String, | ||
message: objectType<AppConfig['message']>(), | ||
notification: objectType<AppConfig['notification']>(), | ||
}; | ||
}; | ||
|
||
const useApp = () => { | ||
return useInjectAppContext(); | ||
}; | ||
|
||
const App = defineComponent({ | ||
name: 'AApp', | ||
props: initDefaultProps(AppProps(), {}), | ||
setup(props, { slots }) { | ||
const { prefixCls } = useConfigInject('app', props); | ||
const [wrapSSR, hashId] = useStyle(prefixCls); | ||
const customClassName = computed(() => { | ||
return classNames(hashId.value, prefixCls.value, props.rootClassName); | ||
}); | ||
|
||
const appConfig = useInjectAppConfigContext(); | ||
const mergedAppConfig = computed(() => ({ | ||
message: { ...appConfig.message, ...props.message }, | ||
notification: { ...appConfig.notification, ...props.notification }, | ||
})); | ||
useProvideAppConfigContext(mergedAppConfig.value); | ||
|
||
const [messageApi, messageContextHolder] = useMessage(mergedAppConfig.value.message); | ||
const [notificationApi, notificationContextHolder] = useNotification( | ||
mergedAppConfig.value.notification, | ||
); | ||
const [ModalApi, ModalContextHolder] = useModal(); | ||
|
||
const memoizedContextValue = computed(() => ({ | ||
message: messageApi, | ||
notification: notificationApi, | ||
modal: ModalApi, | ||
})); | ||
useProvideAppContext(memoizedContextValue.value); | ||
|
||
return () => { | ||
return wrapSSR( | ||
<div class={customClassName.value}> | ||
{ModalContextHolder()} | ||
{messageContextHolder()} | ||
{notificationContextHolder()} | ||
{slots.default?.()} | ||
</div>, | ||
); | ||
}; | ||
}, | ||
}); | ||
|
||
App.useApp = useApp; | ||
|
||
App.install = function (app: TypeApp) { | ||
app.component(App.name, App); | ||
}; | ||
|
||
export default App as typeof App & | ||
Plugin & { | ||
readonly useApp: typeof useApp; | ||
}; |
Oops, something went wrong.