/* message.css */ @keyframes message-move-out { 0% { opacity: 1; transform: translateY(0); } 100% { opacity: 0; transform: translateY(-100%); } } #message-container .message.move-out { animation: message-move-out 0.3s ease-in-out; /* 让动画结束后保持结束状态 */ animation-fill-mode: forwards; }
animation-fill-mode: forwards;这个是干嘛的呢?因为动画结束后默认会回到元素的最初状态,在这里表现的是消失后又出现了。
所以animation-fill-mode: forwards;是为了让动画结束后保持这个结束状态,也就是不在显示了。
4. 编写js插件
那么,在写js之前呢,我们先来思考一下,如果你是插件的使用者,你想怎么来调用这个插件?
我们的插件很简单,就是在需要的时候弹出一个消息,假设插件他提供给我们的是一个类,就叫做Message吧,并且他内部有一个show方法,那么只要使用者实例化这个类后,调用他的show方法,然后传入不同的参数就可以弹出一个消息了。而且我们所实例化的对象可以是全局唯一的。
<!-- message.html --> <!-- 省略... --> <script> // message可以定义为全局对象,项目中可以直接调用。 const message = new Message(); message.show({ type: 'success', text: '点个关注不迷路~' }); </script>
所以呢,我们要先写一个Message类,并且必须要实现一个show方法。
/* message.js */ class Message { constructor() { } show({ type = 'info', text = '' }) { } }
这里我直接用了es6的class关键词,其实他的内部还是原型链的形式。用class呢,可以让我们更直观的了解这个类。
根据我们在第一部分的分析,所有的消息元素都是需要在js中创建的,所以我们不需要使用者来写任何html代码,那么我们只需要在对象被实例化new Message()的时候,就去创建消息容器message-container,后续在调用show方法时候,直接把消息插入到message-container内部即可。
/* message.js */ class Message { /** * 构造函数会在实例化的时候自动执行 */ constructor() { const containerId = 'message-container'; // 检测下html中是否已经有这个message-container元素 this.containerEl = document.getElementById(containerId); if (!this.containerEl) { // 创建一个Element对象,也就是创建一个id为message-container的dom节点 this.containerEl = document.createElement('div'); this.containerEl.id = containerId; // 把message-container元素放在html的body末尾 document.body.appendChild(this.containerEl); } } show({ type = 'info', text = '' }) { } }
这样,我们调用const message = new Message()的时候会在dom中自动的插入一个message-container节点。
那么,最重要的还是我们的show方法:
创建一个消息节点,并把它追加到message-container容器的末尾。
设定一个时间,在这个时间结束后自动的将消息移除。
监听“关闭按钮”的click事件,来让用户可以手动的移除消息。
我们一步一步来。
4.1 创建一个消息节点,并把它追加到message-container容器的末尾。
class Message { // 省略... show({ type = 'info', text = '' }) { // 创建一个Element对象 let messageEl = document.createElement('div'); // 设置消息class,这里加上move-in可以直接看到弹出效果 messageEl.className = 'message move-in'; // 消息内部html字符串 messageEl.innerHTML = ` <span></span> <div>${text}</div> <div></div> `; // 追加到message-container末尾 // this.containerEl属性是我们在构造函数中创建的message-container容器 this.containerEl.appendChild(messageEl); }
我们来调用下试试~
<!-- message.html -->
<!-- 省略... -->
<button>弹窗消息提醒</button>
<script>
// message可以定义为全局对象,项目中可以直接调用。
const message = new Message();
document.querySelector('.btn').addEventListener('click', () => {
message.show({
type: 'success',
text: '点个关注不迷路~'
});
});
</script>
4.2 设定一个时间,在这个时间结束后自动的将消息移除。
// message.js class Message { // 省略... show({ type = 'info', text = '', duration = 2000 }) { // 省略... // 用setTimeout来做一个定时器 setTimeout(() => { // Element对象内部有一个remove方法,调用之后可以将该元素从dom树种移除! messageEl.remove(); }, duration); } }
可以看到,消息在过了2秒后,自动的从dom树中移除了,不过呢并没有动画,还记得前边我们写了move-out类吗?这个类和message是同级的。现在我们只需要在定时结束后把这个类应用到message元素上就行。