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

  在前端项目中,有时会需要通知、提示一些信息给用户,尤其是在后台系统中,操作的正确与否,都需要给与用户一些信息。
  
  1. 实例
  
  在Vue组件的methods内,调用如下代码
  
  `this``.$toast({`=
  
  `content:` `"可自动关闭"``,`
  
  `autoClose:` `true`
  
  `})`
  
  在页面的右侧会出现一个Toast弹框,多次点击时,会依照顺序进行显示,并且Toast可自动关闭,具体效果如图。
  
  代码地址:Github UI-Library
  
  2. 原理
  
  代码结构
  
  将Toast插件分为两个部分:
  
  Toast组件本身,包含本身的dom结构以及data,并在其生命周期完成在页面中的挂载与销毁;
  
  在组件外构建一层代理并提供相关方法用于调用、并控制多个Toast在页面中显示的顺序。
  
  Toast方法
  
  为了能够通过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组件的通用解决方案。
  
  `/* 初始化每个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(www.wanmeiyuele.cn``this``.$el);`
  
  `// 需要自动关闭时,调用startTimer`
  
  `if` `(``this``.autoClose)` `this``.startTimer();`
  
  `},`
  
  `beforeDestroy() {`
  
  `this``.stopTimer(www.michenggw.com);`
  
  `this``.$el.removeEventListener(``"transitionend"``,` `this``.destroyElement);`
  
  `},`
  
  `destroyed() {`
  
  `// 注销`
  
  `this``.$el.parentNode.removeChild(``this``.$el);`
  
  `}`
  
  自动关闭
  
  需要自动时,就要在利用setTimeout完成该功能,并在注销时clearTimeout掉,防止泄露。
  
  `startTimer() {`
  
  `if` `(`yongshiyule178.com/ `this``.duration > 0) {`
  
  `this``.timer = setTimeout(() => {`
  
  `if` `(!``this`www.mcyllpt.com/ `.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插件,提取不同业务之间公共的部分,减少业务的工作量。
  
  好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值
  
  本次给大家推荐一个交流圈,里面概括移动应用网站开发,css,html,webpack,vue node angular以及面试资源等。
  
  对web开发技术感兴趣的同学,欢迎加入:582735936,不管你是小白还是大牛我都欢迎,还有大牛整理的一套高效率学习路线和教程与您免费分享,同时每天更新视频资料。
  
  最后,祝大家早日学有所成,拿到满意offer,快速升职加薪,走上人生巅峰。

原文地址:https://www.cnblogs.com/qwangxiao/p/10134369.html

时间: 2024-11-13 03:46:47

从零开始实现Vue简单的Toast插件的相关文章

Vue中的better-scroll插件

Vue中的better-scroll插件 在需要的文件中添加 import BScorll from 'better-scroll'; 引用的示例代码: let scroll = new BScroll(Dom对象, {//options startX: 0, startY: 0 }) Vue获得Dom对象方法, <div v-el:food-wrapper></div>//定义对象 this.$els.foodWrapper//获取对象 (Vue 更新数据时是异步的,所以在数据未

Vue简单知识点

vue生命周期的理解 什么是vue生命周期? Vue 实例从创建到销毁的过程,就是生命周期.从开始创建.初始化数据.编译模板.挂载Dom→渲染.更新→渲染.销毁等一系列过程,称之为 Vue 的生命周期. vue生命周期总共有几个阶段? 总共分为8个阶段创建前/后,载入前/后,更新前/后,销毁前/后 beforeCreate(创建前) : Vue 实例的挂载元素 $el 和 数据对象data都为undefined,还未初始化. created(创建后) :完成数据观测,属性和方法的运算,初始化事件

[前端] VUE基础 (6) (v-router插件)

一.v-router插件 1.v-router插件介绍 v-router是vue的一个核心插件,vue+vue-router主要用来做SPA(单页面应用)的. 什么是SPA:就是在一个页面中,有多个页签,我们选择页签显示不同的内容,但页面不跳转. 例如: 在网易云音乐的主页中,发现音乐.我的音乐.朋友这三个页签就是单页面应用.当我们切换他们时,可以观察到url的变化: 这里看到的url改变(路由改变)的路由是vue-router提供的,而不是对应django的路由系统(前后端分离的项目,djan

图片延迟加载并等比缩放,一个简单的JQuery插件

使用方法: $(".viewArea img").zoom({height:74,width:103}); (function($){    $.fn.zoom = function(settings){                //一些默认配置:                settings = $.extend({                    height:0,                    width:0,                    load

【UI插件】简单的日历插件(下)—— 学习MVC思想

前言 我们上次写了一个简单的日历插件,但是只是一个半成品,而且做完后发现一些问题,于是我们今天尝试来解决这些问题 PS:距离上次貌似很久了 上次,我们大概遇到哪些问题呢: ① 既然想做一套UI库,那么就应该考虑其它UI库的接入问题 这个意思就是,我们的系统中所有UI插件应该有一些统一行为,我们如果希望统一为所有的插件加一点什么东西,需要有位置可加 这个意味着,可能我们所有的插件需要继承至一个抽象的UI类,并且该类提供了通用的几个事件点 ② 上次做的日历插件虽然说是简单,其耦合还是比较严重的(其实

Sublime插件开发——简单的代码模板插件

最近一段一直使用sublime进行golang开发,整体感觉很不错,虽然比不上eclipse之类IDE强大,但是用起来很轻巧便捷,开发golang完全做够了.由于有一部分代码复用率很高,经常要用到,而自己记性特别差也懒得每次自己敲,就希望能够像其他IDE的插件那样能直接插入代码模板,于是就研究了下sublime的插件开发(网上有很多人推荐Gist,但是发现由于网络原因适用Gist插件很慢,每次都要等很长时间). 装过插件的都知道sublime的插件采用python开发的,所以如果想要开发需要对p

编写一个简单的Jquery插件

1.实现内容 定义一个简单的jquery插件,alert传递进来的参数 2.插件js文件(jquery.showplugin.js) (function ($) { //定义插件中的方法 var methods = { //Object showName: function (name) { alert('Name:' + name); }, showAge: function (age) { alert('Age' + age); } }; //method方法名 $.fn.showplugi

Awesomplete - 零依赖的简单自动完成插件

Awesomplete 是一款超轻量级的,可定制的,简单的自动完成插件,零依赖,使用现代化标准构建.你可以简单地添加 awesomplete 样式,让它自动处理(你仍然可以通过指定 HTML 属性配置更多选项),您可以用几行 JS 代码,提供更多的自定义. 在线演示      源码下载 您可能感兴趣的相关文章 网站开发中很有用的 jQuery 效果[附源码] 分享35个让人惊讶的 CSS3 动画效果演示 十分惊艳的8个 HTML5 & JavaScript 特效 Web 开发中很实用的10个效果

一个简单的jQuery插件ajaxfileupload实现ajax上传文件例子

页面代码:   <html>     <!-- 引入相关的js文件,相对路径  -->     <script type="text/javascript" src="js/jquery.js"></script>       <script type="text/javascript" src="js/ajaxfileupload.js"></script&g