diff --git a/components/_util/PortalWrapper.js b/components/_util/PortalWrapper.js index 924fab2dd..fc897219b 100644 --- a/components/_util/PortalWrapper.js +++ b/components/_util/PortalWrapper.js @@ -24,6 +24,7 @@ export default { visible: PropTypes.bool, }, data() { + this._component = null; const { visible } = this.$props; openCount = visible ? openCount + 1 : openCount; return {}; diff --git a/components/modal/ConfirmDialog.jsx b/components/modal/ConfirmDialog.jsx index a7162237d..38007f544 100644 --- a/components/modal/ConfirmDialog.jsx +++ b/components/modal/ConfirmDialog.jsx @@ -3,108 +3,106 @@ import Dialog from './Modal'; import ActionButton from './ActionButton'; import { getConfirmLocale } from './locale'; -export default { - functional: true, - render(h, context) { - const { props } = context; - const { - icon, - onCancel, - onOk, - close, - zIndex, - afterClose, - visible, - keyboard, - centered, - getContainer, - maskStyle, - okButtonProps, - cancelButtonProps, - closable = false, - } = props; - const okType = props.okType || 'primary'; - const prefixCls = props.prefixCls || 'ant-modal'; - const contentPrefixCls = `${prefixCls}-confirm`; - // 默认为 true,保持向下兼容 - const okCancel = 'okCancel' in props ? props.okCancel : true; - const width = props.width || 416; - const style = props.style || {}; - const mask = props.mask === undefined ? true : props.mask; - // 默认为 false,保持旧版默认行为 - const maskClosable = props.maskClosable === undefined ? false : props.maskClosable; - const runtimeLocale = getConfirmLocale(); - const okText = props.okText || (okCancel ? runtimeLocale.okText : runtimeLocale.justOkText); - const cancelText = props.cancelText || runtimeLocale.cancelText; - const autoFocusButton = props.autoFocusButton === null ? false : props.autoFocusButton || 'ok'; - const transitionName = props.transitionName || 'zoom'; - const maskTransitionName = props.maskTransitionName || 'fade'; +const ConfirmDialog = (_, { attrs }) => { + const { + icon, + onCancel, + onOk, + close, + zIndex, + afterClose, + visible, + keyboard, + centered, + getContainer, + maskStyle, + okButtonProps, + cancelButtonProps, + closable = false, + } = attrs; + const okType = attrs.okType || 'primary'; + const prefixCls = attrs.prefixCls || 'ant-modal'; + const contentPrefixCls = `${prefixCls}-confirm`; + // 默认为 true,保持向下兼容 + const okCancel = 'okCancel' in attrs ? attrs.okCancel : true; + const width = attrs.width || 416; + const style = attrs.style || {}; + const mask = attrs.mask === undefined ? true : attrs.mask; + // 默认为 false,保持旧版默认行为 + const maskClosable = attrs.maskClosable === undefined ? false : attrs.maskClosable; + const runtimeLocale = getConfirmLocale(); + const okText = attrs.okText || (okCancel ? runtimeLocale.okText : runtimeLocale.justOkText); + const cancelText = attrs.cancelText || runtimeLocale.cancelText; + const autoFocusButton = attrs.autoFocusButton === null ? false : attrs.autoFocusButton || 'ok'; + const transitionName = attrs.transitionName || 'zoom'; + const maskTransitionName = attrs.maskTransitionName || 'fade'; - const classString = classNames( - contentPrefixCls, - `${contentPrefixCls}-${props.type}`, - `${prefixCls}-${props.type}`, - props.class, - ); + const classString = classNames( + contentPrefixCls, + `${contentPrefixCls}-${attrs.type}`, + `${prefixCls}-${attrs.type}`, + attrs.class, + ); - const cancelButton = okCancel && ( - - {cancelText} - - ); + const cancelButton = okCancel && ( + + {cancelText} + + ); - return ( - close({ triggerCancel: true }, e)} - visible={visible} - closable={closable} - title="" - transitionName={transitionName} - footer="" - maskTransitionName={maskTransitionName} - mask={mask} - maskClosable={maskClosable} - maskStyle={maskStyle} - style={style} - width={width} - zIndex={zIndex} - afterClose={afterClose} - keyboard={keyboard} - centered={centered} - getContainer={getContainer} - > -
-
- {typeof icon === 'function' ? icon(h) : icon} - {props.title === undefined ? null : ( - {props.title} - )} -
- {typeof props.content === 'function' ? props.content(h) : props.content} -
-
-
- {cancelButton} - - {okText} - + return ( + close({ triggerCancel: true }, e)} + visible={visible} + closable={closable} + title="" + transitionName={transitionName} + footer="" + maskTransitionName={maskTransitionName} + mask={mask} + maskClosable={maskClosable} + maskStyle={maskStyle} + style={style} + width={width} + zIndex={zIndex} + afterClose={afterClose} + keyboard={keyboard} + centered={centered} + getContainer={getContainer} + > +
+
+ {typeof icon === 'function' ? icon() : icon} + {attrs.title === undefined ? null : ( + {attrs.title} + )} +
+ {typeof attrs.content === 'function' ? attrs.content() : attrs.content}
-
- ); - }, +
+ {cancelButton} + + {okText} + +
+
+
+ ); }; +ConfirmDialog.inheritAttrs = false; +export default ConfirmDialog; diff --git a/components/modal/Modal.jsx b/components/modal/Modal.jsx index 16e08f41a..47f24c553 100644 --- a/components/modal/Modal.jsx +++ b/components/modal/Modal.jsx @@ -1,3 +1,4 @@ +import { inject } from 'vue'; import classNames from 'classnames'; import Dialog from '../vc-dialog'; import PropTypes from '../_util/vue-types'; @@ -8,14 +9,7 @@ import Button from '../button'; import buttonTypes from '../button/buttonTypes'; const ButtonType = buttonTypes().type; import LocaleReceiver from '../locale-provider/LocaleReceiver'; -import { - initDefaultProps, - getComponentFromProp, - getClass, - getStyle, - mergeProps, - getListeners, -} from '../_util/props-util'; +import { initDefaultProps, getComponent, getSlot } from '../_util/props-util'; import { ConfigConsumerProps } from '../config-provider'; let mousePosition = null; @@ -116,8 +110,10 @@ export default { this.sVisible = val; }, }, - inject: { - configProvider: { default: () => ConfigConsumerProps }, + setup() { + return { + configProvider: inject('configProvider', ConfigConsumerProps), + }; }, // static info: ModalFunc; // static success: ModalFunc; @@ -128,6 +124,7 @@ export default { methods: { handleCancel(e) { this.$emit('cancel', e); + this.$emit('update:visible', false); this.$emit('change', false); }, @@ -136,26 +133,19 @@ export default { }, renderFooter(locale) { const { okType, confirmLoading } = this; - const cancelBtnProps = mergeProps( - { on: { click: this.handleCancel } }, - this.cancelButtonProps || {}, - ); - const okBtnProps = mergeProps( - { - on: { click: this.handleOk }, - props: { - type: okType, - loading: confirmLoading, - }, - }, - this.okButtonProps || {}, - ); + const cancelBtnProps = { onClick: this.handleCancel, ...(this.cancelButtonProps || {}) }; + const okBtnProps = { + onClick: this.handleOk, + type: okType, + loading: confirmLoading, + ...(this.okButtonProps || {}), + }; return (
- +
); }, @@ -168,11 +158,9 @@ export default { wrapClassName, centered, getContainer, - $slots, - $scopedSlots, $attrs, } = this; - const children = $scopedSlots.default ? $scopedSlots.default() : $slots.default; + const children = getSlot(this); const { getPrefixCls, getPopupContainer: getContextPopupContainer } = this.configProvider; const prefixCls = getPrefixCls('modal', customizePrefixCls); @@ -180,36 +168,29 @@ export default { ); - const closeIcon = getComponentFromProp(this, 'closeIcon'); + const closeIcon = getComponent(this, 'closeIcon'); const closeIconToRender = ( {closeIcon || } ); - const footer = getComponentFromProp(this, 'footer'); - const title = getComponentFromProp(this, 'title'); + const footer = getComponent(this, 'footer'); + const title = getComponent(this, 'title'); const dialogProps = { - props: { - ...this.$props, - getContainer: getContainer === undefined ? getContextPopupContainer : getContainer, - prefixCls, - wrapClassName: classNames({ [`${prefixCls}-centered`]: !!centered }, wrapClassName), - title, - footer: footer === undefined ? defaultFooter : footer, - visible, - mousePosition, - closeIcon: closeIconToRender, - }, - on: { - ...getListeners(this), - close: this.handleCancel, - }, - class: getClass(this), - style: getStyle(this), - attrs: $attrs, + ...this.$props, + ...$attrs, + getContainer: getContainer === undefined ? getContextPopupContainer : getContainer, + prefixCls, + wrapClassName: classNames({ [`${prefixCls}-centered`]: !!centered }, wrapClassName), + title, + footer: footer === undefined ? defaultFooter : footer, + visible, + mousePosition, + closeIcon: closeIconToRender, + onClose: this.handleCancel, }; return {children}; }, diff --git a/components/modal/confirm.js b/components/modal/confirm.js index 9eabc437c..5ffee6215 100644 --- a/components/modal/confirm.js +++ b/components/modal/confirm.js @@ -1,7 +1,7 @@ -import Vue from 'vue'; +import { createApp } from 'vue'; import ConfirmDialog from './ConfirmDialog'; import { destroyFns } from './Modal'; -import Base from '../base'; + import Omit from 'omit.js'; export default function confirm(config) { @@ -12,7 +12,7 @@ export default function confirm(config) { let currentConfig = { ...Omit(config, ['parentContext']), close, visible: true }; let confirmDialogInstance = null; - const confirmDialogProps = { props: {} }; + let confirmDialogProps = {}; function close(...args) { destroy(...args); } @@ -21,11 +21,11 @@ export default function confirm(config) { ...currentConfig, ...newConfig, }; - confirmDialogProps.props = currentConfig; + Object.assign(confirmDialogInstance, currentConfig); } function destroy(...args) { if (confirmDialogInstance && div.parentNode) { - confirmDialogInstance.$destroy(); + confirmDialogInstance.unmount(div); confirmDialogInstance = null; div.parentNode.removeChild(div); } @@ -43,10 +43,8 @@ export default function confirm(config) { } function render(props) { - confirmDialogProps.props = props; - const V = Base.Vue || Vue; - return new V({ - el, + confirmDialogProps = props; + return createApp({ parent: config.parentContext, data() { return { confirmDialogProps }; @@ -56,7 +54,7 @@ export default function confirm(config) { const cdProps = { ...this.confirmDialogProps }; return ; }, - }); + }).mount(el); } confirmDialogInstance = render(currentConfig); diff --git a/components/modal/index.js b/components/modal/index.js index e2b5e3dbe..d5cb8e6f2 100644 --- a/components/modal/index.js +++ b/components/modal/index.js @@ -4,7 +4,6 @@ import InfoCircleOutlined from '@ant-design/icons-vue/InfoCircleOutlined'; import CheckCircleOutlined from '@ant-design/icons-vue/CheckCircleOutlined'; import CloseCircleOutlined from '@ant-design/icons-vue/CloseCircleOutlined'; import ExclamationCircleOutlined from '@ant-design/icons-vue/ExclamationCircleOutlined'; -import Base from '../base'; // export { ActionButtonProps } from './ActionButton' // export { ModalProps, ModalFuncProps } from './Modal' @@ -12,9 +11,7 @@ import Base from '../base'; const info = function(props) { const config = { type: 'info', - icon: h => { - return ; - }, + icon: , okCancel: false, ...props, }; @@ -24,9 +21,7 @@ const info = function(props) { const success = function(props) { const config = { type: 'success', - icon: h => { - return ; - }, + icon: , okCancel: false, ...props, }; @@ -36,9 +31,7 @@ const success = function(props) { const error = function(props) { const config = { type: 'error', - icon: h => { - return ; - }, + icon: , okCancel: false, ...props, }; @@ -48,9 +41,7 @@ const error = function(props) { const warning = function(props) { const config = { type: 'warning', - icon: h => { - return ; - }, + icon: , okCancel: false, ...props, }; @@ -83,9 +74,8 @@ Modal.destroyAll = function destroyAllFn() { }; /* istanbul ignore next */ -Modal.install = function(Vue) { - Vue.use(Base); - Vue.component(Modal.name, Modal); +Modal.install = function(app) { + app.component(Modal.name, Modal); }; export default Modal; diff --git a/components/vc-dialog/Dialog.jsx b/components/vc-dialog/Dialog.jsx index 39bb1af6e..a7f057eca 100644 --- a/components/vc-dialog/Dialog.jsx +++ b/components/vc-dialog/Dialog.jsx @@ -1,5 +1,5 @@ import { provide, Transition } from 'vue'; -import { initDefaultProps } from '../_util/props-util'; +import { initDefaultProps, getSlot } from '../_util/props-util'; import KeyCode from '../_util/KeyCode'; import contains from '../vc-util/Dom/contains'; import LazyRenderBox from './LazyRenderBox'; @@ -49,6 +49,7 @@ function offset(el) { let cacheOverflow = {}; export default { + name: 'VcDialog', mixins: [BaseMixin], props: initDefaultProps(IDialogPropTypes, { mask: true, @@ -64,6 +65,9 @@ export default { data() { return { destroyPopup: false, + inTransition: false, + titleId: `rcDialogTitle${uuid++}`, + dialogMouseDown: undefined, }; }, @@ -80,11 +84,6 @@ export default { created() { provide('dialogContext', this); }, - - beforeMount() { - this.inTransition = false; - this.titleId = `rcDialogTitle${uuid++}`; - }, mounted() { this.$nextTick(() => { this.updatedCallback(false); @@ -285,7 +284,7 @@ export default { {closer} {header}
- {this.$slots.default} + {getSlot(this)}
{footer} @@ -320,22 +319,24 @@ export default { let maskElement; if (props.mask) { const maskTransition = this.getMaskTransitionName(); - maskElement = ( + const tempMaskElement = ( ); if (maskTransition) { const maskTransitionProps = getTransitionProps(maskTransition); maskElement = ( - {maskElement} + {tempMaskElement} ); + } else { + maskElement = tempMaskElement; } } return maskElement; diff --git a/examples/index.js b/examples/index.js index 895ad05ab..ec941d450 100644 --- a/examples/index.js +++ b/examples/index.js @@ -28,6 +28,7 @@ import Popconfirm from 'ant-design-vue/popconfirm'; import Popover from 'ant-design-vue/popover'; import notification from 'ant-design-vue/notification'; import message from 'ant-design-vue/message'; +import Modal from 'ant-design-vue/modal'; import 'ant-design-vue/style.js'; const app = createApp(App); @@ -59,4 +60,5 @@ app .use(Tag) .use(Popconfirm) .use(Popover) + .use(Modal) .mount('#app');