feat: update modal

pull/2376/head
tangjinzhou 2020-06-15 23:47:49 +08:00
parent e2a7165508
commit 75e1661c16
7 changed files with 157 additions and 186 deletions

View File

@ -24,6 +24,7 @@ export default {
visible: PropTypes.bool, visible: PropTypes.bool,
}, },
data() { data() {
this._component = null;
const { visible } = this.$props; const { visible } = this.$props;
openCount = visible ? openCount + 1 : openCount; openCount = visible ? openCount + 1 : openCount;
return {}; return {};

View File

@ -3,108 +3,106 @@ import Dialog from './Modal';
import ActionButton from './ActionButton'; import ActionButton from './ActionButton';
import { getConfirmLocale } from './locale'; import { getConfirmLocale } from './locale';
export default { const ConfirmDialog = (_, { attrs }) => {
functional: true, const {
render(h, context) { icon,
const { props } = context; onCancel,
const { onOk,
icon, close,
onCancel, zIndex,
onOk, afterClose,
close, visible,
zIndex, keyboard,
afterClose, centered,
visible, getContainer,
keyboard, maskStyle,
centered, okButtonProps,
getContainer, cancelButtonProps,
maskStyle, closable = false,
okButtonProps, } = attrs;
cancelButtonProps, const okType = attrs.okType || 'primary';
closable = false, const prefixCls = attrs.prefixCls || 'ant-modal';
} = props; const contentPrefixCls = `${prefixCls}-confirm`;
const okType = props.okType || 'primary'; // true
const prefixCls = props.prefixCls || 'ant-modal'; const okCancel = 'okCancel' in attrs ? attrs.okCancel : true;
const contentPrefixCls = `${prefixCls}-confirm`; const width = attrs.width || 416;
// true const style = attrs.style || {};
const okCancel = 'okCancel' in props ? props.okCancel : true; const mask = attrs.mask === undefined ? true : attrs.mask;
const width = props.width || 416; // false
const style = props.style || {}; const maskClosable = attrs.maskClosable === undefined ? false : attrs.maskClosable;
const mask = props.mask === undefined ? true : props.mask; const runtimeLocale = getConfirmLocale();
// false const okText = attrs.okText || (okCancel ? runtimeLocale.okText : runtimeLocale.justOkText);
const maskClosable = props.maskClosable === undefined ? false : props.maskClosable; const cancelText = attrs.cancelText || runtimeLocale.cancelText;
const runtimeLocale = getConfirmLocale(); const autoFocusButton = attrs.autoFocusButton === null ? false : attrs.autoFocusButton || 'ok';
const okText = props.okText || (okCancel ? runtimeLocale.okText : runtimeLocale.justOkText); const transitionName = attrs.transitionName || 'zoom';
const cancelText = props.cancelText || runtimeLocale.cancelText; const maskTransitionName = attrs.maskTransitionName || 'fade';
const autoFocusButton = props.autoFocusButton === null ? false : props.autoFocusButton || 'ok';
const transitionName = props.transitionName || 'zoom';
const maskTransitionName = props.maskTransitionName || 'fade';
const classString = classNames( const classString = classNames(
contentPrefixCls, contentPrefixCls,
`${contentPrefixCls}-${props.type}`, `${contentPrefixCls}-${attrs.type}`,
`${prefixCls}-${props.type}`, `${prefixCls}-${attrs.type}`,
props.class, attrs.class,
); );
const cancelButton = okCancel && ( const cancelButton = okCancel && (
<ActionButton <ActionButton
actionFn={onCancel} actionFn={onCancel}
closeModal={close} closeModal={close}
autoFocus={autoFocusButton === 'cancel'} autoFocus={autoFocusButton === 'cancel'}
buttonProps={cancelButtonProps} buttonProps={cancelButtonProps}
> >
{cancelText} {cancelText}
</ActionButton> </ActionButton>
); );
return ( return (
<Dialog <Dialog
prefixCls={prefixCls} prefixCls={prefixCls}
class={classString} class={classString}
wrapClassName={classNames({ [`${contentPrefixCls}-centered`]: !!centered })} wrapClassName={classNames({ [`${contentPrefixCls}-centered`]: !!centered })}
onCancel={e => close({ triggerCancel: true }, e)} onCancel={e => close({ triggerCancel: true }, e)}
visible={visible} visible={visible}
closable={closable} closable={closable}
title="" title=""
transitionName={transitionName} transitionName={transitionName}
footer="" footer=""
maskTransitionName={maskTransitionName} maskTransitionName={maskTransitionName}
mask={mask} mask={mask}
maskClosable={maskClosable} maskClosable={maskClosable}
maskStyle={maskStyle} maskStyle={maskStyle}
style={style} style={style}
width={width} width={width}
zIndex={zIndex} zIndex={zIndex}
afterClose={afterClose} afterClose={afterClose}
keyboard={keyboard} keyboard={keyboard}
centered={centered} centered={centered}
getContainer={getContainer} getContainer={getContainer}
> >
<div class={`${contentPrefixCls}-body-wrapper`}> <div class={`${contentPrefixCls}-body-wrapper`}>
<div class={`${contentPrefixCls}-body`}> <div class={`${contentPrefixCls}-body`}>
{typeof icon === 'function' ? icon(h) : icon} {typeof icon === 'function' ? icon() : icon}
{props.title === undefined ? null : ( {attrs.title === undefined ? null : (
<span class={`${contentPrefixCls}-title`}>{props.title}</span> <span class={`${contentPrefixCls}-title`}>{attrs.title}</span>
)} )}
<div class={`${contentPrefixCls}-content`}> <div class={`${contentPrefixCls}-content`}>
{typeof props.content === 'function' ? props.content(h) : props.content} {typeof attrs.content === 'function' ? attrs.content() : attrs.content}
</div>
</div>
<div class={`${contentPrefixCls}-btns`}>
{cancelButton}
<ActionButton
type={okType}
actionFn={onOk}
closeModal={close}
autoFocus={autoFocusButton === 'ok'}
buttonProps={okButtonProps}
>
{okText}
</ActionButton>
</div> </div>
</div> </div>
</Dialog> <div class={`${contentPrefixCls}-btns`}>
); {cancelButton}
}, <ActionButton
type={okType}
actionFn={onOk}
closeModal={close}
autoFocus={autoFocusButton === 'ok'}
buttonProps={okButtonProps}
>
{okText}
</ActionButton>
</div>
</div>
</Dialog>
);
}; };
ConfirmDialog.inheritAttrs = false;
export default ConfirmDialog;

View File

@ -1,3 +1,4 @@
import { inject } from 'vue';
import classNames from 'classnames'; import classNames from 'classnames';
import Dialog from '../vc-dialog'; import Dialog from '../vc-dialog';
import PropTypes from '../_util/vue-types'; import PropTypes from '../_util/vue-types';
@ -8,14 +9,7 @@ import Button from '../button';
import buttonTypes from '../button/buttonTypes'; import buttonTypes from '../button/buttonTypes';
const ButtonType = buttonTypes().type; const ButtonType = buttonTypes().type;
import LocaleReceiver from '../locale-provider/LocaleReceiver'; import LocaleReceiver from '../locale-provider/LocaleReceiver';
import { import { initDefaultProps, getComponent, getSlot } from '../_util/props-util';
initDefaultProps,
getComponentFromProp,
getClass,
getStyle,
mergeProps,
getListeners,
} from '../_util/props-util';
import { ConfigConsumerProps } from '../config-provider'; import { ConfigConsumerProps } from '../config-provider';
let mousePosition = null; let mousePosition = null;
@ -116,8 +110,10 @@ export default {
this.sVisible = val; this.sVisible = val;
}, },
}, },
inject: { setup() {
configProvider: { default: () => ConfigConsumerProps }, return {
configProvider: inject('configProvider', ConfigConsumerProps),
};
}, },
// static info: ModalFunc; // static info: ModalFunc;
// static success: ModalFunc; // static success: ModalFunc;
@ -128,6 +124,7 @@ export default {
methods: { methods: {
handleCancel(e) { handleCancel(e) {
this.$emit('cancel', e); this.$emit('cancel', e);
this.$emit('update:visible', false);
this.$emit('change', false); this.$emit('change', false);
}, },
@ -136,26 +133,19 @@ export default {
}, },
renderFooter(locale) { renderFooter(locale) {
const { okType, confirmLoading } = this; const { okType, confirmLoading } = this;
const cancelBtnProps = mergeProps( const cancelBtnProps = { onClick: this.handleCancel, ...(this.cancelButtonProps || {}) };
{ on: { click: this.handleCancel } }, const okBtnProps = {
this.cancelButtonProps || {}, onClick: this.handleOk,
); type: okType,
const okBtnProps = mergeProps( loading: confirmLoading,
{ ...(this.okButtonProps || {}),
on: { click: this.handleOk }, };
props: {
type: okType,
loading: confirmLoading,
},
},
this.okButtonProps || {},
);
return ( return (
<div> <div>
<Button {...cancelBtnProps}> <Button {...cancelBtnProps}>
{getComponentFromProp(this, 'cancelText') || locale.cancelText} {getComponent(this, 'cancelText') || locale.cancelText}
</Button> </Button>
<Button {...okBtnProps}>{getComponentFromProp(this, 'okText') || locale.okText}</Button> <Button {...okBtnProps}>{getComponent(this, 'okText') || locale.okText}</Button>
</div> </div>
); );
}, },
@ -168,11 +158,9 @@ export default {
wrapClassName, wrapClassName,
centered, centered,
getContainer, getContainer,
$slots,
$scopedSlots,
$attrs, $attrs,
} = this; } = this;
const children = $scopedSlots.default ? $scopedSlots.default() : $slots.default; const children = getSlot(this);
const { getPrefixCls, getPopupContainer: getContextPopupContainer } = this.configProvider; const { getPrefixCls, getPopupContainer: getContextPopupContainer } = this.configProvider;
const prefixCls = getPrefixCls('modal', customizePrefixCls); const prefixCls = getPrefixCls('modal', customizePrefixCls);
@ -180,36 +168,29 @@ export default {
<LocaleReceiver <LocaleReceiver
componentName="Modal" componentName="Modal"
defaultLocale={getConfirmLocale()} defaultLocale={getConfirmLocale()}
scopedSlots={{ default: this.renderFooter }} children={this.renderFooter}
/> />
); );
const closeIcon = getComponentFromProp(this, 'closeIcon'); const closeIcon = getComponent(this, 'closeIcon');
const closeIconToRender = ( const closeIconToRender = (
<span class={`${prefixCls}-close-x`}> <span class={`${prefixCls}-close-x`}>
{closeIcon || <CloseOutlined class={`${prefixCls}-close-icon`} />} {closeIcon || <CloseOutlined class={`${prefixCls}-close-icon`} />}
</span> </span>
); );
const footer = getComponentFromProp(this, 'footer'); const footer = getComponent(this, 'footer');
const title = getComponentFromProp(this, 'title'); const title = getComponent(this, 'title');
const dialogProps = { const dialogProps = {
props: { ...this.$props,
...this.$props, ...$attrs,
getContainer: getContainer === undefined ? getContextPopupContainer : getContainer, getContainer: getContainer === undefined ? getContextPopupContainer : getContainer,
prefixCls, prefixCls,
wrapClassName: classNames({ [`${prefixCls}-centered`]: !!centered }, wrapClassName), wrapClassName: classNames({ [`${prefixCls}-centered`]: !!centered }, wrapClassName),
title, title,
footer: footer === undefined ? defaultFooter : footer, footer: footer === undefined ? defaultFooter : footer,
visible, visible,
mousePosition, mousePosition,
closeIcon: closeIconToRender, closeIcon: closeIconToRender,
}, onClose: this.handleCancel,
on: {
...getListeners(this),
close: this.handleCancel,
},
class: getClass(this),
style: getStyle(this),
attrs: $attrs,
}; };
return <Dialog {...dialogProps}>{children}</Dialog>; return <Dialog {...dialogProps}>{children}</Dialog>;
}, },

View File

@ -1,7 +1,7 @@
import Vue from 'vue'; import { createApp } from 'vue';
import ConfirmDialog from './ConfirmDialog'; import ConfirmDialog from './ConfirmDialog';
import { destroyFns } from './Modal'; import { destroyFns } from './Modal';
import Base from '../base';
import Omit from 'omit.js'; import Omit from 'omit.js';
export default function confirm(config) { export default function confirm(config) {
@ -12,7 +12,7 @@ export default function confirm(config) {
let currentConfig = { ...Omit(config, ['parentContext']), close, visible: true }; let currentConfig = { ...Omit(config, ['parentContext']), close, visible: true };
let confirmDialogInstance = null; let confirmDialogInstance = null;
const confirmDialogProps = { props: {} }; let confirmDialogProps = {};
function close(...args) { function close(...args) {
destroy(...args); destroy(...args);
} }
@ -21,11 +21,11 @@ export default function confirm(config) {
...currentConfig, ...currentConfig,
...newConfig, ...newConfig,
}; };
confirmDialogProps.props = currentConfig; Object.assign(confirmDialogInstance, currentConfig);
} }
function destroy(...args) { function destroy(...args) {
if (confirmDialogInstance && div.parentNode) { if (confirmDialogInstance && div.parentNode) {
confirmDialogInstance.$destroy(); confirmDialogInstance.unmount(div);
confirmDialogInstance = null; confirmDialogInstance = null;
div.parentNode.removeChild(div); div.parentNode.removeChild(div);
} }
@ -43,10 +43,8 @@ export default function confirm(config) {
} }
function render(props) { function render(props) {
confirmDialogProps.props = props; confirmDialogProps = props;
const V = Base.Vue || Vue; return createApp({
return new V({
el,
parent: config.parentContext, parent: config.parentContext,
data() { data() {
return { confirmDialogProps }; return { confirmDialogProps };
@ -56,7 +54,7 @@ export default function confirm(config) {
const cdProps = { ...this.confirmDialogProps }; const cdProps = { ...this.confirmDialogProps };
return <ConfirmDialog {...cdProps} />; return <ConfirmDialog {...cdProps} />;
}, },
}); }).mount(el);
} }
confirmDialogInstance = render(currentConfig); confirmDialogInstance = render(currentConfig);

View File

@ -4,7 +4,6 @@ import InfoCircleOutlined from '@ant-design/icons-vue/InfoCircleOutlined';
import CheckCircleOutlined from '@ant-design/icons-vue/CheckCircleOutlined'; import CheckCircleOutlined from '@ant-design/icons-vue/CheckCircleOutlined';
import CloseCircleOutlined from '@ant-design/icons-vue/CloseCircleOutlined'; import CloseCircleOutlined from '@ant-design/icons-vue/CloseCircleOutlined';
import ExclamationCircleOutlined from '@ant-design/icons-vue/ExclamationCircleOutlined'; import ExclamationCircleOutlined from '@ant-design/icons-vue/ExclamationCircleOutlined';
import Base from '../base';
// export { ActionButtonProps } from './ActionButton' // export { ActionButtonProps } from './ActionButton'
// export { ModalProps, ModalFuncProps } from './Modal' // export { ModalProps, ModalFuncProps } from './Modal'
@ -12,9 +11,7 @@ import Base from '../base';
const info = function(props) { const info = function(props) {
const config = { const config = {
type: 'info', type: 'info',
icon: h => { icon: <InfoCircleOutlined />,
return <InfoCircleOutlined />;
},
okCancel: false, okCancel: false,
...props, ...props,
}; };
@ -24,9 +21,7 @@ const info = function(props) {
const success = function(props) { const success = function(props) {
const config = { const config = {
type: 'success', type: 'success',
icon: h => { icon: <CheckCircleOutlined />,
return <CheckCircleOutlined />;
},
okCancel: false, okCancel: false,
...props, ...props,
}; };
@ -36,9 +31,7 @@ const success = function(props) {
const error = function(props) { const error = function(props) {
const config = { const config = {
type: 'error', type: 'error',
icon: h => { icon: <CloseCircleOutlined />,
return <CloseCircleOutlined />;
},
okCancel: false, okCancel: false,
...props, ...props,
}; };
@ -48,9 +41,7 @@ const error = function(props) {
const warning = function(props) { const warning = function(props) {
const config = { const config = {
type: 'warning', type: 'warning',
icon: h => { icon: <ExclamationCircleOutlined />,
return <ExclamationCircleOutlined />;
},
okCancel: false, okCancel: false,
...props, ...props,
}; };
@ -83,9 +74,8 @@ Modal.destroyAll = function destroyAllFn() {
}; };
/* istanbul ignore next */ /* istanbul ignore next */
Modal.install = function(Vue) { Modal.install = function(app) {
Vue.use(Base); app.component(Modal.name, Modal);
Vue.component(Modal.name, Modal);
}; };
export default Modal; export default Modal;

View File

@ -1,5 +1,5 @@
import { provide, Transition } from 'vue'; import { provide, Transition } from 'vue';
import { initDefaultProps } from '../_util/props-util'; import { initDefaultProps, getSlot } from '../_util/props-util';
import KeyCode from '../_util/KeyCode'; import KeyCode from '../_util/KeyCode';
import contains from '../vc-util/Dom/contains'; import contains from '../vc-util/Dom/contains';
import LazyRenderBox from './LazyRenderBox'; import LazyRenderBox from './LazyRenderBox';
@ -49,6 +49,7 @@ function offset(el) {
let cacheOverflow = {}; let cacheOverflow = {};
export default { export default {
name: 'VcDialog',
mixins: [BaseMixin], mixins: [BaseMixin],
props: initDefaultProps(IDialogPropTypes, { props: initDefaultProps(IDialogPropTypes, {
mask: true, mask: true,
@ -64,6 +65,9 @@ export default {
data() { data() {
return { return {
destroyPopup: false, destroyPopup: false,
inTransition: false,
titleId: `rcDialogTitle${uuid++}`,
dialogMouseDown: undefined,
}; };
}, },
@ -80,11 +84,6 @@ export default {
created() { created() {
provide('dialogContext', this); provide('dialogContext', this);
}, },
beforeMount() {
this.inTransition = false;
this.titleId = `rcDialogTitle${uuid++}`;
},
mounted() { mounted() {
this.$nextTick(() => { this.$nextTick(() => {
this.updatedCallback(false); this.updatedCallback(false);
@ -285,7 +284,7 @@ export default {
{closer} {closer}
{header} {header}
<div key="body" class={`${prefixCls}-body`} style={bodyStyle} ref="body" {...bodyProps}> <div key="body" class={`${prefixCls}-body`} style={bodyStyle} ref="body" {...bodyProps}>
{this.$slots.default} {getSlot(this)}
</div> </div>
{footer} {footer}
</div> </div>
@ -320,22 +319,24 @@ export default {
let maskElement; let maskElement;
if (props.mask) { if (props.mask) {
const maskTransition = this.getMaskTransitionName(); const maskTransition = this.getMaskTransitionName();
maskElement = ( const tempMaskElement = (
<LazyRenderBox <LazyRenderBox
v-show={props.visible} v-show={props.visible}
style={this.getMaskStyle()} style={this.getMaskStyle()}
key="mask" key="mask"
class={`${props.prefixCls}-mask`} class={`${props.prefixCls}-mask`}
{...props.maskProps} {...(props.maskProps || {})}
/> />
); );
if (maskTransition) { if (maskTransition) {
const maskTransitionProps = getTransitionProps(maskTransition); const maskTransitionProps = getTransitionProps(maskTransition);
maskElement = ( maskElement = (
<Transition key="mask" {...maskTransitionProps}> <Transition key="mask" {...maskTransitionProps}>
{maskElement} {tempMaskElement}
</Transition> </Transition>
); );
} else {
maskElement = tempMaskElement;
} }
} }
return maskElement; return maskElement;

View File

@ -28,6 +28,7 @@ import Popconfirm from 'ant-design-vue/popconfirm';
import Popover from 'ant-design-vue/popover'; import Popover from 'ant-design-vue/popover';
import notification from 'ant-design-vue/notification'; import notification from 'ant-design-vue/notification';
import message from 'ant-design-vue/message'; import message from 'ant-design-vue/message';
import Modal from 'ant-design-vue/modal';
import 'ant-design-vue/style.js'; import 'ant-design-vue/style.js';
const app = createApp(App); const app = createApp(App);
@ -59,4 +60,5 @@ app
.use(Tag) .use(Tag)
.use(Popconfirm) .use(Popconfirm)
.use(Popover) .use(Popover)
.use(Modal)
.mount('#app'); .mount('#app');