mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-23 09:52:57 +08:00
refactor(Dialog): refactor with composition api
This commit is contained in:
parent
902a1b7c63
commit
2b8284a227
@ -1,25 +1,32 @@
|
|||||||
|
import { reactive } from 'vue';
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
import { createNamespace, addUnit, pick } from '../utils';
|
import { createNamespace, addUnit, pick } from '../utils';
|
||||||
import { BORDER_TOP, BORDER_LEFT } from '../utils/constant';
|
import { BORDER_TOP, BORDER_LEFT } from '../utils/constant';
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
import Popup from '../popup';
|
import Popup, { popupSharedProps } from '../popup';
|
||||||
import Button from '../button';
|
import Button from '../button';
|
||||||
import ActionBar from '../action-bar';
|
import ActionBar from '../action-bar';
|
||||||
import ActionBarButton from '../action-bar-button';
|
import ActionBarButton from '../action-bar-button';
|
||||||
|
|
||||||
const [createComponent, bem, t] = createNamespace('dialog');
|
const [createComponent, bem, t] = createNamespace('dialog');
|
||||||
|
|
||||||
|
const popupKeys = [
|
||||||
|
...Object.keys(popupSharedProps),
|
||||||
|
'transition',
|
||||||
|
'closeOnPopstate',
|
||||||
|
];
|
||||||
|
|
||||||
export default createComponent({
|
export default createComponent({
|
||||||
props: {
|
props: {
|
||||||
show: Boolean,
|
...popupSharedProps,
|
||||||
title: String,
|
title: String,
|
||||||
theme: String,
|
theme: String,
|
||||||
width: [Number, String],
|
width: [Number, String],
|
||||||
message: String,
|
message: String,
|
||||||
className: null,
|
|
||||||
callback: Function,
|
callback: Function,
|
||||||
lazyRender: Boolean,
|
className: null,
|
||||||
beforeClose: Function,
|
beforeClose: Function,
|
||||||
messageAlign: String,
|
messageAlign: String,
|
||||||
showCancelButton: Boolean,
|
showCancelButton: Boolean,
|
||||||
@ -28,10 +35,6 @@ export default createComponent({
|
|||||||
confirmButtonText: String,
|
confirmButtonText: String,
|
||||||
confirmButtonColor: String,
|
confirmButtonColor: String,
|
||||||
closeOnClickOverlay: Boolean,
|
closeOnClickOverlay: Boolean,
|
||||||
overlay: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true,
|
|
||||||
},
|
|
||||||
allowHtml: {
|
allowHtml: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: true,
|
||||||
@ -52,180 +55,160 @@ export default createComponent({
|
|||||||
|
|
||||||
emits: ['confirm', 'cancel', 'update:show'],
|
emits: ['confirm', 'cancel', 'update:show'],
|
||||||
|
|
||||||
data() {
|
setup(props, { emit, slots }) {
|
||||||
return {
|
const loading = reactive({
|
||||||
loading: {
|
|
||||||
confirm: false,
|
confirm: false,
|
||||||
cancel: false,
|
cancel: false,
|
||||||
},
|
});
|
||||||
|
|
||||||
|
const onUpdateShow = (value) => {
|
||||||
|
emit('update:show', value);
|
||||||
};
|
};
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
const close = (action) => {
|
||||||
onClickOverlay() {
|
onUpdateShow(false);
|
||||||
this.handleAction('overlay');
|
if (props.callback) {
|
||||||
},
|
props.callback(action);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
handleAction(action) {
|
const handleAction = (action) => {
|
||||||
this.$emit(action);
|
// should not trigger close event when hidden
|
||||||
|
if (!props.show) {
|
||||||
// show not trigger close event when hidden
|
|
||||||
if (!this.show) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.beforeClose) {
|
emit(action);
|
||||||
this.loading[action] = true;
|
|
||||||
this.beforeClose(action, (state) => {
|
|
||||||
if (state !== false && this.loading[action]) {
|
|
||||||
this.onClose(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.loading.confirm = false;
|
if (props.beforeClose) {
|
||||||
this.loading.cancel = false;
|
loading[action] = true;
|
||||||
|
props.beforeClose(action, (result) => {
|
||||||
|
if (result !== false && loading[action]) {
|
||||||
|
close(action);
|
||||||
|
}
|
||||||
|
loading[action] = false;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.onClose(action);
|
close(action);
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
|
|
||||||
onClose(action) {
|
const renderTitle = () => {
|
||||||
this.onUpdateShow(false);
|
const title = slots.title ? slots.title() : props.title;
|
||||||
|
if (title) {
|
||||||
if (this.callback) {
|
|
||||||
this.callback(action);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
onUpdateShow(value) {
|
|
||||||
this.$emit('update:show', value);
|
|
||||||
},
|
|
||||||
|
|
||||||
genRoundButtons() {
|
|
||||||
return (
|
return (
|
||||||
<ActionBar class={bem('footer')}>
|
<div
|
||||||
{this.showCancelButton && (
|
class={bem('header', {
|
||||||
<ActionBarButton
|
isolated: !props.message && !slots.default,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{title}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderContent = () => {
|
||||||
|
if (slots.default) {
|
||||||
|
return <div class={bem('content')}>{slots.default()}</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { title, message, allowHtml, messageAlign } = props;
|
||||||
|
if (message) {
|
||||||
|
return (
|
||||||
|
<div class={bem('content')}>
|
||||||
|
<div
|
||||||
|
class={bem('message', {
|
||||||
|
'has-title': slots.title || title,
|
||||||
|
[messageAlign]: messageAlign,
|
||||||
|
})}
|
||||||
|
{...{
|
||||||
|
[allowHtml ? 'innerHTML' : 'textContent']: message,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderButtons = () => (
|
||||||
|
<div class={[BORDER_TOP, bem('footer')]}>
|
||||||
|
{props.showCancelButton && (
|
||||||
|
<Button
|
||||||
size="large"
|
size="large"
|
||||||
type="warning"
|
text={props.cancelButtonText || t('cancel')}
|
||||||
text={this.cancelButtonText || t('cancel')}
|
|
||||||
class={bem('cancel')}
|
class={bem('cancel')}
|
||||||
color={this.cancelButtonColor}
|
style={{ color: props.cancelButtonColor }}
|
||||||
loading={this.loading.cancel}
|
loading={loading.cancel}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
this.handleAction('cancel');
|
handleAction('cancel');
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{this.showConfirmButton && (
|
{props.showConfirmButton && (
|
||||||
|
<Button
|
||||||
|
size="large"
|
||||||
|
text={props.confirmButtonText || t('confirm')}
|
||||||
|
class={[bem('confirm'), { [BORDER_LEFT]: props.showCancelButton }]}
|
||||||
|
style={{ color: props.confirmButtonColor }}
|
||||||
|
loading={loading.confirm}
|
||||||
|
onClick={() => {
|
||||||
|
handleAction('confirm');
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
const renderRoundButtons = () => (
|
||||||
|
<ActionBar class={bem('footer')}>
|
||||||
|
{props.showCancelButton && (
|
||||||
|
<ActionBarButton
|
||||||
|
size="large"
|
||||||
|
type="warning"
|
||||||
|
text={props.cancelButtonText || t('cancel')}
|
||||||
|
class={bem('cancel')}
|
||||||
|
color={props.cancelButtonColor}
|
||||||
|
loading={loading.cancel}
|
||||||
|
onClick={() => {
|
||||||
|
handleAction('cancel');
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{props.showConfirmButton && (
|
||||||
<ActionBarButton
|
<ActionBarButton
|
||||||
size="large"
|
size="large"
|
||||||
type="danger"
|
type="danger"
|
||||||
text={this.confirmButtonText || t('confirm')}
|
text={props.confirmButtonText || t('confirm')}
|
||||||
class={bem('confirm')}
|
class={bem('confirm')}
|
||||||
color={this.confirmButtonColor}
|
color={props.confirmButtonColor}
|
||||||
loading={this.loading.confirm}
|
loading={loading.confirm}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
this.handleAction('confirm');
|
handleAction('confirm');
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</ActionBar>
|
</ActionBar>
|
||||||
);
|
);
|
||||||
},
|
|
||||||
|
|
||||||
genButtons() {
|
|
||||||
const multiple = this.showCancelButton && this.showConfirmButton;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div class={[BORDER_TOP, bem('footer')]}>
|
|
||||||
{this.showCancelButton && (
|
|
||||||
<Button
|
|
||||||
size="large"
|
|
||||||
class={bem('cancel')}
|
|
||||||
loading={this.loading.cancel}
|
|
||||||
text={this.cancelButtonText || t('cancel')}
|
|
||||||
style={{ color: this.cancelButtonColor }}
|
|
||||||
onClick={() => {
|
|
||||||
this.handleAction('cancel');
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{this.showConfirmButton && (
|
|
||||||
<Button
|
|
||||||
size="large"
|
|
||||||
class={[bem('confirm'), { [BORDER_LEFT]: multiple }]}
|
|
||||||
loading={this.loading.confirm}
|
|
||||||
text={this.confirmButtonText || t('confirm')}
|
|
||||||
style={{ color: this.confirmButtonColor }}
|
|
||||||
onClick={() => {
|
|
||||||
this.handleAction('confirm');
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
genContent(hasTitle) {
|
|
||||||
if (this.$slots.default) {
|
|
||||||
return <div class={bem('content')}>{this.$slots.default()}</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { message, messageAlign } = this;
|
|
||||||
if (message) {
|
|
||||||
const data = {
|
|
||||||
class: bem('message', {
|
|
||||||
'has-title': hasTitle,
|
|
||||||
[messageAlign]: messageAlign,
|
|
||||||
}),
|
|
||||||
[this.allowHtml ? 'innerHTML' : 'textContent']: message,
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div class={bem('content')}>
|
|
||||||
<div {...data} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { message } = this;
|
|
||||||
const title = this.$slots.title ? this.$slots.title() : this.title;
|
|
||||||
const Title = title && (
|
|
||||||
<div
|
|
||||||
class={bem('header', { isolated: !message && !this.$slots.default })}
|
|
||||||
>
|
|
||||||
{title}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
const { width, title, theme, message, className } = props;
|
||||||
return (
|
return (
|
||||||
<Popup
|
<Popup
|
||||||
role="dialog"
|
role="dialog"
|
||||||
class={[bem([this.theme]), this.className]}
|
class={[bem([theme]), className]}
|
||||||
style={{ width: addUnit(this.width) }}
|
style={{ width: addUnit(width) }}
|
||||||
aria-labelledby={this.title || message}
|
aria-labelledby={title || message}
|
||||||
{...{
|
{...{
|
||||||
...pick(this, [
|
...pick(props, popupKeys),
|
||||||
'show',
|
'onUpdate:show': onUpdateShow,
|
||||||
'overlay',
|
|
||||||
'transition',
|
|
||||||
'lazyRender',
|
|
||||||
'closeOnPopstate',
|
|
||||||
'closeOnClickOverlay',
|
|
||||||
]),
|
|
||||||
'onUpdate:show': this.onUpdateShow,
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{Title}
|
{renderTitle()}
|
||||||
{this.genContent(title)}
|
{renderContent()}
|
||||||
{this.theme === 'round-button'
|
{theme === 'round-button' ? renderRoundButtons() : renderButtons()}
|
||||||
? this.genRoundButtons()
|
|
||||||
: this.genButtons()}
|
|
||||||
</Popup>
|
</Popup>
|
||||||
);
|
);
|
||||||
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -8,15 +8,7 @@ function initInstance() {
|
|||||||
const Wrapper = {
|
const Wrapper = {
|
||||||
setup() {
|
setup() {
|
||||||
const { state, toggle } = usePopupState();
|
const { state, toggle } = usePopupState();
|
||||||
return () => (
|
return () => <VanDialog {...{ ...state, 'onUpdate:show': toggle }} />;
|
||||||
<VanDialog
|
|
||||||
lazyRender={false}
|
|
||||||
{...{
|
|
||||||
...state,
|
|
||||||
'onUpdate:show': toggle,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user