弹窗插件封装 js插件封装-弹窗组件封装-类型判断-发布订阅
https://gitee.com/eric167/js---
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="css/reset.min.css">
<link rel="stylesheet" href="css/modalplugin.css">
<style>
.box .form{
height: 40px;
display:flex;
justify-content:flex-start;
align-items:center;
}
.box .form span{
margin-right:3%;
width:30%;
text-align:right;
}
.box .form input{
width: 100%;
padding:0 5px;
height:30px;
box-sizing:border-box;
border:1px solid #eee;
}
</style>
</head>
<body>
<!-- <div class="drag_modal"></div>
<div class="drag_content">
<div class="drag_head">
系统温馨提示
<a href="javascript:;" class="drag_close"></a>
</div>
<div class="drag_main">
哈哈哈
</div>
<div class="drag_foot">
<a href="javascript:;" class="drag_button">取消</a>
<a href="javascript:;" class="drag_button">确定</a>
</div>
</div> -->
<button id="btn">点我</button>
<script src="./webpack/dist/modalplugin.min.js"></script>
<script>
console.log(window);
btn.onclick = function(){
// let m1 = M({
// drag:true, // 是否开启拖拽 默认开启
// title:"登录",
// template : `<div class="box">
// <div class="form">
// <span>用户名:</span>
// <input type="text" id="username"/>
// </div>
// <div class="form">
// <span>密码:</span>
// <input type="password" id="password"/>
// </div>
// </div>`,
// buttons:[
// {
// text:'取消',
// click(self){
// console.log(self);
// self.close();
// }
// },{
// text:'确定',
// click(self){
// let username = document.querySelector('#username'),
// password = document.querySelector('#password');
// console.log(username.value,password.value);
// self.close();
// }
// }
// ]
// })
let m2 = M({
template:"实现了插件组件封装",
title:"提示",
buttons:[
{
text:'确定',
click(self){
self.close();
}
}
],
// 周期函数 [回调函数,用户需要处理的事情都要写在两个回调函数当中]
onopen:self=>{
console.log('已打开',self);
},
onclose(){
console.log('已关闭',this);
}
})
// 周期函数 发布订阅,可以灵活的给某一个事件订阅自己要执行的方法
m2.ondragstart.on(self=>{
console.log('拖拽开始');
})
m2.ondraging.on(self=>{
console.log('拖拽中');
})
m2.ondragend.on(self=>{
console.log('拖拽结束');
})
}
</script>
</body>
</html>
------------------------------
/*
* 插件支持的配置信息(基于不同的配置信息,实现不同的功能):
* + title[string] 标题
* + template[string] 自定义的内容或者模板(基于ES6的模板字符串,拼接更丰富的内容结构)
* + buttons[array] 自定义按钮(组)
* [{text:'确定',click:[callback]},...]
* + modal[boolean] 控制遮罩层是否显示 默认是true
* + drag[boolean] 是否允许拖拽 默认是true
* + onopen[function] 打开
* + onclose[function] 关闭
* 拖拽的生命周期函数「当前操作的某个节点上,允许用户自定义处理的事情」
* 「发布订阅」
* + 拖拽开始 ondragstart
* + 拖拽中 ondraging
* + 拖拽结束 ondragend
*
* // 发布订阅
* // 工具库
*/
import utils from './lib/utils';
import Sub from './lib/sub';
// 插件的核心
function ModalPlugin(config){
let self = this;
self.config = config;
self.$drag_modal = null;
self.$drag_content = null;
self.startX = 0;
self.startY = 0;
self.startL = 0;
self.startT = 0;
self._MOVE = null;
self._UP = null;
// 如果开启拖拽 那就需要创建三个事件池
if(self.config.drag){
self.ondragstart = new Sub;
self.ondraging = new Sub;
self.ondragend = new Sub;
}
self.init();
}
ModalPlugin.prototype = {
version:'1.0.0',
constructor:ModalPlugin,
init(){
let self = this;
self.create();
// 基于事件委托实现 容器中元素点击处理的相关事务 关闭按钮 && 自定义按钮
if(self.$drag_content){
self.$drag_content.addEventListener('click',function(ev){
let target = ev.target,
targetTag = target.tagName,
targetClass = target.className;
// 关闭按钮
if(targetTag === 'A' && targetClass === 'drag_close') {
self.close();
return ;
}
// 自定义按钮
if(targetTag === 'A' && targetClass === 'drag_button') {
let index = +target.getAttribute('index'),
item = self.config.buttons[index];
// 判断 不为空 并且 是函数 就执行函数
if(item && utils.isFunction(item.click)){
item.click.call(self,self);
}
return ;
}
})
}
if(self.config.drag){
// 开启拖拽
let $drag_head = self.$drag_content.querySelector('.drag_head');
$drag_head.style.cursor = 'move';
$drag_head.addEventListener('mousedown',self.down.bind(self));
}
},
// 动态创建结构
create(){
let self = this,
config = self.config,
fragment = document.createDocumentFragment();
// 创建遮罩层
if(config.modal){
self.$drag_modal = document.createElement('div');
self.$drag_modal.className = 'drag_modal';
fragment.appendChild(self.$drag_modal);
}
// 创建内容
self.$drag_content = document.createElement('div');
self.$drag_content.className = 'drag_content';
self.$drag_content.innerHTML = `
<div class="drag_head">
${config.title}
<a href="javascript:;" class="drag_close"></a>
</div>
<div class="drag_main">${config.template} </div>
${config.buttons.length > 0 ?
` <div class="drag_foot">
${config.buttons.map((item,index) => {
return `<a href="javascript:;" class="drag_button" index="${index}">${item.text}</a>`
}).join('')}
</div> `
: ``}
`;
fragment.appendChild(self.$drag_content);
// 把动态元素添加到页面当中
document.body.appendChild(fragment);
fragment = null;
// 控制元素显示
self.$drag_content.offsetHeight; // 刷新渲染队列
self.$drag_modal ? self.$drag_modal.style.opacity = 1 : null;
self.$drag_content ? self.$drag_content.style.opacity = 1 : null;
// 改变盒子居中的方式
let HTML = document.documentElement;
self.$drag_content.style.left = `${(HTML.clientWidth - self.$drag_content.clientWidth)/2}px`;
self.$drag_content.style.top = `${(HTML.clientHeight - self.$drag_content.clientHeight)/2}px`;
self.$drag_content.style.transform = 'translate(0,0)';
// 触发开发的周期函数
self.config.onopen.call(self,self);
},
// 关闭弹窗
close(){
let self = this,
body = document.body;
if(self.$drag_modal){
self.$drag_modal.style.opacity = 0;
// 动画结束之后移除元素
self.$drag_modal.ontransitionend = () => {
body.removeChild(self.$drag_modal);
self.$drag_modal.ontransitionend = null;
}
}
if(self.$drag_content){
self.$drag_content.style.opacity = 0;
// 动画结束之后移除元素
self.$drag_content.ontransitionend = () => {
body.removeChild(self.$drag_content);
self.$drag_content.ontransitionend = null;
// 触发关闭的周期函数
self.config.onclose.call(self,self);
}
}
},
// 拖拽系列方法
down(ev){
let self = this;
self.startX = ev.pageX;
self.startY = ev.pageY;
self.startL = self.$drag_content.offsetLeft;
self.startT = self.$drag_content.offsetTop;
self._MOVE = self.move.bind(self);
self._UP = self.up.bind(self);
document.addEventListener('mousemove',self._MOVE);
document.addEventListener('mouseup',self._UP);
// 通知事件池中的方法执行
self.ondragstart.fire(self);
},
move(ev){
let self = this,
curL = ev.pageX - self.startX + self.startL,
curT = ev.pageY - self.startY + self.startT;
// 边界判断
let HTML = document.documentElement,
minL = 0,
minT = 0,
maxL = HTML.clientWidth - self.$drag_content.offsetWidth,
maxT = HTML.clientHeight - self.$drag_content.offsetHeight;
curL = curL < minL ? minL : (curL > maxL ? maxL : curL);
curT = curT < minT ? minT : (curT > maxT ? maxT : curT);
self.$drag_content.style.left = `${curL}px`;
self.$drag_content.style.top = `${curT}px`;
// 通知事件池中的方法执行
self.ondraging.fire(self);
},
up(){
let self = this;
document.removeEventListener('mousemove',self._MOVE);
document.removeEventListener('mouseup',self._UP);
// 通知事件池中的方法执行
self.ondragend.fire(self);
}
}
// 暴露的API
// 定义每一个参数规则
const props = {
title:{
type:'string',
default:"系统温馨提示"
},
template:{
type:'string',
required: true
},
buttons:{
type:'array',
default:[]
},
modal:{
type:'boolean',
default:true
},
drag:{
type:'boolean',
default:true
},
drag:{
type:'boolean',
default:true
},
onopen:{
type:'function',
default:()=>{}
},
onclose:{
type:'function',
default:()=>{}
},
}
const proxyModal = function proxyModal(options){
// 验证配置项
!options || !utils.isPlainObject(options) ? options = {} : null;
// console.log(options);
let config = {};
utils.each(props,(key,rule)=>{
let opValue = options[key],
{type,default:defaultValue,required} = rule;
// options 没有传递配置项 : 验证是否为必传 && 取参数默认值
if(typeof opValue === 'undefined'){
if(required) throw new TypeError(`${key} must be required`);
config[key] = defaultValue
return ;
}
// options 有传递 key 这一项, 验证值的格式 && 取传进来的值
if(utils.toType(opValue) !== type ) throw new TypeError(`${key} must be an ${type}`);
// 对象合并
config[key] = utils.merge(defaultValue,opValue);
});
return new ModalPlugin(config);
};
if(typeof window !== "undefined"){
window.M = window.ModalPlugin = proxyModal;
}
if(typeof module === "object" && typeof module.exports === 'object') {
module.exports = proxyModal;
}
-----------------------------------------
sub.js
function Sub() {
this.pond = [];
}
Sub.prototype = {
constructor: Sub,
on(func) {
let pond = this.pond;
!pond.includes(func) ? pond.push(func) : null;
},
off(func) {
let pond = this.pond;
pond.forEach((item, index) => item === func ? pond[index] = null : null);
},
fire(...params) {
let pond = this.pond;
for (let i = 0; i < pond.length; i++) {
let itemFunc = pond[i];
if (typeof itemFunc !== "function") {
pond.splice(i, 1);
i--;
continue;
}
itemFunc(...params);
}
}
};
export default Sub;
---------------------------
var getProto = Object.getPrototypeOf;
var class2type = {};
var toString = class2type.toString;
var hasOwn = class2type.hasOwnProperty;
var fnToString = hasOwn.toString;
var ObjectFunctionString = fnToString.call(Object);
[
"Boolean",
"Number",
"String",
"Symbol",
"Function",
"Array",
"Date",
"RegExp",
"Object",
"Error"
].forEach(function (name) {
class2type["[object " + name + "]"] = name.toLowerCase();
});
function toType(obj) {
if (obj == null) {
return obj + "";
}
return typeof obj === "object" || typeof obj === "function" ?
class2type[toString.call(obj)] || "object" :
typeof obj;
}
function isPlainObject(obj) {
var proto,
Ctor,
type = toType(obj);
if (!obj || type !== "object") {
return false;
}
proto = getProto(obj);
if (!proto) {
return true;
}
Ctor = hasOwn.call(proto, "constructor") && proto.constructor;
return typeof Ctor === "function" && fnToString.call(Ctor) === ObjectFunctionString;
}
function isFunction(obj) {
return typeof obj === "function" && typeof obj.nodeType !== "number";
};
function isWindow(obj) {
return obj != null && obj === obj.window;
};
function isArrayLike(obj) {
var length = !!obj && "length" in obj && obj.length,
type = toType(obj);
if (isFunction(obj) || isWindow(obj)) {
return false;
}
return type === "array" || length === 0 ||
typeof length === "number" && length > 0 && (length - 1) in obj;
}
function merge(obj1, obj2) {
let isPlain1 = isPlainObject(obj1),
isPlain2 = isPlainObject(obj2);
if (!isPlain1) return obj2;
if (!isPlain2) return obj1;
[
...Object.getOwnPropertyNames(obj2),
...Object.getOwnPropertySymbols(obj2)
].forEach(key => {
obj1[key] = merge(obj1[key], obj2[key]);
});
return obj1;
}
function each(obj, callback) {
var length, i = 0;
if (isArrayLike(obj)) {
length = obj.length;
for (; i < length; i++) {
if (callback.call(obj[i], i, obj[i]) === false) {
break;
}
}
} else {
var keys = [
...Object.getOwnPropertyNames(obj),
...Object.getOwnPropertySymbols(obj)
];
for (; i < keys.length; i++) {
var key = keys[i],
value = obj[key];
if (callback.call(value, key, value) === false) {
break;
}
}
}
return obj;
}
export default {
toType,
isPlainObject,
isFunction,
isWindow,
isArrayLike,
merge,
each
};
utils.js -> 封装好的工具类-》js类型验证
我是Eric,手机号是13522679763

浙公网安备 33010602011771号