封装
- 原生js封装弹窗效果
主要目的呈现思路,动态创建样式,下面一些其它参数还没有处理;
通过实现过程可以更深刻理解闭包,this指向,oop,业务拆分,
(function(window){
function Popup(options) {
// 把用户的参数和默认的参数合并
var opts = Object.assign({},Popup.defaultOptions, options);
this.opts = opts;
this.w = window.innerWidth;
this.h = window.innerHeight;
this.mask = null;
this.view = null;
this.first = null;
this.init();
}
Popup.prototype = {
contructor: Popup,
init: function() {
this.initDom();
// this.renderView();
this.mask = document.body.querySelector(".mask");
this.view = document.body.querySelector(".view");
this.bindEvent(this.mask,"click", this.close)
this.initCss(this.mask);
this.initCss(this.view);
this.first = true;
},
//创建弹出层的dom结构
initDom() {
var strHtml = `
<div class="popup">
<div class="mask"></div>
<div class="view">
</div>
</div>
`
var popupDom = new DOMParser().parseFromString(strHtml,'text/html').body.childNodes[0];
document.body.appendChild(popupDom);
},
//删除节点
destoryDom() {
var popupNode = document.body.querySelectorAll(".popup");
if(popupNode.length <= 0) return;
Array.prototype.forEach.call(popupNode, (node) => {
document.body.removeChild(node);
})
},
//初始化节点样式
initCss(node) {
if(node.className == "mask") {
node.style.cssText = `
width: 100%;
height: 100vh;
background-color: black;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1;
opacity: 0;
visibility: hidden;
transition: all 2s linear;
`
}else if(node.className == "view") {
node.style.cssText = `
background-color: #fff;
position: absolute;
z-index: 1000;
display: block;
transition: all 2s linear;
`
node.style.cssText += this.initViewPosition();
}
},
open: function() {
if(this.first) {
this.changeStatus()
}else {
this.init();
setTimeout(() => {
this.changeStatus()
})
}
},
close: function() {
var mask = document.body.querySelector(".mask");
var view = document.body.querySelector(".view");
this.mask.style.opacity = 0;
this.mask.style.visibility = "hidden";
this.viewInitEnd("init");
this.first = false;
setTimeout(() => {
this.destoryDom();
}, 2000);// 这个时间和你过渡动画时间一致
},
//这里可以用es6语法优化,但是为了理解this指向问题,用es5语法改变this
bindEvent: function(node,event,cb) {
// 要达到效果:回调函数中的this指向,永远指向实例
node.addEventListener(event, function() {
cb && cb.call(this);
}.bind(this), false)
},
//控制显示层dom结构
renderView: function() {
this.view.append(this.opts.viewDom);
},
//控制显示层的方向
initViewPosition: function() {
console.log(this)
switch (this.opts.position) {
case "bottom":
return `
width: ${this.w}px;
height: 0;
left: 0;
bottom: 0;
`
break;
case "top":
return `
width: ${this.w}px;
height: 0;
left: 0;
top: 0;
`
break;
case "left":
return `
width: 0;
height: ${this.h}px;
left: 0;
top: 0;
`
break;
case "right":
return `
width: 0;
height: ${this.h}px;
right: 0;
top: 0;
`
break
}
},
//显示层的初始状态和关闭状态
viewInitEnd: function(type) {
if(type == "end") {
if(this.opts.position == ("top" || "bottom")) {
this.view.style.height = "200px"
}else {
this.view.style.width = "100px"
}
}else if(type == "init") {
if(this.opts.position == ("top" || "bottom")) {
this.view.style.height = 0
}else {
this.view.style.width = 0
}
}
},
//控制显示层动画时间
initViewTime: function() {
// 。。。
},
//改变后的样式状态
changeStatus() {
this.mask.style.opacity = .6;
this.mask.style.visibility = "visible";
this.viewInitEnd("end");
}
}
// 默认参数就是说明该插件具备的功能有哪些
Popup.defaultOptions = {
viewDom:null,
position:"bottom",//显示层的从那个方向出来,可选值为 top bottom right left
overlay_class:"",//自定义遮罩层类名
duration:300,//动画时长,单位毫秒
round:false,//是否显示圆角
lock_scroll: true,//是否锁定背景滚动
lazy_render: true,//是否在显示弹层时才渲染节点
close_on_click_overlay:true,//是否在点击遮罩层后关闭
closeable:false,//是否显示关闭图标
close_icon:"",//关闭图标名称或图片链接
close_icon_position:"top-right",//关闭图标位置,可选值为top-leftbottom-left bottom-right
get_container: "body",//弹窗挂在位置
}
return window.Popup = Popup
})(window)
- jquery 封装
下次更新
网友评论