mirror of
https://github.com/youzan/vant.git
synced 2026-05-02 01:01:43 +08:00
Toast: use flex layout, support loading with text, improve performance
This commit is contained in:
+37
-61
@@ -1,81 +1,57 @@
|
||||
import Vue from 'vue';
|
||||
import ToastComponent from './toast';
|
||||
import VueToast from './toast';
|
||||
|
||||
const ToastConstructor = Vue.extend(ToastComponent);
|
||||
let instance;
|
||||
|
||||
const getInstance = () => {
|
||||
if (instance) instance.clear();
|
||||
|
||||
instance = new ToastConstructor({
|
||||
el: document.createElement('div')
|
||||
});
|
||||
return instance;
|
||||
};
|
||||
|
||||
const removeDom = event => {
|
||||
/* istanbul ignore else */
|
||||
if (event.target.parentNode) {
|
||||
event.target.parentNode.removeChild(event.target);
|
||||
const defaultOptions = {
|
||||
visible: true,
|
||||
type: 'text',
|
||||
duration: 3000,
|
||||
forbidClick: false,
|
||||
clear: () => {
|
||||
instance.visible = false;
|
||||
}
|
||||
};
|
||||
|
||||
var Toast = (options = {}) => {
|
||||
const duration = options.duration || 3000;
|
||||
const createInstance = () => {
|
||||
if (!instance) {
|
||||
const ToastConstructor = Vue.extend(VueToast);
|
||||
instance = new ToastConstructor({
|
||||
el: document.createElement('div')
|
||||
});
|
||||
document.body.appendChild(instance.$el);
|
||||
}
|
||||
};
|
||||
|
||||
const instance = getInstance();
|
||||
const Toast = (options = {}) => {
|
||||
createInstance();
|
||||
|
||||
options = typeof options === 'string' ? { message: options } : options;
|
||||
options = { ...defaultOptions, ...options };
|
||||
Object.assign(instance, options);
|
||||
|
||||
instance.closed = false;
|
||||
clearTimeout(instance.timer);
|
||||
instance.type = options.type ? options.type : 'text';
|
||||
instance.message = typeof options === 'string' ? options : options.message;
|
||||
instance.forbidClick = options.forbidClick ? options.forbidClick : false;
|
||||
instance.clear = () => {
|
||||
if (instance.closed) return;
|
||||
instance.visible = false;
|
||||
instance.$el.addEventListener('transitionend', removeDom);
|
||||
instance.closed = true;
|
||||
};
|
||||
|
||||
document.body.appendChild(instance.$el);
|
||||
Vue.nextTick(function() {
|
||||
instance.visible = true;
|
||||
instance.$el.removeEventListener('transitionend', removeDom);
|
||||
instance.timer = setTimeout(function() {
|
||||
if (options.duration !== 0) {
|
||||
instance.timer = setTimeout(() => {
|
||||
instance.clear();
|
||||
}, duration);
|
||||
});
|
||||
}, options.duration);
|
||||
}
|
||||
|
||||
return instance;
|
||||
};
|
||||
|
||||
Toast.loading = (options) => {
|
||||
return new Toast({
|
||||
type: 'loading',
|
||||
...options
|
||||
});
|
||||
};
|
||||
|
||||
Toast.success = (options) => {
|
||||
const message = typeof options === 'string' ? options : options.message;
|
||||
return new Toast({
|
||||
type: 'success',
|
||||
message: message,
|
||||
...options
|
||||
});
|
||||
};
|
||||
|
||||
Toast.fail = (options) => {
|
||||
const message = typeof options === 'string' ? options : options.message;
|
||||
return new Toast({
|
||||
type: 'fail',
|
||||
message: message,
|
||||
...options
|
||||
});
|
||||
};
|
||||
const createMethod = type => (options = {}) => Toast({
|
||||
type,
|
||||
message: typeof options === 'string' ? options : options.message,
|
||||
...options
|
||||
});
|
||||
|
||||
Toast.loading = createMethod('loading');
|
||||
Toast.success = createMethod('success');
|
||||
Toast.fail = createMethod('fail');
|
||||
Toast.clear = () => {
|
||||
/* istanbul ignore else */
|
||||
if (instance) instance.clear();
|
||||
instance && instance.clear();
|
||||
};
|
||||
|
||||
export default Toast;
|
||||
|
||||
+15
-22
@@ -2,19 +2,18 @@
|
||||
<transition name="van-toast-fade">
|
||||
<div class="van-toast-wrapper" v-show="visible">
|
||||
<div :class="['van-toast', 'van-toast--' + displayStyle]">
|
||||
<!-- 只显示文字 -->
|
||||
<!-- text only -->
|
||||
<div v-if="displayStyle === 'text'" class="van-toast__text">{{ message }}</div>
|
||||
<!-- 加载中 -->
|
||||
<van-loading v-if="displayStyle === 'loading' && type === 'loading'" type="gradient-circle" color="white"></van-loading>
|
||||
<!-- 图案加文字 -->
|
||||
<div v-if="displayStyle === 'html'" class="van-toast__text" v-html="message" />
|
||||
|
||||
<!-- with icon -->
|
||||
<template v-if="displayStyle === 'default'">
|
||||
<van-icon class="van-toast__icon" :name="type"></van-icon>
|
||||
<div class="van-toast__text">{{ message }}</div>
|
||||
<van-loading v-if="type === 'loading'" color="white" />
|
||||
<van-icon v-else class="van-toast__icon" :name="type" />
|
||||
<div v-if="message" class="van-toast__text">{{ message }}</div>
|
||||
</template>
|
||||
<!-- 传入html -->
|
||||
<div v-if="displayStyle === 'html'" class="van-toast__text" v-html="message"></div>
|
||||
</div>
|
||||
<div class="van-toast__overlay" v-if="forbidClick"></div>
|
||||
<div class="van-toast__overlay" v-if="forbidClick" />
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
@@ -24,15 +23,8 @@ import Icon from '../icon';
|
||||
import Loading from '../loading';
|
||||
|
||||
const TOAST_TYPES = ['text', 'html', 'loading', 'success', 'fail'];
|
||||
const DEFAULT_STYLE_LIST = ['success', 'fail'];
|
||||
/**
|
||||
* van-toast
|
||||
* @module components/toast
|
||||
* @desc toast
|
||||
* @param {string} [type=false] - 类型
|
||||
* @param {string} [message] - 信息
|
||||
*
|
||||
*/
|
||||
const DEFAULT_STYLE_LIST = ['success', 'fail', 'loading'];
|
||||
|
||||
export default {
|
||||
name: 'van-toast',
|
||||
|
||||
@@ -40,13 +32,12 @@ export default {
|
||||
[Icon.name]: Icon,
|
||||
[Loading.name]: Loading
|
||||
},
|
||||
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
default: 'text',
|
||||
validator(value) {
|
||||
return TOAST_TYPES.indexOf(value) > -1;
|
||||
}
|
||||
validator: value => TOAST_TYPES.indexOf(value) > -1
|
||||
},
|
||||
message: {
|
||||
type: String,
|
||||
@@ -57,14 +48,16 @@ export default {
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
visible: false
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
displayStyle() {
|
||||
return DEFAULT_STYLE_LIST.indexOf(this.type) > -1 ? 'default' : this.type;
|
||||
return DEFAULT_STYLE_LIST.indexOf(this.type) !== -1 ? 'default' : this.type;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2,16 +2,19 @@
|
||||
|
||||
.van-toast {
|
||||
position: fixed;
|
||||
z-index: 3001;
|
||||
border-radius: 5px;
|
||||
background-color: rgb(39, 39, 39, .7);
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate3d(-50%, -50%, 0);
|
||||
font-size: 12px;
|
||||
display: flex;
|
||||
color: $white;
|
||||
text-align: center;
|
||||
line-height: 12px;
|
||||
z-index: 3001;
|
||||
font-size: 12px;
|
||||
line-height: 1.2;
|
||||
border-radius: 5px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
transform: translate3d(-50%, -50%, 0);
|
||||
background-color: rgb(39, 39, 39, .7);
|
||||
|
||||
&-wrapper {
|
||||
transition: opacity .2s;
|
||||
@@ -19,16 +22,12 @@
|
||||
|
||||
&__overlay {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
background: transparent;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 3000;
|
||||
}
|
||||
|
||||
&--loading {
|
||||
padding: 45px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
&--text {
|
||||
@@ -37,18 +36,21 @@
|
||||
}
|
||||
|
||||
&--default {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
width: 90px;
|
||||
min-height: 90px;
|
||||
padding: 15px;
|
||||
|
||||
.van-toast__icon {
|
||||
padding-top: 20px;
|
||||
font-size: 50px;
|
||||
}
|
||||
|
||||
.van-loading {
|
||||
margin: 10px 0 5px;
|
||||
}
|
||||
|
||||
.van-toast__text {
|
||||
padding: 15px 0 20px;
|
||||
font-size: 14px;
|
||||
line-height: 1.2;
|
||||
padding-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user