效果如下:

关闭message后前后message的衔接非常丝滑,这部分是我比较感兴趣的。带着这个问题先了解下DOM结构,顺便整理下作者的思路。

从DOM里我们可以看到所有的message都在一个容器里,而这个容器做了绝对定位实现了可视窗口的水平居中,新增的message只要在容器里append对应的元素就会在页面上显示出来。

接下来我们看下每个message元素的秘密~

我们可以看到这里设置了height和padding属性的动画,那上文中的动画大概率是在关闭时设置height和padding为0,因为bfc的规则在动画期间前后的message也会挤占其空间,所以看起来比较丝滑。动画执行完成后再将元素remove掉。

这里注意到一个不太常用的css属性:will-change,援引MDN上的表述,这个属性会根据开发者指定的要改变的值提前做优化准备。will-change

其他内部的元素是常见的根据弹框类型和消息进行渲染,不再进行细究。接下来关注点放到js上。

引入方式很简单,只有一个js文件

代码示例如下:

 1 // 配置全局默认参数
2 cocoMessage.config({
3 duration: 10000,
4 });
5 // 普通消息,可传入自动关闭时间、提示信息、关闭回调
6 cocoMessage.info(3000, "请先登录!", function () {
7 console.log("close");
8 });
9 // 成功消息,可传入element元素
10 var div1 = document.createElement("div");
11 div1.innerText = "修改成功!";
12 cocoMessage.success(div1);
13 // 警告消息,时间设置0不会自动关闭
14 cocoMessage.warning("需要手动关闭", 0);
15 // 失败消息
16 cocoMessage.error("修改失败!", 3000);
17 // loading消息
18 var closeMsg = cocoMessage.loading(true);
19 setTimeout(function () {
20 closeMsg();
21 }, 4000);
22 // 关闭所有消息
23 cocoMessage.destroyAll();

这里我们可看到支持的类型有info、success、warning、error、loading五种,基本场景都覆盖到了。传参比较灵活,可以一个两个三个,而且类型也不固定。带着这些疑问开始了真正的代码走读,解开它神秘的面纱:

首先看下代码结构:

定义了一个兼容的_typeof方法(原谅我没看懂这个兼容逻辑,有明白的兄弟可以在评论区留言);然后是一个常见的立即执行函数,函数前的!和用括号包裹起来的效果一样,常见的还有+-。

传进去两个参数,第一个是void 0(也就是undefined,个人感觉用this也没问题,感兴趣的可以了解下),另一个参数是主体函数,后面会做详细介绍,我们先看下这个立即执行函数都做了什么:

先检查环境中是否有module.exports再检查define.amd,最后才用全局变量。显然这个是兼容CommonJs规范、AMD/CMD规范和直接引用的写法。其中用global = global || self 的写法而不是window因为可以兼容服务器端(global全局变量)和浏览器端(window全局变量)。这样会在浏览器window变量下暴露cocoMessage变量。另外提一下使用立即执行函数是可以避免污染全局变量的。在进入方法内部前,建议把这部分代码收藏一波

1 !function (global, factory) {
2 (typeof exports === "undefined" ? "undefined" : _typeof(exports)) === "object" && typeof module !== "undefined" ?
3 module.exports = factory() :
4 typeof define === "function" && define.amd ?
5 define(factory) :
6 (global = global || self, global.cocoMessage = factory());
7 }(void 0, function () {
8 // code here
9 });

刚进入方法会创建msgWrapper变量保存消息父元素,定义默认配置initArgs,暴露cocoMessage变量并在页面元素加载完毕后添加style标签。上图中白色备注是比较通用的方法,下文会将重点放在红色备注的方法上。

首先关注下创建msgWrapper元素的c方法

第一个参数传输对象,key可以是className来给元素添加class属性,另一种可以是以_开头可以给元素绑定相应的事件。

第二个参数可以传输文本、元素、包含多个元素的数组(或者伪数组)。

// 创建class为coco-msg-stage的div元素
var msgWrapper = c({
className: "coco-msg-stage"
}, "默认消息");
// 创建class为coco-msg-wait并在元素上绑定click事件
c({
className: "coco-msg-wait " ,
_click: function _click () {
if (closable) {
closeMsg(el, onClose);
}
}
}
// 多次调用创建复杂元素
c({
className: "coco-msg-stage"
}, c({
className: "coco-msg-loading",
_click: function(){
console.log("loading")
}
})
);
然后看下initArgs和cocoMessage这两个变量

共有info、success、warning、error、loading、destoryAll、config这七个方法,这也正是这个插件想要暴露给用户的。默认参数中消息是空字符串,关闭时间是2s,不会显示关闭按钮,当然这些都可以通过config方法修改全局的默认配置,从中也可以看到随时可以修改配置,即时生效。除去destoryAll方法我们先关注下消息的5中类型,创建方法大同小异:都是通过initConfig方法创建的。其中arguments是伪数组,也就是我们调用info等方法传递的所有参数,可以通过通数组一样角标方式取值。loading方法是特殊的,把initConfig方法的结果返回了,通过demo我们知道返回值是个方法,执行后会关闭loading,下文我们再关注下loading类型的消息有什么特殊处理,开始进入initConfig方法

这里仅是对参数进行统一,上文中有个疑问,为什么参数可以随便传,而且顺序不一致也不影响?答案就在这个方法里,之前传的参数有提示信息:字符串(string类型)或元素(Element或object类型)、延迟时间:数字(number类型)、关闭后的回调:方法(function类型)、是否显示关闭按钮(boolean类型)。到这里应该发现这里的玄机了,每个参数都有唯一的类型而且还不会冲突,这样就可以根据传参类型的不同识别传的值了。封装后的对象大致如下:

{
msg: "提示消息",
type: "info",
showClose: false,
duration: 2000,
onClose: function(){
console.log("closed")
}
}

虽然以上方法设计得很巧妙,但是健壮性要差一些,如果要扩展设置文字是否居中、自定义类名、自定义图标等功能时不免会要进行重构。所以调用方法改成这样会便于扩展:

cocoMessage.info({
msg: '请先登录',
duracion: '2000',
showClose: true,
onClose: function(){
console.log('closed')
}
});

到这一步需要的参数封装完成了,接下来会调用createMsgEl方法创建消息元素。

方法较长分为两个部分,完成了根据传入的参数创建元素并添加到body中显示出来,并绑定关闭按钮的点击事件和触发自动关闭的条件。图中画问好的正是上文中我们存疑的问题,正因为这里返回了关闭消息的方法就可以实现执行后关闭loading。

到这里还剩closeMsg方法destoryAll方法,我们先看closeMsg:

首先会设置padding和height为0,进而实现开头说的动画效果,然后执行自定义的关闭回调方法。最后再删除消息元素,如果没有消息也会把父元素一并删除。需要注意的是这里还会判断消息元素是否存在,这并不是冗余的代码,而是考虑到点击按钮关闭和执行全部关闭一起执行时后触发的会报错的问题,因为这里有300ms的延迟。

最后是destoryAll方法,关闭所有消息。

获取父元素所有的消息元素再循环调用closeMsg方法进行删除。

 到这里原生的消息提示插件已经解读完毕,这是款很轻量和优秀的插件。
 
总结:
首先通过立即执行函数避免全局变量污染,只对外暴露七个方法。通过变量检测实现对CommonJs规范、AMD/CMD规范和直接引用的兼容。通过巧妙的参数设计,实现了对参数先后顺序没有要求,通过设置padding和height值来实现动画效果。
亮点:
设置will-change的css属性提高性能和用户体验;
通过兼容监听元素animationEnd事件来执行回调,解决了setTimeout不准确和性能问题;
通过c方法可以很方便得创建元素,有点react的味道;
给svg内元素设置动画;
 
插件预览地址:https://www.jq22.com/jquery-info23645

【源码解读】js原生消息提示插件的更多相关文章

  1. fastclick.js源码解读分析

    阅读优秀的js插件和库源码,可以加深我们对web开发的理解和提高js能力,本人能力有限,只能粗略读懂一些小型插件,这里带来对fastclick源码的解读,望各位大神不吝指教~! fastclick诞生 ...

  2. 消息提示插件toastr.js与Messenger组件

    Toastr是一款基于jQuery的通知插件,可以灵活的自定义样式和拓展其功能! toastr是一个基于Jquery简单.漂亮的消息提示插件,使用简单.方便,可以根据设置的超时时间自动消失. cdn最 ...

  3. js便签笔记(10) - 分享:json2.js源码解读笔记

    1. 如何理解“json” 首先应该意识到,json是一种数据转换格式,既然是个“格式”,就是个抽象的东西.它不是js对象,也不是字符串,它只是一种格式,一种规定而已. 这个格式规定了如何将js对象转 ...

  4. js便签笔记(10) - 分享:json.js源码解读笔记

    1. 如何理解“json” 首先应该意识到,json是一种数据转换格式,既然是个“格式”,就是个抽象的东西.它不是js对象,也不是字符串,它只是一种格式,一种规定而已. 这个格式规定了如何将js对象转 ...

  5. Mybatis源码解读-插件

    插件允许对Mybatis的四大对象(Executor.ParameterHandler.ResultSetHandler.StatementHandler)进行拦截 问题 Mybatis插件的注册顺序 ...

  6. php-msf 源码解读【转】

    php-msf: https://github.com/pinguo/php-msf 百度脑图 - php-msf 源码解读: http://naotu.baidu.com/file/cc7b5a49 ...

  7. 从koa-session源码解读session本质

    前言 Session,又称为"会话控制",存储特定用户会话所需的属性及配置信息.存于服务器,在整个用户会话中一直存在. 然而: session 到底是什么? session 是存在 ...

  8. React16源码解读:开篇带你搞懂几个面试考点

    引言 如今,主流的前端框架React,Vue和Angular在前端领域已成三足鼎立之势,基于前端技术栈的发展现状,大大小小的公司或多或少也会使用其中某一项或者多项技术栈,那么掌握并熟练使用其中至少一种 ...

  9. Vue 源码解读(8)—— 编译器 之 解析(上)

    特殊说明 由于文章篇幅限制,所以将 Vue 源码解读(8)-- 编译器 之 解析 拆成了上下两篇,所以在阅读本篇文章时请同时打开 Vue 源码解读(8)-- 编译器 之 解析(下)一起阅读. 前言 V ...

随机推荐

  1. chrome 开发者工具使用一例

    今天搜到了一篇我想看的文章,某网站上又是弹出注册小窗遮挡,又是一堆漂浮广告,还把字体搞成灰色. 右键审查元素,找到几个div,删掉:原来那个字体的灰色,是个什么script做的遮罩,也删掉. 然后整个 ...

  2. redis 五种常见攻击方法

    如果需要大佬写好的脚本,可以直接去github上面搜 参考文章:https://www.cnblogs.com/wineme/articles/11731612.html    https://www ...

  3. C# 数组 ArrayList List<T>区别

    System.Collenctions和System.Collenctions.Generic 中提供了很多列表.集合和数组.例如:List<T>集合,数组Int[],String[] . ...

  4. EF生成模型时Disigner中无信息

    原博文 http://blog.sina.com.cn/s/blog_a1b63a730101ezs4.html 说明 DbContext是对ObjectContext的简化封装.原来的ObjectC ...

  5. 在飞儿云主机里使用酷Q时遇到相关问题的解决办法

    情况1:酷Q Air版本可以使用,而Pro版本无法运行 解决方法如下: p.p1 { margin: 0; font: 13px "Helvetica Neue"; color: ...

  6. H3C S5120V2-SI 交换机配置

    连接终端线 可以看到开机信息 ......................................................................Done. System is ...

  7. MPEG2TS文件格式概述

    总结TS文件格式,早在几个月前就有了这个想法,但一直拖到今天才真正准备写一篇博文来介绍. 再不介绍的话,估计几月后又要去故纸堆里翻东西了,毕竟个人笔记中总结记录的东西太多,搞不好哪天给意外弄丢了. 1 ...

  8. CODING 静态网站服务升级,快速、稳定、高拓展!

    CODING 静态网站拥有强大的页面托管服务,目前已有数万开发者.设计师.产品经理.团队与企业使用 CODING 静态网站托管了他(她)们的个人网站.博客.企业与产品官网.在线文档等.CODING 静 ...

  9. Java学习日报7.29

    package student;import java.util.*;public class student { Scanner sc=new Scanner(System.in); private ...

  10. ASP.Net中的TreeView控件中对节点的上移和下移操作

    Web中的TreeView中的没有PreNode和NextNode属性. 但它的集合属性中有一个IndexOf属性,从而能够找到它的前一个节点知后一个节点. TreeView中要么只有一个根节点:要么 ...