Message 消息提示实现原理
使用 Vue 的小伙伴可能使用过 element-ui 中的 Message 消息提示
使用 React 的小伙伴可能使用过 ant-design Message 全局提示
Message.success({message: '消息提示'})
他们的原理都相似,这篇文章将会带你手写实现消息提示组件。
Vue
对于这样的消息组件,是用函数执行的进行调用,并不是在模板中直接使用组件的形式,不是组件那他们的 DOM 是如何创建到页面中显示出来的呢?其实还是利用了组件的虚拟 DOM 渲染的。
先准备好消息提示组件
<template> <div> <ul> <li v-for="(item, index) in messages" :key="index" class="message"> {{ item.message }} </li> </ul> </div> </template> <script> export default { data () { return { messages: [], id: 0 } }, methods: { add (options) { let layer = { id: this.id++, ...options } layer.timer = setTimeout(() => { this.remove(layer) }, 2000); this.messages.push(layer) }, remove (layer) { this.messages = this.messages.filter(item => item.id !== layer.id) } } } </script> <style> .message { position: fixed; left: 50%; top: 30px; transform: translate3d(-50%, 0, 0); background: #000; background: #f0f9eb; color: #67c23a; padding: 10px 20px; border-radius: 4px; animation: move 0.3s; } @keyframes move { 0% { top: 0; opacity: 0; } 100% { top: 30px; opacity: 1; } } ul,li { list-style: none; } </style>
然后调用方法再渲染 DOM 到页面
import Vue from 'vue' import MessageComponent from './MessageComponent.vue' class Msg { constructor () { let vm = new Vue({ render: h => h(MessageComponent) }).$mount() document.body.appendChild(vm.$el) this.component = vm.$children[0] } success (options) { this.component.add(options) } } Msg.getInstance = (function () { let instance; return function () { if (!instance) { instance = new Msg() } return instance } })() export const Message = Msg.getInstance()
React
先实现这个组件的 DOM 结构和基本的交换效果。 MessageComponent.js
文件
import React, { Component } from 'react'; import './Message.css' class MessageComponent extends Component { constructor(props) { super(props) this.state = { id: 0, messages: [], max: 5 } } add = (options) => { let { id, messages } = this.state let layer = { id: id++, ...options } layer.timer = setTimeout(() => { this.remove(layer) }, 2000); messages.push(layer) this.setState({ id, messages }) } remove = (layer) => { clearTimeout(layer.timer) let messages = this.state.messages.filter(item => item.id !== layer.id) this.setState({ messages }) } render() { return ( <ul> {this.state.messages.map( (item, index) => <li key={item.id} className="message">{item.message}</li> )} </ul> ); } } export default MessageComponent;
再加上一些样式。 Message.css
文件
.message { position: fixed; left: 50%; top: 30px; transform: translate3d(-50%, 0, 0); background: #000; background: #f0f9eb; color: #67c23a; padding: 10px 20px; border-radius: 4px; animation: move 0.3s; } @keyframes move { 0% { top: 0; opacity: 0; } 100% { top: 30px; opacity: 1; } } ul,li { list-style: none; }
现在组件和样式都准备好了,我们需要考虑组件如何渲染到页面中。通过用法我们知道 Message 是当做函数来直接使用的。说明函数执行的过程中会把消息组件渲染到页面中。
Message.success({ message: Math.random() }) }
原理
import React from 'react'; import ReactDOM from 'react-dom'; import MessageComponent from './MessageComponent' class Msg { constructor () { let myRef = {current: ''} const div = document.createElement('div') document.body.append(div) ReactDOM.render(<MessageComponent ref={myRef} />, div) this.refs = myRef } success (options) { this.refs.current.add(options) } } Msg.getInstance = (function () { let instance; return function () { if (!instance) { instance = new Msg() } return instance } })() export const Message = Msg.getInstance()
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

上一篇: 详解 Web 缓存
下一篇: 不要相信一个熬夜的人说的每一句话
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论