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