简介
告诉组件Notification
罕用于全局展现告诉揭示信息。本文将剖析其源码实现,急躁读完,置信会对您有所帮忙。 组件文档 Notification gitee源码
更多组件分析详见 Element 2 源码分析组件总览 。
Notification vs Message
Notification
在性能配置以及源码实现上与 Message
十分相似,所以局部反复内容本文将不做详尽解释。为了更好了解,请先浏览 Message 组件实现、Message 服务实现。
Message
罕用于被动操作后的反馈提醒,
- 可提供胜利、正告和谬误等反馈信息。
- 顶部居中显示并主动隐没,是一种不打断用户操作的轻量级提醒形式。
Notification
罕用于显示全局的告诉揭示音讯。
- 较为简单的告诉内容。
- 零碎被动推送。
悬浮呈现在页面角落。
应用形式
跟Message
组件一样,Notification
以服务的形式调用。调用办法为 Notification(options)
,组件为每个 type 定义了各自的办法,如 Notification.success(options)
,并且能够调用 Notification.closeAll()
手动敞开所有实例。
options
参数配置项,在此不做详尽解释,详见 组件文档 Notification#options。
当组件库残缺引入,间接应用this.$notify(options)
。
// packages\notification\index.jsimport Notification from './src/main.js';export default Notification;// src/index.jsconst install = function(Vue, opts = {}) { Vue.prototype.$notify = Notification;};// 残缺引入this.$notify(options);// 独自援用import { Notification } from 'element-ui'; Notification(options);
组件源码
DOM构造
组件 Notification
的 DOM 层次结构跟 Alert
十分相似。
<transition name="el-notification-fade"> <!-- 组件根节点 --> <div class="el-notification"> <!-- icon 图标 --> <i class="el-notification__icon"></i> <!-- 文字内容区域 --> <div class="el-notification__group"> <!-- 题目 --> <h2 class="el-notification__title" v-text="title"></h2> <!-- 阐明文字 --> <div class="el-notification__content" v-show="message"> <slot> <p v-if="!dangerouslyUseHTMLString">{{ message }}</p> <p v-else v-html="message"></p> </slot> </div> <!-- 敞开按钮 --> <div class="el-notification__closeBtn el-icon-close"></div> </div> </div></transition>
类名为el-notification
的<div>
元素根节点 1️
,应用 transition
实现过渡成果,蕴含两个子节点:
2️
左侧的图标 。3️
右侧的文字内容区域 。4️
题目5️
阐明文字6️
敞开按钮(定位应用相对布局)
下图为组件Alert
的DOM层次结构,十分类似。具体能够浏览前文 源码分析之Alert 。
组件性能
事件监听器。它能够是 transitionend
或 animationend
notification
性能实现跟 message
相似,接下来次要阐明下不同之处,类似代码将省略。
// packages\notification\src\main.vue<template> <transition name="el-notification-fade"> <div :class="['el-notification', customClass, horizontalClass]" v-show="visible" :style="positionStyle" @mouseenter="clearTimer()" @mouseleave="startTimer()" @click="click" > // 省略... </div> </transition></template><script type="text/babel"> export default { data() { return { // ... title: '', // 题目 position: 'top-right' // 自定义弹出地位 }; }, computed: { // typeClass() 图标类名 // horizontalClass() 依据position 断定程度方向属性 // verticalProperty() 依据position 断定垂直方向属性 // positionStyle() }, watch: { // closed() }, methods: { // destroyElement() // click() 点击回调事件 // close() // clearTimer() // startTimer() // keydown }, mounted() { // startTimer // add keydown Listener }, beforeDestroy() { // remove keydown Listener } };</script>
生命周期 & 事件
跟message组件一样,当被挂载之后调用办法startTimer
启用定时器,实现实例的主动敞开。挂载之后增加keydown
事件监听。实例销毁之前,会移除keydown
事件监听。
根节点不仅绑定 mouseenter
、mouseleave
事件,也绑定了 click
事件,用于点击实例时调用传入的回调函数。
click() { if (typeof this.onClick === 'function') { this.onClick(); }},
组件 transition
没有绑定after-leave
钩子函数,而是在侦听器中增加了 transitionend
事件监听,调用办法 destroyElement
用于组件敞开后的销毁工作。
// watch 侦听closed(newVal) { if (newVal) { this.visible = false; this.$el.addEventListener('transitionend', this.destroyElement); // 增加过渡成果事件监听 }}// methodsdestroyElement() { this.$el.removeEventListener('transitionend', this.destroyElement); //移除过渡成果事件监听 // vm destroy && remove el },
办法 keydown
不仅实现按ESC
键敞开音讯组件,同时反对按backspace
detele
键取革除定时器,按其余键复原计时器。
keydown(e) { // 8 backspace 46 detele 革除定时器 if (e.keyCode === 46 || e.keyCode === 8) { this.clearTimer(); } else if (e.keyCode === 27) { // esc敞开音讯 if (!this.closed) { this.close(); } } else { this.startTimer(); // 复原计时器 }}
地位偏移
属性position
定义实例的弹出地位,反对四个选项:top-right
、top-left
、bottom-right
、bottom-left
,默认为top-right
。
组件应用相对定位,依据属性position
值断定高低、左右边界偏移属性。
计算属性verticalProperty
用于断定高低偏移属性应用top或bottom;计算属性positionStyle
基于 verticalProperty
值生成内联款式 top/bottom:20px
。
verticalProperty() { return /^top-/.test(this.position) ? 'top' : 'bottom';}, positionStyle() { return { [this.verticalProperty]: `${ this.verticalOffset }px` };}
左右偏移应用计算属性horizontalClass
生成类名right
或left
。
horizontalClass() { return this.position.indexOf('right') > -1 ? 'right' : 'left';},
相干款式定义:
.el-notification.right { right: 16px} .el-notification.left { left: 16px}
服务实现
Notification
在源码实现上与 Message
十分相似,具体的性能流程解说请浏览前文Message 服务实现,此处不在过多赘述。
源码精简后构造如下,代码创立了function
类型的对象Notification
,同时给对象增加属性办法 close
、closeAll
、 warning
、info
、 error
,导出对象 Notification
。
// packages\notification\src\main.jsconst NotificationConstructor = Vue.extend(Main); // 组件结构器 let instance; // 组件实例 let instances = []; // 存储所有组件实例数组let seed = 1; // 用于递增计数 const Notification = function(options) { // 逻辑 ...};['success', 'warning', 'info', 'error'].forEach(type => { // 逻辑 ...});Notification.close = function(id, userOnClose) { // 逻辑 ...};Notification.closeAll = function() { // 逻辑 ...};export default Notification;
Notification
反对自定义弹出地位,能够从屏幕四角中的任意一角弹出,然而所有实例都在保留在同一数组中,在款式计算的过程中,新增了逻辑辨别地位雷同的元素。
函数Notification
中,依据属性position
过滤元素个数,进行偏移量计算。即便未设置offset
值,组件默认偏移量为 16
。
const Notification = function(options) { // ... const position = options.position || 'top-right'; // ... let verticalOffset = options.offset || 0; instances.filter(item => item.position === position).forEach(item => { verticalOffset += item.$el.offsetHeight + 16; }); verticalOffset += 16; instance.verticalOffset = verticalOffset; // ...};
函数close
中,当删除实例后,从新计算只须要调整索引值大于以后实例index的偏移量,依据属性position
过滤元素,同时依据计算属性verticalProperty
更新DOM元素款式。
Notification.close = function(id, userOnClose) { // ... // 数据更新后 偏移量计算 const position = instance.position; const removedHeight = instance.dom.offsetHeight; for (let i = index; i < len - 1; i++) { if (instances[i].position === position) { instances[i].dom.style[instance.verticalProperty] = parseInt(instances[i].dom.style[instance.verticalProperty], 10) - removedHeight - 16 + 'px'; } }};// 计算属性verticalProperty() { return /^top-/.test(this.position) ? 'top' : 'bottom';},
款式实现
组件款式源码 packages\theme-chalk\src\notification.scss
应用混合指令 b
、when
、m
、e
嵌套生成组件款式。
// 生成 .el-notification@include b(notification) { // ... // 生成 .el-notification.right &.right { // ... } // 生成 .el-notification.left &.left { // ... } // 生成 .el-notification__group @include e(group) { // ... } // 生成 .el-notification__title @include e(title) { // ... } // 生成 .el-notification__content @include e(content) { // ... // 生成 .el-notification__content p p { // ... } } // 生成 .el-notification__icon @include e(icon) { // ... } // 生成 .el-notification__closeBtn @include e(closeBtn) { // ... // 生成 .el-notification__closeBtn:hover &:hover { // ... } } // 生成 .el-notification .el-icon-success/error/info/warning .el-icon-success { // color ... } // error/info/warning}.el-notification-fade-enter { // 生成 .el-notification-fade-enter.right &.right { // ... } // 生成 .el-notification-fade-enter.left &.left { // ... }}// 生成 .el-notification-fade-leave-active .el-notification-fade-leave-active { // ...}
关注专栏
如果本文对您有所帮忙请关注➕、 点赞、 珍藏⭐!您的认可就是对我的最大反对!
此文章已收录到专栏中 ,能够间接关注。