【js模块化+promise】让弹窗们弹起来

弹窗或者浮层是页面上看起来微不足道,却又常常起到重要作用的“零件”。比如最近做的项目中,一个页面上涉及了6个以上的弹窗及其对应的逻辑处理,可以说页面几乎是由弹窗逻辑构成的。因此,如何让这些弹窗优雅地弹起来(别人能够很快地对这些代码进行维护),是一个很重要的问题。

对于弹窗的实现,比较旧的做法是直接在html上加上弹窗的元素,在不需要的时候先将其隐藏,通过js逐个实现弹窗的展示和逻辑。但是这种做法在页面弹窗较多或者多个页面使用相同弹窗时,是非常繁琐的,且代码不易维护,复用度低。因此,本文将介绍js模块化结合promise打造弹窗的方法。

1.       js模块化

本文主要介绍弹窗的实现,因此不再过多赘述什么是js模块化,也不去对比AMD规范和CMD规范,如有疑问的可以参考Javascript模块化编程。后面将用具体的例子,一步一步说明弹窗的实现过程,例子中使用的js模块加载框架为SeaJS。

什么是SeaJS?

SeaJS的主要目的是令JavaScript开发模块化并可以轻松愉悦进行加载,将前端工程师从繁重的JavaScript文件及对象依赖处理中解放出来,可以专注于代码本身的逻辑。SeaJS可以与jQuery这类框架完美集成。使用SeaJS可以提高JavaScript代码的可读性和清晰度,解决目前JavaScript编程中普遍存在的依赖关系混乱和代码纠缠等问题,方便代码的编写和维护。

Ø  定义弹窗模块

SeaJS遵循CMD规范,因此一个模块就是一个js文件,通过define方法来定义,模块定义的方法如下:

define(function(require, exports, module) {
    // 模块代码
});

Ÿ   exports: 是一个对象,用来向外提供模块接口。通过exports.func=function(){};语句,则可以直接将该方法通过exports暴露出去,不需要将其return。当然也可以通过return的方法来向外提供接口。Ÿ   require: 是一个方法,接受模块标识作为唯一参数,用来获取其他模块提供的接口。也即是说在一个模块内部需要加载其他模块,可以通过require(‘./path/another’)实现。

Ÿ   module: 是一个对象,上面存储了与当前模块相关联的一些属性和方法。

本文的示例中,将弹窗定义到文件sample.js中,代码如下所示:

define(function (require, exports, module) {
    //弹窗dom,此处借用了之前项目中的弹窗样式
var tpl = '<style>.survey-confirm{font-family:微软雅黑;border:1px solid #dbdbdb;position:fixed;left:50%;top:40%;width:260px;height:140px;margin-left:-130px;background:#fff;z-index:1003}.survey-confirm-title{height:40px;line-height:40px;padding-left:16px;background:#f1f5fd;border-bottom:1px solid #b0c0e7;color:#2c4a93}.survey-confirm-content{height:40px;padding:10px;color:#333}.survey-confirm-button{text-align:center;height:20px;line-height:20px}.survey-mask{position:fixed;height:100%;width:100%;background:#aaa;z-index:1002;top:0;left:0;opacity:.5;filter:alpha(opacity:50)}.button{height:28x;line-height:18px;border-radius:3px;background:#f1f5fd;border:1px solid #b0c0e7;color:#2c4a93}</style><div class="sample-pop"><div class="survey-confirm"><div class="survey-confirm-title">Notice</div><div class="survey-confirm-content"></div><div class="survey-confirm-button"><input type="button" class="button  button-strong" id="survey-confirm-y" value="Confirm">   <input type="button" class="button" id="survey-confirm-n" value="Cancel"></div></div><div class="survey-mask"></div></div>'; 
// 暴露给外部的弹窗加载方法
exports.init = function () {
    // 加载弹窗
        $('body').append(tpl);
var pop = $('.sample-pop');
// button点击事件绑定
pop.find('.button').click(function() {
pop.remove();
});
    };
});

Ø  弹窗模块的调用 

在一个模块进行其他模块的加载,使用require方法,前面已经讲过。在页面上进行模块加载时,使用seajs.use。

// 加载一个模块,在加载完成时,执行回调
seajs.use('./a', function(a) {
    a.doSomething();
});

这里,我们在页面上添加一个button,用于触发弹窗,代码如下所示:

<html lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<title>seajs</title>
	<script src="sea.js" type="text/javascript" charset="utf-8" ></script>
	<script src="jquery.min.js" type="text/javascript" charset="utf-8"></script>
	<script src="sample.js" type="text/javascript" charset="utf-8" ></script>
</head>
<body>
	<input type="button" id="sea1" value="click1">
</body>
<script>
$(document).ready(function(){
    $('#sea1').click(function(){
	    seajs.use('sample', function (sa) {
              // 这里的sa即是模块的exports对象
		    sa.init();
		});
	});
});
</script>
</html>

此时,将弹窗模块化的工作算是告一段落,点击页面上的button,则可以加载出弹窗如下图所示:

Ø  通用的弹窗模块

为了在多个页面复用这个弹窗(或者一个页面的不同弹窗需求),我们需要让这个弹窗更加通用,比如文案,长宽自定义。因此我们需要对弹窗模块进行一些修改,代码如下所示:

define(function (require, exports, module) {
    var tpl = '…此处省略模板定义,同上…'; 
    exports.init = function (content, style, buttonConfirm, buttonCancel) {
        $('body').append(tpl);
var pop = $('.sample-pop');
pop.find('.survey-confirm-content').text(content);
if (style && style['height']) {
    pop.find('.survey-confirm').css('height',style['height']);
}
if (style && style['width']) {
    pop.find('.survey-confirm').css('width',style['width']);
}
if (buttonConfirm != 'Confirm') {
    if (buttonConfirm === null) {
    pop.find('#survey-confirm-y').hide();
}
else {
        pop.find('#survey-confirm-y').val(buttonConfirm);
}
}
if (buttonCancel != 'Cancel') {
    if (buttonCancel === null) {
    pop.find('#survey-confirm-n').hide();
}
else {
        pop.find('#survey-confirm-n').val(buttonCancel);
}
}
pop.find('.button').click(function() {
    pop.remove();
});
    };
});

而页面上,我们添加三个button来分别触发三个不同的弹窗调用,代码如下所示:

<html lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<title>seajs</title>
	<script src="sea.js" type="text/javascript" charset="utf-8" ></script>
	<script src="jquery.min.js" type="text/javascript" charset="utf-8"></script>
	<script src="sample.js" type="text/javascript" charset="utf-8" ></script>
</head>
<body>
	<input type="button" id="sea1" value="click1">
	<input type="button" id="sea2" value="click2">
	<input type="button" id="sea3" value="click3">
</body>
<script>
$(document).ready(function(){
    $('#sea1').click(function(){
	    seajs.use('sample', function (sa) {
		    sa.init('this is a sample', null, 'Confirm', 'Cancel');
		});
	});
	$('#sea2').click(function(){
	    seajs.use('sample', function (sa) {
		    sa.init('this is another sample', null, 'Yes', 'No,Thx');
		});
	});
	$('#sea3').click(function(){
	    seajs.use('sample', function (sa) {
		    sa.init('this is a alert', null, null, 'ok');
		});
	});
});
</script>
</html>

三个弹窗的效果依次如下图所示:


  

好的,到这里我们算是实现了可定制化复用的弹窗模块。接下来,我们该操心另一件事情了,那就是弹窗按钮的点击逻辑。

2.       Promise

什么是Promise?

Promise是CommonJS的规范之一,拥有resolve、reject、done、fail、then等方法,能够帮助我们控制代码的流程,避免函数的多层嵌套。如今异步在web开发中越来越重要,对于开发人员来说,这种非线性执行的编程会让开发者觉得难以掌控,而Promise可以让我们更好地掌控代码的执行流程,jQuery等流行的js库都已经实现了这个对象

在我们的例子中将使用JQuery的promise,来实现对弹窗逻辑的异步处理。JQuery提供了一个方法jQuery.Deferred(),用以创建一个Deferred对象。Deferred对象从名字可以看出,是一个延迟处理的方案。它提供了多个方法,用以实现在未来的某个时间点执行我们期望的回调。下面用具体的例子说明deferred方法的使用。

我们给上一节的三个弹窗分别命名为a、b、c,现在我们需要实现这样的逻辑,弹窗a弹出后,点击确定则弹出弹窗b,点击取消则弹出弹窗c(当然也可以有更复杂的逻辑,我们这里只是为了说明deferred)。

按照旧方法,我们是需要给弹窗a的两个按钮分别绑定点击处理事件的。对于这种弹窗的通用模块来说,这样做肯定是不好的。下面我们看看promise可以做些什么。

exports.init = function (content,style,buttonConfirm,buttonCancel) {
        var dtd = $.Deferred();   // 创建一个deferred对象
        $('body').append(tpl);
        /* 中间代码省略 */
pop.find('#survey-confirm-y').click(function() {
    pop.remove();
dtd.resolve(); // 将deferred对象的执行状态修改为已完成
});
pop.find('#survey-confirm-n').click(function() {
    pop.remove();
dtd.reject(); // 将deferred对象的执行状态修改为失败
});
return dtd.promise(); // 返回另一个deferred对象
    };

首先,我们在init函数中定义一个deferred对象dtd,然后分别在两个按钮的点击事件中调用deferred.resolve()和deferred.reject()方法。Deferred对象有三种状态,进行中,已完成和已失败。而这两个方法就分别为将deferred对象的状态修改为已完成和已失败。当deferred对象的执行状态发生变化后,会触发相应的回调方法,后面会讲到。而init方法会在最后执行deferred.promise()方法来返回另一个deferred对象,也即是我们说的promise。这个promise和原本的deferred对象不同,它不具有对deferred状态进行修改的方法(我们只用promise执行状态改变后的回调)。页面上的弹窗调用代码如下所示:

$('#sea1').click(function(){
    seajs.use('sample', function (sa) {
    sa.init('this is a sample', null, 'Confirm', 'Cancel')
.done(function(){  // 已完成状态触发调用done
            seajs.use('sample', function (sa) {
            sa.init('this is another sample', null, 'Yes', 'No, Thx');
            });	
        }).fail(function(){  // 已失败状态触发调用fail
            seajs.use('sample', function (sa) {
            sa.init('this is a sample', null, null, 'ok');
            });
});
    });
});

init方法调用后返回promise(也即是deferred对象),然后可以通过deferred.done(callback)和deferred.fail(callback)方法来指定deferred对象状态改变后的回调。示例代码中实现的则是已完成状态时调用弹窗b,而已失败状态时调用弹窗c。除了done和fail,还可以用deferred.then(callbackDone, callbackFail)方法来分别指定成功和失败后的回调。而deferred还有一个方法deferred.always(callback),不论状态值变为失败或成功,都执行指定的回调。当需要等待多个deferred对象都改变状态才执行回调时,可以用jquery.when(dtd1, dtd2)方法。

 

写到这里,我们想要的这种灵活的弹窗已经duang地弹起来啦~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值