通过 JavaScript 实现弹出层的简单方式
程序员文章站
2022-05-06 09:33:08
...
文件结构
文件结构参照下图,忽略 .vscode
文件夹
说明
- 点击按钮出现弹出层
- 允许用户自定义弹出框内容
- 弹出层存在时隐藏滚动条并禁止滚动
- 点击弹出框的按钮或右上角的 X 关闭弹出层
效果图
下图为弹出前样式
下图为弹出层样式
HTML 结构
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>弹出层练习</title>
<link rel="stylesheet" href="./main.css" />
</head>
<body>
<!-- 弹出层结构 -->
<!-- <div class="mask"></div>
<div class="modal-wrap">
<div class="modal">
<div class="modal-header">
<div class="modal-title">Title</div>
<div class="close">
<span></span>
<span></span>
</div>
</div>
<div class="modal-content">Content</div>
<div class="modal-footer">
<button class="modal-confirm">Confirm</button>
</div>
</div>
</div> -->
<!-- 用户定义弹出框内容 -->
<div class="user-input">
<input type="text" id="input-title" placeholder="请输入弹出框标题(默认为 Title)" />
<input type="text" id="input-content" placeholder="请输入弹出框内容(默认为 Content)" />
<input type="text" id="input-buttontext" placeholder="请输入弹出框关闭按钮文字(默认为 Confirm)" />
</div>
<!-- 点击按钮触发弹出层 -->
<div>
<button id="test">Trigger</button>
</div>
<script src="./main.js"></script>
</body>
</html>
CSS
body {
padding: 0;
margin: 0;
font-size: 14px;
}
.mask {
position: fixed;
height: 100vh;
width: 100vw;
top: 0;
left: 0;
z-index: 1;
background-color: rgba(0, 0, 0, 0.3);
overflow: hidden;
}
.user-input {
display: grid;
grid-template-columns: 400px;
grid-template-rows: repeat(3, 1fr);
row-gap: 10px;
margin-bottom: 10px;
}
.user-input input {
outline: none;
padding: 4px;
}
.modal-wrap {
position: fixed;
top: 0;
left: 0;
display: flex;
height: 100vh;
width: 100vw;
justify-content: center;
align-items: center;
z-index: 2;
overflow: hidden;
}
.modal {
background-color: #fff;
box-shadow: 0 0 30px rgba(0, 0, 0, 0.1);
width: 400px;
border-radius: 2px;
}
.modal-header,
.modal-content {
border-bottom: 1px solid #eee;
}
.modal-header {
position: relative;
}
.modal-title {
padding: 10px;
font-size: 16px;
font-weight: 700;
}
.close:hover span {
background-color: red;
}
.close {
position: absolute;
right: 10px;
top: 10px;
cursor: pointer;
width: 16px;
height: 16px;
}
.close span {
display: block;
position: absolute;
width: 16px;
height: 2px;
background-color: lightgray;
top: 50%;
transition: all 0.2s ease-out;
}
.close span:nth-child(1) {
transform: rotate(-45deg);
}
.close span:nth-child(2) {
transform: rotate(45deg);
}
.modal-content {
padding: 10px;
}
.modal-footer{
padding: 10px;
text-align: right;
}
JavaScript
// 隐藏滚动条并禁止滚动
let stopScroll = () => {
let body = document.querySelector('body');
body.style.overflow = 'hidden';
body.onmousewheel = () => false;
body.onkeydown = function (e) {
if (e.keyCode == 38 || e.keyCode == 40) {
return false;
}
}
}
// 显示滚动条并允许滚动
let openScroll = () => {
let body = document.querySelector('body');
body.style.overflow = 'auto';
body.onmousewheel = () => true;
body.onkeydown = function (e) {
if (e.keyCode == 38 || e.keyCode == 40) {
return true;
}
}
}
// 显示弹出框
let showModal = () => {
// 获取用户输入内容
let title = document.querySelector('#input-title').value;
let content = document.querySelector('#input-content').value;
let buttonText = document.querySelector('#input-buttontext').value;
title = title === '' ? undefined : title;
content = content === '' ? undefined : content;
buttonText = buttonText === '' ? undefined : buttonText;
let mask = genMask();
let modalWrap = genModalWrap();
let modal = genModal(title, content, buttonText);
let body = document.querySelector('body');
modalWrap.appendChild(modal);
body.appendChild(mask);
body.appendChild(modalWrap);
stopScroll();
return true;
}
// 隐藏弹出框
let hideModal = () => {
let mask = document.querySelector('.mask');
let modalWrap = document.querySelector('.modal-wrap');
let body = document.querySelector('body');
body.removeChild(mask);
body.removeChild(modalWrap);
openScroll();
return true;
}
// 生成指定名称的 tag 并添加相应的 class
let createElementWithClasslist = (name, classList = []) => {
let ele = document.createElement(name);
for (const v of classList) {
ele.classList.add(v);
}
return ele;
}
// 生成弹出框
let genModal = (title = 'Title', content = 'Content', buttonText = 'Confirm') => {
let modal = createElementWithClasslist('div', ['modal']);
// modalHeader
let modalHeader = createElementWithClasslist('div', ['modal-header']);
let modalTitle = createElementWithClasslist('div', ['modal-title']);
modalTitle.innerHTML = title;
let close = createElementWithClasslist('div', ['close']);
close.appendChild(document.createElement('span'));
close.appendChild(document.createElement('span'));
// 点击 X 关闭弹出框
close.addEventListener('click', hideModal);
modalHeader.appendChild(modalTitle);
modalHeader.appendChild(close);
// modalContent
let modalContent = createElementWithClasslist('div', ['modal-content']);
modalContent.innerHTML = content;
// modalFooter
let modalFooter = createElementWithClasslist('div', ['modal-footer']);
let modalConfirm = createElementWithClasslist('button', ['modal-confirm']);
modalConfirm.innerHTML = buttonText;
// 点击按钮关闭弹出框
modalConfirm.addEventListener('click', hideModal);
modalFooter.appendChild(modalConfirm);
// building
modal.appendChild(modalHeader);
modal.appendChild(modalContent);
modal.appendChild(modalFooter);
// return element
return modal;
}
// 生成遮罩层
let genMask = () => {
return createElementWithClasslist('div', ['mask']);
}
// 生成弹出框的 wrapper
let genModalWrap = () => {
return createElementWithClasslist('div', ['modal-wrap']);
}
// 为按钮绑定事件(点击时出现弹出层)
let testButton = document.querySelector('#test');
testButton.addEventListener('click', showModal);