实现一个简单的Toast插件,方便迁移到不一样的项目中,用来全局提示、警告一些信息。前端
概述: 在前端项目中,有时会须要通知、提示一些信息给用户,尤为是在后台系统中,操做的正确与否,都须要给与用户一些信息。git
在Vue组件的methods
内,调用以下代码github
this.$toast({
content: "可自动关闭",
autoClose: true
})
复制代码
在页面的右侧会出现一个Toast弹框,屡次点击时,会依照顺序进行显示,而且Toast可自动关闭,具体效果如图。 app
代码地址:Github UI-Librarydom
代码结构ide
将Toast插件分为两个部分:函数
data
,并在其生命周期完成在页面中的挂载与销毁;Toast方法工具
为了可以经过this.$toast({...})
调用Toast组件,须在Vue的prototype
上添加一个方法,以下post
let instances = []
let initIndex = 0
Vue.prototype.$toast = (options = {}) => {
/* 建立一个Toast组件的实例 */
let instance = generateInstance(options)
/* 将单个toast存入队列中 */
instances.push(instance)
}
复制代码
当调用该方法时,经过generateInstance
建立一个Toast组件的实例,并将其放入instances
,统一管理。ui
/* 构造单个toast */
const ToastConstructor = Vue.extend(Toast)
const verticalOffset = 16
function generateInstance(options) {
// 利用ToastConstructor建立一个Toast的实例
let instance = new ToastConstructor({
propsData: options
}).$mount(document.createElement('div'))
if (typeof options.onClose === 'function') instance.onClose = options.onClose
//计算instance verticalOffset
let id = 'toast_' + initIndex++
instance.id = id
// 初始化Toast在空间中的垂直偏移量
instance.verticalOffset = initVerticalOffset(instance.position)
//监听组件close
instance.$once('toastClose', function () {
const curInstance = this
// 当Toast组件关闭时,从新计算垂直方向的偏移量
updateVerticalOffset(curInstance)
typeof curInstance.onClose === 'function' && curInstance.onClose()
})
return instance;
}
复制代码
generateInstance
函数中,首先利用ToastConstructor
构造函数建立一个Toast组件的实例,并经过propsData
传入属性值,同时经过$mount(document.createElement('div'))
渲染该组件。
ToastConstructor
是经过Vue.extend
创造Toast组件的构造函数,关于这部分的具体原理,能够参考 基于Vue构造器建立Form组件的通用解决方案。
initVerticalOffset
函数计算Toast组件的初始偏移量
/* 初始化每一个toast对象在页面中的垂直属性 */
function initVerticalOffset(position) {
// 筛选同一方向的Toast组件
let typeInstances = instances.filter(item => item.position === position)
// 计算偏移量
return typeInstances.reduce((sum, elem) =>
(elem.$el.offsetHeight + sum + verticalOffset),
verticalOffset)
}
复制代码
以后当某个Toast关闭时,须要更新全部Toast实例在页面中偏移量
/* 更新每一个toast对象在页面中的垂直属性 */
function updateVerticalOffset(removeInstance) {
let index = 0
let removeHeight = removeInstance.verticalOffset
// 兼容ie 去掉find method
for (; index < instances.length; index++) {
if (instances[index].id === removeInstance.id) break;
}
instances.splice(index, 1);
// 删除关闭的Toast组件
instances.splice(index, 1)
// 更新在删除位置以后的组件的位置
for (; index < instances.length; ++index) {
if (instances[index].position === removeInstance.position) {
[instances[index].verticalOffset, removeHeight] =
[removeHeight, instances[index].verticalOffset]
}
}
}
复制代码
以上完成了Toast组件的建立、如何在页面中初始化、更新的位置。
Toast组件
组件的功能比较简单,只须要展现信息,以及具有自动关闭、手动关闭两个功能,属性也要包括Toast的类型、位置、内容等。
let instance = new ToastConstructor({
propsData: options
}).$mount(document.createElement('div'))
复制代码
当Toast组件$mount
调用时,会触发mounted
的生命周期
mounted() {
// 挂载Toast在页面中
document.body.appendChild(this.$el);
// 须要自动关闭时,调用startTimer
if (this.autoClose) this.startTimer();
},
beforeDestroy() {
this.stopTimer();
this.$el.removeEventListener("transitionend", this.destroyElement);
},
destroyed() {
// 注销
this.$el.parentNode.removeChild(this.$el);
}
复制代码
setTimeout
完成该功能,并在注销时clearTimeout
掉,防止泄露。startTimer() {
if (this.duration > 0) {
this.timer = setTimeout(() => {
if (!this.closed) {
this.close();
}
}, this.duration);
}
},
stopTimer() {
if (this.timer) clearTimeout(this.timer);
}
复制代码
进一步将其封装成Vue的插件
export default {
install (Vue) {
Vue.prototype.$toast = (options = {}) => {...}
}
}
复制代码
而且对所须要传入的必需属性,作处理异常处理
let requireProps = Object.keys(Toast.props)
.filter((elem) => (Toast.props[elem].required))
requireProps.forEach((elem) => {
if (!options[elem]) throw `err: options lack ${elem} prop`
})
if ( options.type && !types.some(elem => elem === options.type) )
throw `err: toast not exist ${options.type} type`
复制代码
经过封装一个Toast插件,提取不一样业务之间公共的部分,减小业务的工做量。
往期文章:
原创声明: 该文章为原创文章,转载请注明出处。