全网最详细之从0搭建网站系列(前端篇3)——自定义自己的弹出层

从本篇开始,我们就开始手写自己网站独特风格的组件。由于弹出框在网页用到很多,而且与用户具有良好的交互性,因此弹出框在设计、实现及展示上必须花费很大功夫。

目录

1、自定义自己的弹框

        1、简单的提示框:

        2、带配置项的提示框


       3、较复杂的弹出框


在线访问链接:链接 

源代码下载:链接

js依赖于zq.js:在线访问

        在写前端组件的时候,我们要明确一个组件都需要什么。首先我们写弹框的时候会发现很多样式和事件可以公用,我们就可以把这些公共部分封装成模板或者在js里动态装配(推荐),基于装配过程我们可以封装一些内部方法。然后暴露出不公共的部分封装成默认配置项和配置项,并将配置项暴露给开发者。然后将装配过程的一些对象返回给开发者,让其定制自己的样式或者事件。这样,我们根据配置项就能生成想要的组件和动态绑定事件。

1、自定义自己的弹框

        1、简单的提示框:

html代码:

<div class="panel-dialog-tips-base">
										<div class="panel-dialog-tips-base-msg">
											<span>普通的提示框:新增失败新增失败新增失败新增失败新增失败新增失败新增失败!</span>
										</div>
									</div>

 css样式如下:

            .panel-dialog-tips-base {
				min-height: 2rem;
				max-width: 16rem;
				text-align: center;
				top: 25%;
				line-height: 2rem;
			}
			.panel-dialog-tips-base-msg {
				background: rgba(0, 0, 0, 0.6);
				border-radius: 5px;
				max-width: 16rem;
				padding: 0 2rem;
			}
			.panel-dialog-tips-base-msg span {
				color: #fff;
				display: inline-block;
			}

       上图的html是很简单的,公共部分是外层两个div跟span标签,我们可以在js里自动装配它,唯一不同的内容就只有span标签的内容即弹出的内容,所以就可以作为配置项或者传参的内容。当然我们这个提示框没有关闭按钮,所以我们可以将弹出时间作为传参传入。这样的话,我们的配置项就是传入文本跟显示时间。默认配置项为显示时间为2s,即不传弹出时间默认2s关闭。

       如果要在整个页面弹出,我们需要修改一下样式,为了区分上面:

            .dialog-tips-base {
				min-height: 2rem;
				text-align: center;
				position: fixed;/*弹框是绝对绝对定位居中的*/
				top: 35%;
				line-height: 2rem;
				width: 100%;

			}
			.dialog-tips-base-msg {
				background: rgba(0, 0, 0, 0.6);
				border-radius: 5px;
				margin: auto;
				padding: 0 2rem;
				max-width: 16rem;
			}
			.dialog-tips-base-msg span {
				color: #fff;
				display: inline-block;
			}

        最后装配js是我最擅长的了,我们这次先以传参的形式去弹出,因为后面会有更复杂的弹框,只有我们做到最复杂的弹框的时候,才去写配置项,这是为了防止频繁的修改逻辑和没有必要的拓展,参数多了还要去适配前面简单的。所以我们做出较复杂的弹框后,才去抽取配置项跟事件:

        /**
		 * 弹出提示框
		 * @param {Object} msg 提示框的内容
		 * @param {Object} t 提示框显示时间,默认2s
		 */
		function openBaseDialog1(msg, t) {
			$(".dialog").remove();//先清空页面的提示框
			var $dialog = $("<div></div>").addClass("dialog-tips-base dialog").append($("<div></div>").addClass(
				"dialog-tips-base-msg").append($("<span></span>").append(msg)));
			$dialog.appendTo($("body"))
			setTimeout(function() {
				$dialog.remove()
			}, t || 2000)
		}
//或者function openBaseDialog1(msg, t=2000){...}

        2、带配置项的提示框

稍微拓展一下html就可以了:

<div class="panel-dialog-tips-base">
										<div class="panel-dialog-tips-base-msg">
											<span>普通的提示框:新增失败!</span>
											<div class="panel-dialog-tips-base-btn">
												<a class="dialog-tips-base-btn-btn1">好的</a>
												<a class="dialog-tips-base-btn-btn2 close-dialog">取消</a>
											</div>
										</div>
									</div>

拓展的css如下:

            .panel-dialog-tips-base-btn {
				display: flex;
				justify-content: center;
			}

			.panel-dialog-tips-base-btn a {
				display: block;
				color: var(--primary);
				width: 33%;
				height: 28px;
				line-height: 25px;
				text-decoration: none;
			}

        这个我们就可以封装成配置项了,因为提示框可能再也做不出什么花样来了。不公共的部分还是弹出内容,弹出时间,弹出按钮,弹出按钮的文字即其点击事件,我们就可以这么封装:

{
    msg:"提示框文本",//提示框文本
    time:2,//弹出时间
    btn:[//按钮
        //第一个按钮配置项,
        {
			btn_text: "好的",//按钮文本
            btn_type:"cancel",//按钮类型
			btn_fn: function() {
				alert("关闭");//按钮点击事件
			},
		}
     ]
}

//默认配置项
{
    "time":2,
    btn:[{
			btn_text: "取消",
			btn_fn: function() {
				closeDialog();
			},
		}
    ]
}

        最后就是根据配置项跟默认配置项装配我们的弹框了,这边我在按钮处也定制了一个默认的配置,当btn_type为cancel时,加载默认的取消按钮的配置项。js代码如下:

function openBaseDialog2(config) {
			//定义默认配置项
			var defaultConfig = {
				time:2000,
				btn:[
						{
							btn_text: "取消",
							btn_fn: function() {
								closeDialog();
							},
						}
				]
			};
			//传入的配置与默认配置项生成一个新的配置项,两者不同的字段都会生成在新配置项内,相同的字段又传入的覆盖默认的。
			var config = $.extend({}, defaultConfig, config);
			$(".dialog").remove();//只能弹出一个提示框,在弹出前将其他提示框移除
			var $dialog_btn = $("<div></div>").addClass("panel-dialog-tips-base-btn");
			$.each(config.btn,function(index,value){
				if(value.btn_type=="cancel"){//使用取消按钮的配置项
					value = {
						btn_text: "取消",
						btn_fn: function() {
							closeDialog();
						},
					}
				}
				$("<a></a>").append(value.btn_text).off("click").on("click", value.btn_fn).appendTo($dialog_btn);
			})
			//装配,把每一个共有的dom元素对象暴露出来,方便拓展
			var $dialog_span = $("<span></span>").append(config.msg);
			var $dialog_msg = $("<div></div>").addClass("dialog-tips-base-msg").append($dialog_span).append($dialog_btn);
			var $dialog = $("<div></div>").addClass("dialog-tips-base dialog").append($dialog_msg);
			$dialog.appendTo($("body"))
			setTimeout(function() {
				$dialog.remove()
			}, config.time)
		}
//内部方法,立刻关闭弹框
function closeDialog() {
			$(".dialog").remove();
		}

        最后,可以将刚开始那个简单的提示框加入配置项管理。 这里,有的童靴可能会想到关闭弹框用remove会不会很暴力,你的这个想法非常不错。因为我们的弹框的dom是在js动态装配跟操作的,比较耗时,所以每次弹框都去这么生成就很不好。这里关闭弹框我们可以将其隐藏,打开新弹框前只需在隐藏的弹框内改动较少的内容然后展示即可,稍后我将在带有查询功能的组件里用到这个思想。

 3、较复杂的弹出框

         首先我们看到的弹出框一般分三部分组成:头部,身体跟尾部。头部主要是标题,关闭的x,或者再加上最小化跟最大化,还有一个拖拉拽事件跟放缩事件。其中可加入配置项的部分是标题;头部样式;关闭x前回调;是否可以最小化最大化及其回调;是否可以拖拽;是否可以上下伸展;身体主要是内容,这方面有很多种情况,我们就可以预设一些默认的情况,通过在配置项加入类型来去加载不同的预设的一些内容。尾部就是最下面,一般是按钮,配置项就是按钮的一些样式跟回调。

<div class="modal-dialog" style="margin: 0;width: 100%;">
										<div class="modal-content">
											<div class="modal-header"><button class="close"><span>×</span></button><span
													class="modal-title">标题</span></div>
											<div class="modal-body"><img src="img/user-img.png"></div>
											<div class="modal-footer"><a>确定</a></div>
										</div>
									</div>

 补充样式如下:

            .modal {
				background-color: rgba(0, 0, 0, .6);
			}
           .model-body-main{
				display: flex;
				justify-content: center;
			}
			.modal-footer {
				padding: 15px;
				text-align: right;
				/* position: fixed; */
				border-top: 1px solid #e5e5e5;
				display: flex;
				justify-content: center;
			}
			.modal-footer a {
				display: block;
				height: 39px;
				line-height: 38px;
				padding: 0 18px;
				background-color: var(--primary);
				color: var(--white);
				white-space: nowrap;
				text-align: center;
				font-size: 14px;
				border: none;
				width: 90px;
				border-radius: 2px;
				cursor: pointer;
				margin-right: 5px;
			}
			.modal-footer a:hover {
				text-decoration: none;
				opacity: .8;
			}

        细心的同学已经发现了,这不是bootstrap的模态框吗?还真是,但是bootstrap的模态框的代码是写在html里面的,且是写在<dialog>标签内的,就会导致不会根据需求动态弹出想要的内容。因此我将其封装成一个弹框,但是样式是用bootstrap的样式。

        先实现一个简单组装过程:js依赖于zq.js:在线访问

function openModelDialog1(config) {
			
			var defaultConfig={
				dialogWidth:600,//默认弹框宽为600px
				dialogResizable:false,//默认弹框不能缩放
				dialogTop:100,//默认距离顶部100px+xpx
				dialogType:1,//默认弹框类型
				time:false,//默认不自动关闭
				head:{//默认头部配置
					title:"标题",//默认头部标题
					isDrag:false,//默认不能拖拽
					closeFn:function(){//默认点击x前回调,在回调内return false将不会关闭弹框
						
					}
				},
				body:{//默认身体
					html:"",//默认内容
					templet:"",//默认模板用[]占位
					data:{},//模板的数据
				},
				footer:{//默认尾部
					btn:[//默认按钮
						// {
						// 	btnText:"确定",
						// 	btnFn:function(){
						// 		zq.alert("点击了确定")
						// 	}
						// },
						// {
						// 	btnType:"cancel"
						// }
					]
				}
			};
			var config=zq.zmergeEx(defaultConfig,config);//合并传入的配置项跟默认配置项,相同的配置项由传入的覆盖默认的
			var model_index = $(".model").length;//获取当前页面有多少弹框
			var model_class = "model_" + model_index;//生成唯一的class
			var headConfig=config.head;//获取头部配置项
			var bodyConfig=config.body;//获取身体配置项
			var footerConfig=config.footer;//获取尾部配置项
			var $model_close = $("<button></button>").addClass("close").append("<span>×</span>");//生成右上x的JQ对象
			var $mode_title = $("<span></sapn>").addClass("modal-title").append(headConfig.title);//生成标题的JQ对象
			var $model_header = $("<div></div>").addClass("modal-header");//生成弹框顶部JQ对象
			$model_header.append($model_close).append($mode_title);//装配顶部
			var $mode_body;//定义身体的JQ对象
			if(bodyConfig.html==""){
				//如果配置项的html参数为空(注意由于html是默认配置项的内容,在合并的时候要么有值,要么是默认的""),就加载模板内容~~之后会将
				$mode_body = $("<div></div>").addClass("modal-body model-body-main").append(zq.loadTemplete(bodyConfig.templete,bodyConfig.data));
			}else{
				//如果配置项html参数不为空,将html填充至弹框身体内
				$mode_body = $("<div></div>").addClass("modal-body model-body-main").append(bodyConfig.html);
			}
			var $mode_footer;//定义尾部的JQ对象
			if(footerConfig.btn.length==0){
				//如果用户没有配置,将尾部JQ对象置为空,这样就装配不了尾部了
				$mode_footer="";
			}else{
				//如果用户配置了尾部
				var btnConfig=footerConfig.btn;//获取按钮的配置项
				$mode_footer = $("<div></div>").addClass("modal-footer");//生成尾部的JQ对象
				//遍历按钮配置项,装配按钮至尾部JQ对象
				$.each(btnConfig,function(index,value){
					if(zq.isUndefined(value.btnType)){
						//配置项无btnType,用配置项的配置
					}else if(value.btnType=="cancel"){//配置项有btnType,用预设的配置
						value={
							btnText:"取消",
							btnFn:function(){
								$model.remove();
							}
						}
					}
					//装配按钮
					$("<a>"+value.btnText+"</a>").on("click", function() {
						value.btnFn();
					}).appendTo($mode_footer);
				})
			}
			var $model = $("<div></div>").addClass("modal");//生成最外层JQ对象,这个承载了整个弹框的DOM的JQ对象包括遮罩
			var $model_dialog = $("<div></div>").addClass("modal-dialog").width(config.dialogWidth).offset({top:config.dialogTop});//生成弹框外围元素的JQ对象,这个是用于弹框外围定位
			var $model_content = $("<div></div>").addClass("modal-content");//生成弹框内部元素定位的JQ对象
			$model_content.append($model_header).append($mode_body).append($mode_footer);//装配
			$model.append($model_dialog.append($model_content))
				.addClass(model_class).appendTo("body").show();//整个弹框及模态框装配进入body并展示出来
			$model_close.on("click", function() {//右上x动态绑定回调
				zq.timeout().then(function(){
					if(headConfig.closeFn()===undefined||headConfig.closeFn()){//先执行回调函数后再关闭弹框,如果回调函数返回false将不会关闭弹框
						return zq.timeout(200).then(function(){
							$model.remove();
						});
					}else{
						return false;
					}
				})
			});
			if(config.time&&zq.elementType(config.time)=="number"){//如果配置项有时间,则等待一段时间自动关闭弹框
				setTimeout(function() {$model.remove()}, config.time);
			}
			if(headConfig.isDrag){//如果配置项(顶部)允许拖拽,将可以拖拽,基于JQueryUI
				$model.children(".modal-dialog").draggable({ scroll: true,cursor: "move",handle: ".modal-header" });
			}
			if(config.dialogResizable){//如果配置项允许缩放,则可以缩放,基于JQueryUI
				$model.children(".modal-dialog").resizable({minHeight: 150,minWidth: 200,});
			}
			//弹框成功将返回一个自定义对象给调用方,方便调用方根据回调内容做一些操作,如通过对象的model_class去关闭弹框
			return {
				"component_type":"model",
				"model_class":model_class
			};
		}
		
		/**
		 * 内部方法:关闭弹框
		 * @param {Object} index
		 */
		function closeModel(index){
			$("." + index).remove();
		}

        最后是调用:

        var classIndex=openModelDialog1(
							{
								dialogResizable:true,//允许缩放
								head:{
									title:"zqcy",//标题是zqcy
									isDrag:true,//允许拖拽
									closeFn:function(){
										alert("点击lx");
										//return false;
									}
								},
								body:{
									html:"<img src='img/user-img.png'>hoppinzq.com/video/view"//内容是一张图片
								},
								footer:{
									btn:[
										{
											btnText:"确定",
											btnFn:function(){//点击确定回调函数
												zq.alert("点击了确定");
												//在回调里closeModel(classIndex.model_class)关闭弹框
											}
										},
										{
											btnType:"cancel"
										}
									]
								}
							});
						console.log("该组件的返回值,可手动掉用closeModel(classIndex.model_class)关闭该弹框:"+classIndex);

效果拔群:

 最后将拓展一些预定样式即可。下篇将我第一个组件拓展进我们自己的js里

在线访问链接:链接 

源代码下载:链接

 未完待续。。。。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于全网详细的VSCode教程,以下是一个简短的描述: 全网详细的VSCode教程应该包含以下内容:基本介绍、安装和设置、编辑器布局、常用快捷键、实用插件和扩展、调试功能、版本控制、代码片段等。 在基本介绍部分,应该详细介绍VSCode是什么,它的优点和特点,如何下载和安装等。 安装和设置部分应该涵盖不同操作系统上的安装步骤和注意事项。同时,还应该介绍不同配置选项,如主题、字体、缩进设置等。 编辑器布局部分应该解释各个面板和视图的作用,如侧边栏、编辑窗口、终端等。详细说明如何调整布局以优化工作流程。 常用快捷键部分应该列举常用的快捷键和相关操作,如快速打开文件、搜索、查看定义等。应该对不同功能区分操作系统进行说明。 实用插件和扩展部分应该介绍一些常见和有用的插件,如代码片段、代码格式化、调试器等。应该详细解释如何安装和使用这些插件。 调试功能部分应该详细介绍如何配置和使用调试器,包括设置断点、查看变量的值等。 版本控制部分应该介绍如何使用内置的版本控制工具,如Git,如何提交、推送和拉取代码等。 最后,代码片段部分应该教授如何创建和使用代码片段,以提高编码效率。 以上仅是对全网详细的VSCode教程的一些简要描述。当然,真正最详细的教程可能比这个更加全面和详细,具体内容可能还包括更多高级功能和技巧。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值