从零开始实现Vue简单的Toast插件

概述:

在前端项目中,有时会须要通知、提示一些信息给用户,尤为是在后台系统中,操做的正确与否,都须要给与用户一些信息。

1. 实例

在Vue组件的methods内,调用以下代码
`this``.$toast({`=
`content:` `"可自动关闭"``,`
`autoClose:` `true`
`})`

在页面的右侧会出现一个Toast弹框,屡次点击时,会依照顺序进行显示,而且Toast可自动关闭,具体效果如图。前端

代码地址:Github UI-Librarygit

2. 原理

代码结构github

将Toast插件分为两个部分:
  • Toast组件自己,包含自己的dom结构以及data,并在其生命周期完成在页面中的挂载与销毁;
  • 在组件外构建一层代理并提供相关方法用于调用、并控制多个Toast在页面中显示的顺序。

Toast方法app

为了可以经过 this.$toast({...})调用Toast组件,须在Vue的prototype上添加一个方法,以下
`let instances = []`
`let initIndex = 0`
`Vue.prototype.$toast = (options = {}) => {`
`/* 建立一个Toast组件的实例 */`
`let instance = generateInstance(options)`
`/* 将单个toast存入队列中 */`
`instances.push(instance)`
`}`
当调用该方法时,经过generateInstance建立一个Toast组件的实例,并将其放入instances,统一管理。
`/* 构造单个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组件的通用解决方案dom

`/* 初始化每一个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`
`instances.find((elem, i) => {`
`if` `(elem.id === removeInstance.id) index = i`
`})`
`// 删除关闭的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);`
`}`

3. 使用

进一步将其封装成Vue的插件
`export` `default` `{`
`install (Vue) {`
`Vue.prototype.$toast = (options = {}) => {...}`
`}`
`}`
而且对所须要传入的必需属性,作处理异常处理
`export` `default` `{`
`install (Vue) {`
`Vue.prototype.$toast = (options = {}) => {...}`
`}`
`}`

总结
经过封装一个Toast插件,提取不一样业务之间公共的部分,减小业务的工做量。
好了,以上就是这篇文章的所有内容了,但愿本文的内容对你们的学习或者工做具备必定的参考学习价值学习

相关文章
相关标签/搜索