The introduction
Message prompt boxes are common in practical application scenarios. The most common one is the Message prompt box of element UI. We usually use them directly, but have we tried to explore the implementation principle and implement it ourselves? In order to enhance our personal ability and competitiveness, we can try to achieve such a message prompt box.
Implementation effect
Let’s take a look at the final implementation, as shown below:
The preparatory work
Set up the basic project structure
Let’s create a message folder, and then create an index. HTML file, along with message.js and message.css files, as follows:
Layout the message prompt box
In the HTML file, we can first implement a static message prompt as follows:
<div class="message">
<p>This is a prompt box</p>
<i class="message-close-btn">×</i>
</div>
Copy the code
And then message.css we put the basic CSS code:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* Message prompt container style */
.message {
position: fixed;
left: 50%;
transform: translateX(50%);display: flex;
align-items: center;
min-width: 300px;
background-color: #edf2fc;
border: 1px solid #edf2fc;
padding: 16px 17px;
top: 25px;
border-radius: 6px;
overflow: hidden;
z-index: 1000;
}
/* Close button style */
.message > .message-close-btn {
position: absolute;
right: 15px;
top: 50%;
transform: translateY(50%);color: #c0c0c4;
font-size: 17px;
cursor: pointer;
}
.message > .message-close-btn:hover..message > .message-close-btn:active {
color: # 909399;
}
/* Message prompt content style */
.message p {
line-height: 1;
font-size:14px;
color: # 909399;
}
Copy the code
There are four types of prompt boxes, and to center the content, we simply add a class name to the CSS style. For example, to center the content, we just need to add a class name to the CONTAINER element of the HTML prompt box, as follows:
<div class="message message-center">
<p>This is a prompt box</p>
<i class="message-close-btn">×</i>
</div>
Copy the code
Add the following CSS code to the CSS file:
/* Content centered */
.message.message-center {
justify-content: center;
}
Copy the code
Add a class name, and then change the background color and font color, so the HTML code looks like this:
<div class="message message-success">
<p>This is a success message box</p>
<i class="message-close-btn">×</i>
</div>
<div class="message message-warning">
<p>This is a warning box</p>
<i class="message-close-btn">×</i>
</div>
<div class="message message-error">
<p>This is an error message box</p>
<i class="message-close-btn">×</i>
</div>
Copy the code
CSS code is as follows:
/* Successful message box style */
.message.message-success {
background-color: #e1f3d8;
border-color:#e1f3d8;
}
.message.message-success p {
color: #67c23a;
}
/* Warning box style */
.message.message-warning{
background-color: #fdfce6;
border-color: #fdfce6;
}
.message.message-warning p{
color: #e6a23c;
}
/* Error box style */
.message.message-error {
background-color: #fef0f0;
border-color: #fef0f0;
}
.message.message-error p {
color: #f56c6c;
}
Copy the code
With that done, it’s time for our main focus, the JavaScript code, to try and comment it out.
Dynamically create a message box
Define four types of message prompt boxes
We define an object to represent the type of the message prompt, as follows:
// There are four types of message prompt boxes
let typeMap = {
info: "info".warning: "warning".success: "success".error: "error"
}
Copy the code
Add default configuration items
We analyze the configuration items that need to be passed in, such as content, closeTime, showClose button, center and message prompt box type. So the configuration items are defined as follows:
// Default configuration items of the prompt box
let messageOption = {
type: "info".closeTime: 600.center: false.showClose: false.content: "Default content"
}
Copy the code
Create a message prompt class
We use object-oriented programming thinking to think of the message prompt as a class object, so we just need to create a class. It can be created using es6’s class syntax, but for convenience, we use the constructor. Create a constructor Message that looks like this:
function Message(option) {
// This is an initialization
this.init(option);
}
Copy the code
Initialize the
After creating the message prompt constructor, we need to pass in the configuration items, and we do the initialization in the function. Let’s do the initialization.
Message.prototype.init = function (option) {
// Here we create the prompt box element and add the entire prompt box container element to the page
document.body.appendChild(this.create(option));
// Here set the top of the prompt box
this.setTop(document.querySelectorAll('.message'));
If closeTime is greater than 0, the prompt box will be closed by default
if (option.closeTime > 0) {
this.close(option.container, option.closeTime);
}
// Click the Close button to close the prompt box
if (option.close) {
option.close.onclick = (e) = > {
this.close(e.currentTarget.parentElement, 0); }}}Copy the code
Create prompt Box
In the previous initialization, we did a few things, first creating the prompt box container element and adding the prompt box container element to the page BOD. We also do dynamic calculation of the top of the prompt box and determine the default closing time passed in to close the prompt box, click the close button to close the prompt box. Let’s look at the method for creating the prompt box, which is the writing action of the create method. As follows:
Message.prototype.create = function (option) {
If showClose is set to false and closeTime is set to 0, then the close button will not be displayed
if(! option.showClose && option.closeTime <=0)option.showClose = true;
// Create the container element
let element = document.createElement('div');
// Set the class name
element.className = `message message-${option.type}`;
if (option.center) element.classList.add('message-center');
// Create the close button element and set the class name and content
let closeBtn = document.createElement('i');
closeBtn.className = 'message-close-btn';
closeBtn.innerHTML = '× ';
// Create the content element
let contentElement = document.createElement('p');
contentElement.innerHTML = option.content;
// Determine if the close button is displayed, then add the close button element to the prompt box container element
if (closeBtn && option.showClose) element.appendChild(closeBtn);
// Add the content element to the prompt container
element.appendChild(contentElement);
// Store the prompt container element and the close button element in the configuration item object
option.container = element;
option.close = closeBtn;
// Return to the prompt box container element
return element;
}
Copy the code
Realize the closing of the prompt box
As you can see, we create a close method and pass in the prompt container element to close a prompt box. Next, we implement the close method. As follows:
Message.prototype.close = function (messageElement, time) {
// Delay closing based on the time passed in. In effect, remove the element
setTimeout((a)= > {
// Check if there are two cases in which the prompt box container elements are passed in. If there are multiple prompt box container elements, then iterate to delete them; if there is a single prompt box container element, then delete them directly
if (messageElement && messageElement.length) {
for (let i = 0; i < messageElement.length; i++) {
if(messageElement[i].parentElement) { messageElement[i].parentElement.removeChild(messageElement[i]); }}}else if (messageElement) {
if(messageElement.parentElement) { messageElement.parentElement.removeChild(messageElement); }}// After the prompt container element is closed, we reset the top value of the prompt
this.setTop(document.querySelectorAll('.message'));
}, time * 10);
}
Copy the code
Realize the prompt box dynamic top
The last thing we need to implement is to dynamically calculate the top of the message prompt boxes, and then keep the message prompt boxes from overlapping. The code is as follows:
Message.prototype.setTop = function (messageElement) {
// The reason for this is that when you click the last prompt in the page, it will be called again, and the prompt container element will not be retrieved, so the next set of top will not be performed
if(! messageElement || ! messageElement.length)return;
// Since the height of each prompt is the same, we only need to get the height of the first prompt element
const height = messageElement[0].offsetHeight;
for (let i = 0; i < messageElement.length; i++) {
// The top of each prompt box consists of a fixed value plus its height, and we want to multiply it by one of its indexes
messageElement[i].style.top = (25 * (i + 1) + height * i) + 'px'; }}Copy the code
Finally, implement encapsulation so that we can invoke the element UI as we would the element UI
If we want to call $message() or $message.info(), we can do this:
let $message = {};
window['$message'] = $message = function (option) {
let newMessageOption = null;
if (typeof option === 'string') {
newMessageOption = Object.assign(messageOption, { content: option });
} else if (typeof option === 'object'&&!!!!! option) { newMessageOption =Object.assign(messageOption, option);
}
return new Message(newMessageOption);
}
for (let key in typeMap) {
window['$message'][key] = function (option) {
let newMessageOption = null;
if (typeof option === 'string') {
newMessageOption = Object.assign(messageOption, { content: option,type:typeMap[key] });
} else if (typeof option === 'object'&&!!!!! option) { newMessageOption =Object.assign(JSON.parse(JSON.stringify(messageOption)),option,{ type:typeMap[key] });
}
return newMessage(newMessageOption); }}Copy the code
The logic is simple enough to determine the incoming configuration items, merge them, and pass them into the instantiated Message.
In this way, we complete a message prompt box.
Record video
If that doesn’t make sense, check out this video I made: