思路: 实现一个toast类,可采用链式方式进行调用
实现效果如下:
实例化一个toast对象,可实现链式调用,如: 实现一个toast对象, 先执行showloading方法打印出加载中,然后三秒后执行打印‘加载成功’文案
toast.showloading('加载中').delay(3000).msgsucc('加载成功');
一般的函数调用和链式调用的区别:链式调用完方法后,return this返回当前调用方法的对象。
class Toast {
constructor() {
this.queue = Promise.resolve();
}
delay(time) {
this.queue = this.queue.then(() => {
return new Promise(resolve => {
setTimeout(() => {
resolve();
}, time)
})
}).catch(err => {
console.log('出错');
})
return this;
}
showloading(msg) {
this.queue = this.queue.then(() => {
console.log(msg);
})
return this;
}
msgsucc(msg) {
this.queue = this.queue.then(() => {
console.log(msg);
})
return this;
}
msgerror(msg) {
this.queue = this.queue.then(() => {
console.log(msg);
})
}
}
var toast = new Toast();
toast.showloading('加载中').delay(3000).msgsucc('加载成功');
这就是实例化一个对象,并能实现链式调用,下面利用这种方式实现一个简易版的loading消息控件
// 创建dom元素
function creatElement(tagName, options) {
var elem = document.createElement(tagName);
if (options.parent) {
options.parent.appendChild(elem);
}
if (options.attrs) {
for (var name in options.attrs) {
elem.setAttribute(name, options.attrs[name]);
}
}
if (options.classes) {
var clazz = options.classes.replace('/^\\s+$/g', ' ').split(' ');
for (var i = 0; i < clazz.length; i++) {
if (clazz[i]) {
elem.classList.add(clazz[i]);
}
}
}
if (options.styles) {
for (var key in options.styles) {
elem.style[key] = options.styles[key];
}
}
if (options.innerText) {
elem.innerText = options.innerText;
}
if (options.children) {
options.children.forEach(item => {
elem.appendChild(item);
});
}
return elem;
}
function removeElement(elem) {
if (elem && elem.parentNode) {
elem.parentNode.removeChild(elem);
}
}
// 居中
function fnCenterView(view) {
var objh = view.offsetHeight / 2;
var objw = view.offsetWidth / 2;
view.style.top = "-webkit-calc(45% - " + objh + "px)";
view.style.top = "-webkit-calc(50% - " + objw + "px)";
view.style.top = "calc(45% - " + objh + "px)";
view.style.left = "calc(50% - " + objw + "px)";
}
class ToastView {
constructor() {
var body = document.body;
this.view = creatElement('div', {
parent: body,
classes: 'ciel_msgview info'
});
this.loading = null;
this.succ = null;
this.message = null;
}
showloading(msg) {
this.loading = creatElement('div', {
parent: this.view,
classes: 'ciel_msgview_loading'
});
// 实现加载动画效果
for (let i = 0; i < 13; i++) {
let loadingChild = creatElement('div', {
parent: this.loading,
styles: {
'-webkit-transform': 'rotate(' + i * 30 + 'deg) translate(0, -142% )',
'-webkit-animation-delay': -1 + 0.0833 * i + 's'
}
});
}
this.message = creatElement('div', {
parent: this.view,
innerText: msg || '加载中',
classes: 'ciel_msgview_msg'
});
fnCenterView(this.view);
return this;
}
hide(delay = 100, callback) {
setTimeout(() => {
removeElement(this.view);
callback ? callback() : '';
}, delay);
}
msgsucc(msg) {
removeElement(this.loading);
removeElement(this.loading);
var succ = this.succ = creatElement('div', {
parent: this.view,
classes: 'ciel_msgview_succss'
});
let loadingChild = creatElement('div', {
parent: succ
});
if(this.message) {
this.message.innerText = msg || '成功';
}
return this;
}
}
var toast = new ToastView();
let msgview = toast.showloading('正在加载...');
setTimeout(() => {
msgview.msgsucc('加载完成').hide(500);
},2000)
样式实现
.ciel_msgview {
background-color: black;
position: fixed;
top: 50%;
left: 0%;
border-radius: 3px;
background-color: rgba(0, 0, 0, 0.7);
max-width: 80%;
z-index: 99999;
opacity: 0;
transition: transform 0.2s, opacity 0.2s;
word-break: break-all;
transform: scale(0.8, 0.8);
}
.ciel_msgview {
opacity: 1;
transform: scale(1, 1);
}
.ciel_msgview_loading,.ciel_msgview_succss{
width: 100px;
height: 100px;
}
.ciel_msgview_loading div {
width: 3px;
height: 9px;
background-color: white;
position: absolute;
left: 48%;
top: 35px;
opacity: 0;
border-radius: 3px;
animation: loading_fade 1s linear infinite;
}
@keyframes loading_fade {
from {
opacity: 1;
}
to {
opacity: 0.25;
}
}
@keyframes loading_fade {
from {
opacity: 1;
}
to {
opacity: 0.25;
}
}
.ciel_msgview_msg {
width: 100%;
color: white;
position: absolute;
bottom: 10px;
font-size: 14px;
text-align: center;
left: 0;
}
.ciel_msgview_succss div {
width: 48px;
height: auto;
line-height: 26px;
position: relative;
cursor: pointer;
}
.ciel_msgview_succss div::before {
position: absolute;
content: " ";
width: 27px;
height: 45px;
transform: rotate(45deg);
border-right: 5px solid #fff;
border-bottom: 5px solid #fff;
top: 3%;
left: 73%;
}