本文介绍如何从零封装一个轻量级的自定义模态框插件。通过原生JavaScript结合jQuery,实现遮罩层、水平垂直居中定位、多种入场动画(如fadeIn、scale)及自动关闭功能。该组件支持高度定制化的标题、内容及回调函数,旨在解决通用插件无法满足的复杂业务需求,提升开发效率。
自定义模态框插件的设计背景
在移动端前端开发中,弹出层提示信息是最常见的需求之一。虽然市面上有许多流行的弹窗插件可供选择,例如经典的artDialog或视觉效果出色的SweetAlert,但它们往往难以完全覆盖所有个性化场景。
随着项目需求的日益复杂,开发者逐渐发现,通用的弹窗插件通常只能满足大部分基础要求。当定制化需求较高时,花费时间修改现有插件可能不如直接封装一个符合个人开发习惯的弹窗组件,这将显著提升后续项目的开发效率。
首先梳理实现思路。原生JavaScript虽然提供了alert()方法,但它会阻塞主线程且界面体验较差,因此不予采用。从结构上看,弹窗主要由两部分组成:一是覆盖全屏的半透明遮罩层,用于遮挡底层内容;二是弹窗主体,通常需要进行水平垂直居中,并包含可定制的标题与内容区域。若为模态框,还需提供确认或取消按钮,以及弹出和关闭时的动画效果。
基于上述分析,完全可以自行封装一个通用组件,并将其集成到项目的公共JavaScript库中。遵循“能手写尽量不使用第三方插件”的原则,有助于保持代码的轻量与可控。
默认属性与初始化配置
在封装过程中,首先需要定义一组默认属性值,以规范组件的基础行为。
通过遍历默认配置对象,将传入的opts参数与默认值进行合并。在弹窗实例化前,若配置了before()方法,则执行该回调作为准备工作。
var defaultOpts = {
title: '',//标题
content: '',//内容 文字 || html
height: 50,//默认屏幕(父级)的50%
width: 80,//默认屏幕(父级)的80%
type: 'alert-default',//弹框类型
effect: 'fadeIn',//出现效果,默认下跌落
delayTime: 500,//效果延时时间,默认.5s
autoClose: false,//自动关闭
autoTime: 2000, //自动关闭时间默认2s
autoEffect: 'default',//关闭效果
ok: '确定',
okCallback: function(){},//确定回调
cancel: '取消',
cancelCallback: function(){},//取消回调
before : function() {
console.log('before')
},
close: function() {
console.log('close')
},
blankclose: false//空白处点击关闭
}
for (i in defaultOpts) {
if (opts[i] === undefined) {
opts[i] = defaultOpts[i]
}
}
opts.before && opts.before()
DOM结构构建与居中定位
接下来构建DOM结构,这是弹窗渲染的核心部分。
定义一个数组对象来存储弹窗的DOM元素,包括代表全屏遮罩层的alert-mask和代表弹窗主体内容的alert-content。利用join('')方法将数组拼接为HTML字符串,并通过jQuery的append()方法将其追加到body节点的末尾。
var alertHtml = [
'<section class="alert-main" id="alertMain">',
'<div class="alert-mask li-opacity" id="alertMask"></div>',
'<div class="alert-content '+ opts.type +'" id="alertContent">',
opts.content +'</div>',
'</section>'
]
$('body').append(alertHtml.join(''))
DOM生成后,需要处理尺寸与定位,确保弹窗在页面中居中显示。
此处采用fixed定位方式。高度设为传入的height百分比值,top值计算为(100 - height) / 2,从而实现垂直居中;同理,left值计算为(100 - width) / 2,实现水平居中。这种方法经过长期实践验证,兼容各种屏幕尺寸,是较为简单实用的居中方案。
var $alertContent = $('#alertContent'),
$alertMain = $('#alertMain');
$alertContent.css({
'height': opts.height + '%',
'top': (100 - opts.height)/2 + '%',
'width': opts.width + '%',
'left': (100 - opts.width)/2 + '%'
})
$('.li-opacity').css({
'-webkit-animation-duration' : opts.delayTime/1000 + 's'
})
最后,为遮罩层设置动画执行时间,以实现淡入效果。具体的CSS动画定义可参考下方的@-webkit-keyframes opacity规则。
动画效果与交互逻辑实现
除了基础结构,弹窗的视觉动效也是用户体验的关键部分。
本插件实现了四种动画效果:fadeIn(跌落)、sideLeft(从左侧飞入)、scale(放大)以及info(提示信息)。通过定义包含对应CSS属性的集合对象,并利用两个setTimeout函数统一赋值,实现动画的平滑过渡。
var effect = {
'fadeIn': 'top',
'fadeInStart': '-100%',
'fadeInValue': (100 - opts.height)/2 + '%',
'sideLeft': 'left',
'sideLeftStart': '-100%',
'sideLeftValue': (100 - opts.width)/2 + '%',
'scale': '-webkit-transform',
'scaleStart': 'scale(0)',
'scaleValue': 'scale(1)',
'info': '-webkit-transform',
'infoStart': 'scale(1.2)',
'infoValue': 'scale(1)'
}
setTimeout(function(){
$alertContent.css(effect[opts.effect],effect[opts.effect + 'Start']).addClass('alert-show')
setTimeout(function(){
$alertContent.css(effect[opts.effect], effect[opts.effect + 'Value'])
opts.close && opts.close()
},10)
},opts.delayTime)
为了提升交互体验,通常允许用户点击弹窗外的空白区域来关闭弹窗。
通过绑定点击事件即可实现。需要注意的是,选择器需排除弹窗内容区域,仅对遮罩层绑定点击逻辑。同时,为防止事件冒泡影响页面其他元素,需调用stopPropagation()和preventDefault()阻止默认行为。
if(opts.blankclose) {
$('.alert-main :not(.alert-content)').on('click',function(event){
$alertMain.remove()
opts.close && opts.close()
event.stopPropagation()
event.preventDefault()
})
}
除了手动关闭,自动关闭功能也是常见需求。
当配置项autoClose为true且autoTime大于零时,插件会启动一个延时定时器。到达指定时间后,自动移除弹窗并触发关闭回调。
if(opts.autoClose && opts.autoTime > 0) {
setTimeout(function(){$alertMain.remove()},opts.autoTime)
opts.close && opts.close()
}
代码演示与资源获取
以下是具体的代码实现与演示部分。
CSS样式部分定义了弹窗的视觉外观及动画关键帧。
@-webkit-keyframes opacity {
0% {
opacity: 0; /*初始状态 透明度为0*/
}
50% {
opacity: 0; /*中间状态 透明度为0*/
}
100% {
opacity: 1; /*结尾状态 透明度为1*/
}
}
.li-opacity {
-webkit-animation-name: opacity; /*动画名称*/
-webkit-animation-iteration-count: 1; /*动画次数*/
-webkit-animation-delay: 0s; /*延迟时间*/
}
.alert-mask {
position: fixed;
height: 100%;
width: 100%;
left: 0%;
top: 0%;
z-index: 9998;
background-color: rgba(0,0,0,.7);
}
.alert-content {
position: fixed;
box-sizing: border-box;
border-radius: 4px;
z-index: 9999;
-webkit-transition: .4s;
-moz-transition: .4s;
transition: .4s;
display: none;
}
.alert-show {
display: block;
}
.alert-default {
background-color: white;
}
HTML结构部分展示了弹窗的基本DOM树结构。
<p class="alert" data-flag="fadeIn">fadeIn</p>
<p class="alert" data-flag="sideLeft">sideLeft</p>
<p class="alert" data-flag="scale">scale</p>
<p class="alert" data-flag="info">info</p>
JavaScript逻辑部分实现了弹窗的初始化、渲染及交互控制。
require.config({
jquery:'component/jquery/jquery-3.1.0.min',
liAlert: 'li/li-alert',//常用弹框组件
})
require(['jquery'],function($){
require(['liAlert'],function(){
$('.alert').on('click',function(event){
$.alert({
content: '<h1 style="display:flex;justify-content:center;">我是弹框</h1>',
effect: $(event.currentTarget).attr('data-flag'),
blankclose: true,
//autoClose: true
})
})
})
})
运行效果图展示了不同动画效果下的弹窗表现。

完整的源代码已上传至GitHub仓库:https://github.com/helijun/component/tree/master/alert,供参考与下载。
以上就是本文的全部内容,希望能为读者的前端开发工作提供帮助,也欢迎大家继续支持本站。