From 5d2cd516ed931284c38c9396c9d921e2c9d04af2 Mon Sep 17 00:00:00 2001 From: chenjiahan Date: Fri, 7 Aug 2020 07:16:33 +0800 Subject: [PATCH] feat: migrate Toast component --- components.js | 1 + src/toast/Toast.js | 43 ++++++++-------- src/toast/index.js | 119 ++++++++++++++++++++++++------------------- src/toast/index.less | 4 -- vant.config.js | 16 +++--- 5 files changed, 96 insertions(+), 87 deletions(-) diff --git a/components.js b/components.js index caa3f4ba0..e0ee8e4be 100644 --- a/components.js +++ b/components.js @@ -45,4 +45,5 @@ module.exports = [ 'sticky', 'picker', 'dialog', + 'toast', ]; diff --git a/src/toast/Toast.js b/src/toast/Toast.js index 8ab8ceb23..f0955ec68 100644 --- a/src/toast/Toast.js +++ b/src/toast/Toast.js @@ -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 ( - -
- {this.genIcon()} - {this.genMessage()} -
-
+ {this.genIcon()} + {this.genMessage()} + ); }, }); diff --git a/src/toast/index.js b/src/toast/index.js index c3ec0ec12..cc9c0b49a 100644 --- a/src/toast/index.js +++ b/src/toast/index.js @@ -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 ( + + ); + }, }); - 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; diff --git a/src/toast/index.less b/src/toast/index.less index 0f55e7ef3..2664c8364 100644 --- a/src/toast/index.less +++ b/src/toast/index.less @@ -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 diff --git a/vant.config.js b/vant.config.js index 56b13d3e8..337bc7f36 100644 --- a/vant.config.js +++ b/vant.config.js @@ -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', + }, ], }, {