mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
feat: migrate Toast component
This commit is contained in:
parent
17c64b24e7
commit
5d2cd516ed
@ -45,4 +45,5 @@ module.exports = [
|
||||
'sticky',
|
||||
'picker',
|
||||
'dialog',
|
||||
'toast',
|
||||
];
|
||||
|
@ -2,20 +2,18 @@
|
||||
import { createNamespace, isDef } from '../utils';
|
||||
import { lockClick } from './lock-click';
|
||||
|
||||
// Mixins
|
||||
import { PopupMixin } from '../mixins/popup';
|
||||
|
||||
// Components
|
||||
import Icon from '../icon';
|
||||
import Popup from '../popup';
|
||||
import Loading from '../loading';
|
||||
|
||||
const [createComponent, bem] = createNamespace('toast');
|
||||
|
||||
export default createComponent({
|
||||
mixins: [PopupMixin()],
|
||||
|
||||
props: {
|
||||
icon: String,
|
||||
show: Boolean,
|
||||
clear: Function,
|
||||
className: null,
|
||||
iconPrefix: String,
|
||||
loadingType: String,
|
||||
@ -40,6 +38,8 @@ export default createComponent({
|
||||
},
|
||||
},
|
||||
|
||||
emits: ['opened', 'closed', 'update:show'],
|
||||
|
||||
data() {
|
||||
return {
|
||||
clickable: false,
|
||||
@ -55,7 +55,7 @@ export default createComponent({
|
||||
},
|
||||
|
||||
watch: {
|
||||
value: 'toggleClickable',
|
||||
show: 'toggleClickable',
|
||||
forbidClick: 'toggleClickable',
|
||||
},
|
||||
|
||||
@ -67,7 +67,7 @@ export default createComponent({
|
||||
},
|
||||
|
||||
toggleClickable() {
|
||||
const clickable = this.value && this.forbidClick;
|
||||
const clickable = this.show && this.forbidClick;
|
||||
|
||||
if (this.clickable !== clickable) {
|
||||
this.clickable = clickable;
|
||||
@ -124,23 +124,20 @@ export default createComponent({
|
||||
|
||||
render() {
|
||||
return (
|
||||
<transition
|
||||
name={this.transition}
|
||||
onAfterEnter={this.onAfterEnter}
|
||||
onAfterLeave={this.onAfterLeave}
|
||||
<Popup
|
||||
show={this.show}
|
||||
class={[
|
||||
bem([this.position, { [this.type]: !this.icon }]),
|
||||
this.className,
|
||||
]}
|
||||
transition={this.transition}
|
||||
onOpened={this.onAfterEnter}
|
||||
onClosed={this.onAfterLeave}
|
||||
onClick={this.onClick}
|
||||
>
|
||||
<div
|
||||
vShow={this.value}
|
||||
class={[
|
||||
bem([this.position, { [this.type]: !this.icon }]),
|
||||
this.className,
|
||||
]}
|
||||
onClick={this.onClick}
|
||||
>
|
||||
{this.genIcon()}
|
||||
{this.genMessage()}
|
||||
</div>
|
||||
</transition>
|
||||
{this.genIcon()}
|
||||
{this.genMessage()}
|
||||
</Popup>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
@ -1,14 +1,10 @@
|
||||
import Vue from 'vue';
|
||||
import VueToast from './Toast';
|
||||
import { isObject, isServer } from '../utils';
|
||||
import { removeNode } from '../utils/dom/node';
|
||||
import { createApp, nextTick } from 'vue';
|
||||
import VanToast from './Toast';
|
||||
import { isObject, inBrowser } from '../utils';
|
||||
|
||||
const defaultOptions = {
|
||||
icon: '',
|
||||
type: 'text',
|
||||
// @deprecated
|
||||
mask: false,
|
||||
value: true,
|
||||
message: '',
|
||||
className: '',
|
||||
overlay: false,
|
||||
@ -45,18 +41,69 @@ function parseOptions(message) {
|
||||
|
||||
function createInstance() {
|
||||
/* istanbul ignore if */
|
||||
if (isServer) {
|
||||
if (!inBrowser) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!queue.length || multiple) {
|
||||
const toast = new (Vue.extend(VueToast))({
|
||||
el: document.createElement('div'),
|
||||
const root = document.createElement('div');
|
||||
document.body.appendChild(root);
|
||||
|
||||
const app = createApp({
|
||||
data() {
|
||||
return {
|
||||
timer: null,
|
||||
toastProps: {
|
||||
show: false,
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
clear() {
|
||||
this.toggle(false);
|
||||
},
|
||||
toggle(show, duration) {
|
||||
this.toastProps.show = show;
|
||||
|
||||
if (show) {
|
||||
clearTimeout(this.timer);
|
||||
|
||||
if (duration > 0) {
|
||||
this.timer = setTimeout(() => {
|
||||
this.clear();
|
||||
}, duration);
|
||||
}
|
||||
}
|
||||
},
|
||||
setProps(props) {
|
||||
this.toastProps = {
|
||||
...props,
|
||||
duration: undefined,
|
||||
};
|
||||
},
|
||||
onClosed() {
|
||||
if (multiple && inBrowser) {
|
||||
clearTimeout(this.timer);
|
||||
queue = queue.filter((item) => item !== this);
|
||||
app.unmount();
|
||||
document.body.removeChild(root);
|
||||
}
|
||||
},
|
||||
},
|
||||
render() {
|
||||
return (
|
||||
<VanToast
|
||||
{...{
|
||||
...this.toastProps,
|
||||
onClosed: this.onClosed,
|
||||
'onUpdate:show': this.toggle,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
toast.$on('input', (value) => {
|
||||
toast.value = value;
|
||||
});
|
||||
const toast = app.mount(root);
|
||||
|
||||
queue.push(toast);
|
||||
}
|
||||
@ -64,16 +111,6 @@ function createInstance() {
|
||||
return queue[queue.length - 1];
|
||||
}
|
||||
|
||||
// transform toast options to popup props
|
||||
function transformOptions(options) {
|
||||
return {
|
||||
...options,
|
||||
overlay: options.mask || options.overlay,
|
||||
mask: undefined,
|
||||
duration: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
function Toast(options = {}) {
|
||||
const toast = createInstance();
|
||||
|
||||
@ -89,32 +126,11 @@ function Toast(options = {}) {
|
||||
...options,
|
||||
};
|
||||
|
||||
options.clear = () => {
|
||||
toast.value = false;
|
||||
toast.setProps(options);
|
||||
|
||||
if (options.onClose) {
|
||||
options.onClose();
|
||||
}
|
||||
|
||||
if (multiple && !isServer) {
|
||||
toast.$on('closed', () => {
|
||||
clearTimeout(toast.timer);
|
||||
queue = queue.filter((item) => item !== toast);
|
||||
|
||||
removeNode(toast.$el);
|
||||
toast.$destroy();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Object.assign(toast, transformOptions(options));
|
||||
clearTimeout(toast.timer);
|
||||
|
||||
if (options.duration > 0) {
|
||||
toast.timer = setTimeout(() => {
|
||||
toast.clear();
|
||||
}, options.duration);
|
||||
}
|
||||
nextTick(() => {
|
||||
toast.toggle(true, options.duration);
|
||||
});
|
||||
|
||||
return toast;
|
||||
}
|
||||
@ -165,10 +181,9 @@ Toast.allowMultiple = (value = true) => {
|
||||
multiple = value;
|
||||
};
|
||||
|
||||
Toast.install = () => {
|
||||
Vue.use(VueToast);
|
||||
Toast.install = (app) => {
|
||||
app.use(VanToast);
|
||||
app.config.globalProperties.$toast = Toast;
|
||||
};
|
||||
|
||||
Vue.prototype.$toast = Toast;
|
||||
|
||||
export default Toast;
|
||||
|
@ -1,9 +1,6 @@
|
||||
@import '../style/var';
|
||||
|
||||
.van-toast {
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
@ -25,7 +22,6 @@
|
||||
word-wrap: break-word;
|
||||
background-color: @toast-background-color;
|
||||
border-radius: @toast-border-radius;
|
||||
transform: translate3d(-50%, -50%, 0);
|
||||
|
||||
&--unclickable {
|
||||
// lock scroll
|
||||
|
@ -106,10 +106,10 @@ module.exports = {
|
||||
path: 'style',
|
||||
title: 'Style 内置样式',
|
||||
},
|
||||
// {
|
||||
// path: 'toast',
|
||||
// title: 'Toast 轻提示',
|
||||
// },
|
||||
{
|
||||
path: 'toast',
|
||||
title: 'Toast 轻提示',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
@ -440,10 +440,10 @@ module.exports = {
|
||||
path: 'style',
|
||||
title: 'Built-in style',
|
||||
},
|
||||
// {
|
||||
// path: 'toast',
|
||||
// title: 'Toast',
|
||||
// },
|
||||
{
|
||||
path: 'toast',
|
||||
title: 'Toast',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user