最近在使用Vue+TypeScript鼓捣本身的组件库,期间参考很多(抄😂)element,iview的源码。发现了一些经常使用的功能的背后,每每是复杂的实现。因而准备写一系列文章,介绍这些组件背后的原理。今天是第一篇,手把手带你实现Notice组件。css
一般咱们在使用iview或者element的Notice组件的时候,都是经过调用挂载到Vue原型链上的方法的形式。以下图所示。react
咱们的组件的调用方式,也参考相似的设计, 不一样的是咱们新添加了一个APIsetLen。代码以下git
这是由于楼主曾经接过一个需求,在作公司一款toC的时候,产品不但愿屏幕上出现太多的通知框,而是但愿一次最多只出现3个。全部楼主在设计组件的时候,将这个定制化的需求也添加了上去。github
由于咱们须要实现,屏幕上只显示指定数量的Notice通知框,因此咱们使用两个数组,保存Notice的实例。queue队列用来存储所有的Notice实例,showQueue用来屏幕上显示的Notice实例。数组
$Notice,方法用来想queue添加了一个Notice的实例; processQueue方法则用来处理queue队列; remove方法删除特定的Notice; clear方法则用来清除所有的Notice。setLen用来设定同屏显示Notice的数量。len属性则是同屏的最大数量。app
模版设计没啥好说的,常规布局。其中Icon组件,是我以前写的图标组件。showClose,控制是否显示Icon图标。visible控制Notice的显隐。iview
使用Vue.extend方法构建NoticeConstructor,NoticeConstructor是Vue的子类。NoticeConstructor的实例,能够使用mount的参数,将DOM渲染到页面之中。函数
在Notice方法的内部,使用uuid, 生成一个惟一id,这个惟一的标记,将会帮助咱们查找队列中指定的notice对象。紧接着咱们会对onClose方法进行一层包装。onClose将会在每次关闭notice的时候调用,onClose在内部调用Notice.remove方法会将指定的id所对应的notice对象移除出队列。布局
接着咱们将建立notice的实例,并将其push到queue队列中,接着调用$Notice.processQueue方法处理queue队列。学习
关于uuid这个方法,uuid这个方法生成的并非真的惟一id,而是一个重复几率很低的id。重复几率大概是1ms内,1亿多分之1吧。这个是我在stackoverflow上找的方法,代码以下。
在processQueue方法中,咱们首先判断showQueue队列是否是满的。若是不是,咱们将会从queue队列的头部截取一个notice对象。使用$mount方法,生成DOM并append到body中。
由于notice在页面上的样式,是自上而下的,因此咱们将会计算notice的相对顶部的偏移量,每个notice对象的自身高度和15px的间距。
同时,咱们会将notice的visible属性设置为true,这会触发咱们的transition动画,并将这个notice对象push到showQueue队列中。
接着咱们将目光转移到Notice组件内部,咱们将notice,append到DOM中后。咱们会在mounted函数中起一个定时器,定时器将会等待指定的duration毫秒,duration是咱们指定notice存在的时间,若是duration为0,notice将会永远存在。
duration毫秒以后,将会执行notice组件内部的close方法。
在close方法中,咱们会为当前组件添加transitionend,事件。这个事件将会在css动画(离场动画)结束后触发。咱们将visible设置为false这会触发,组件的离场动画。接着咱们调用onClose方法,这会处理咱们的队列。
以前咱们对onClose进行了一层包装,调用onClose方法,会调用咱们的$Notice.remove方法。
在$Notice.remove方法中,咱们将会经过id找到须要移除的notice对象,将其移除出showQueue队列。
接着循环剩下的showQueue队列,将它们style.top向上移动。最后咱们继续调用$Notice.processQueue方法,从queue队列中,拉取新的notice对象,push到showQueue队列中。
当离场动画执行完毕后,transitionend回调会调用destroy方法。
destroy将会主动卸载咱们的组件,并从DOM中移除咱们的元素。notice对象的生命周期至此结束。
clear和setLen相对而言比较简单,这里就再也不赘述了。
本系列的文章,尽可能作到短小精悍。Select,Table,DatePicker组件将会难点。
明天可能会更新一篇React Hook的学习文章。由于报名了周末晚上的公开课介绍Hook的原理。下周想从新阅读下preact的源码,学习学习preact中hook的实现原理。