javascript 封装函数
完整的插件的样子
;(function(window,document){
var MaskShare = function(){
};
MaskShare.prototype = {};
window.MaskShare = MaskShare;
}(window,document));
//前面加;是防止跟其他js压缩时报错
;(function(global){
//开启严格模式
"use strict";
//构造函数定义一个类 传参数
function Scroll(el,options) {
//some code
};
//原型上提供方法
Scroll.prototype = {
//定义方法
show: function() {
//some code
}
};
if (typeof module !== 'undefined' && module.exports) { //兼容CommonJs规范
module.exports = Scroll;
}else if (typeof define === 'function'){ //兼容AMD/CMD规范
define(function () {
return Scroll
})
}else { //注册全局变量,兼容直接使用script标签引入插件
global.Scroll = Scroll;
}
})(this);
// plugin.js
;(function(undefined) {
"use strict"
var _global;
var plugin = {
add: function(n1,n2){ return n1 + n2; },//加
sub: function(n1,n2){ return n1 - n2; },//减
mul: function(n1,n2){ return n1 * n2; },//乘
div: function(n1,n2){ return n1 / n2; },//除
sur: function(n1,n2){ return n1 % n2; } //余
}
// 最后将插件对象暴露给全局对象
_global = (function(){ return this || (0, eval)('this'); }());
if (typeof module !== "undefined" && module.exports) {
module.exports = plugin;
} else if (typeof define === "function" && define.amd) {
define(function(){return plugin;});
} else {
!('plugin' in _global) && (_global.plugin = plugin);
}
}());
表单验证插件
(function(window, document, undefined) {
// 插件的默认参数
var defaults = {
messages: {
required: 'The %s field is required.',
matches: 'The %s field does not match the %s field.',
"default": 'The %s field is still set to default, please change.',
valid_email: 'The %s field must contain a valid email address.',
valid_emails: 'The %s field must contain all valid email addresses.',
min_length: 'The %s field must be at least %s characters in length.',
max_length: 'The %s field must not exceed %s characters in length.',
exact_length: 'The %s field must be exactly %s characters in length.',
greater_than: 'The %s field must contain a number greater than %s.',
less_than: 'The %s field must contain a number less than %s.',
alpha: 'The %s field must only contain alphabetical characters.',
alpha_numeric: 'The %s field must only contain alpha-numeric characters.',
alpha_dash: 'The %s field must only contain alpha-numeric characters, underscores, and dashes.',
numeric: 'The %s field must contain only numbers.',
integer: 'The %s field must contain an integer.',
decimal: 'The %s field must contain a decimal number.',
is_natural: 'The %s field must contain only positive numbers.',
is_natural_no_zero: 'The %s field must contain a number greater than zero.',
valid_ip: 'The %s field must contain a valid IP.',
valid_base64: 'The %s field must contain a base64 string.',
valid_credit_card: 'The %s field must contain a valid credit card number.',
is_file_type: 'The %s field must contain only %s files.',
valid_url: 'The %s field must contain a valid URL.',
greater_than_date: 'The %s field must contain a more recent date than %s.',
less_than_date: 'The %s field must contain an older date than %s.',
greater_than_or_equal_date: 'The %s field must contain a date that\'s at least as recent as %s.',
less_than_or_equal_date: 'The %s field must contain a date that\'s %s or older.'
},
callback: function(errors) {
}
};
var ruleRegex = /^(.+?)\[(.+)\]$/,
numericRegex = /^[0-9]+$/,
integerRegex = /^\-?[0-9]+$/,
decimalRegex = /^\-?[0-9]*\.?[0-9]+$/,
emailRegex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/,
alphaRegex = /^[a-z]+$/i,
alphaNumericRegex = /^[a-z0-9]+$/i,
alphaDashRegex = /^[a-z0-9_\-]+$/i,
naturalRegex = /^[0-9]+$/i,
naturalNoZeroRegex = /^[1-9][0-9]*$/i,
ipRegex = /^((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})$/i,
base64Regex = /[^a-zA-Z0-9\/\+=]/i,
numericDashRegex = /^[\d\-\s]+$/,
urlRegex = /^((http|https):\/\/(\w+:{0,1}\w*@)?(\S+)|)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/,
dateRegex = /\d{4}-\d{1,2}-\d{1,2}/;
... //省略后面的代码
})(window,document);
/*
* Export as a CommonJS module
*/
if (typeof module !== 'undefined' && module.exports) {
module.exports = FormValidator;
}
onmousedown,onmouseover,onmouseout事件
(function (window, undefined) {
var dom = {
//绑定事件
on: function (node, eventName, handler) {
if (node.addEventListener) {
node.addEventListener(eventName, handler);
} else {
node.attachEvent("on" + eventName, handler);
}
},
//获取元素的样式
getStyle: function (node, styleName) {
var realStyle = null;
if (window.getComputedStyle) {
realStyle = window.getComputedStyle(node, null)[styleName];
} else if (node.currentStyle) {
realStyle = node.currentStyle[styleName];
}
return realStyle;
},
//获取设置元素的样式
setCss: function (node, css) {
for (var key in css) {
node.style[key] = css[key];
}
},
};
//#region 拖拽元素类
function DragElement(node) {
this.node = node;
this.x = 0;
this.y = 0;
}
DragElement.prototype = {
constructor: DragElement,
init: function () {
this.setEleCss({
left: dom.getStyle(node, "left"),
top: dom.getStyle(node, "top"),
}).setXY(node.style.left, node.style.top);
},
setXY: function (x, y) {
this.x = parseInt(x) || 0;
this.y = parseInt(y) || 0;
return this;
},
setEleCss: function (css) {
dom.setCss(this.node, css);
return this;
},
};
//#endregion
//#region 鼠标元素
function Mouse() {
this.x = 0;
this.y = 0;
}
Mouse.prototype.setXY = function (x, y) {
this.x = parseInt(x);
this.y = parseInt(y);
};
//#endregion
//拖拽配置
var draggableConfig = {
zIndex: 1,
draggingObj: null,
mouse: new Mouse(),
};
function Drag(ele) {
this.ele = ele;
function mouseDown(event) {
var ele = event.target || event.srcElement;
draggableConfig.mouse.setXY(event.clientX, event.clientY);
draggableConfig.draggingObj = new DragElement(ele);
draggableConfig.draggingObj
.setXY(ele.style.left, ele.style.top)
.setEleCss({
zIndex: draggableConfig.zIndex++,
position: "relative",
});
}
ele.onselectstart = function () {
//防止拖拽对象内的文字被选中
return false;
};
dom.on(ele, "mousedown", mouseDown);
}
dom.on(document, "mousemove", function (event) {
if (draggableConfig.draggingObj) {
var mouse = draggableConfig.mouse,
draggingObj = draggableConfig.draggingObj;
draggingObj.setEleCss({
left: parseInt(event.clientX - mouse.x + draggingObj.x) + "px",
top: parseInt(event.clientY - mouse.y + draggingObj.y) + "px",
});
}
});
dom.on(document, "mouseup", function (event) {
draggableConfig.draggingObj = null;
});
window.Drag = Drag;
})(window, undefined);
调用方法:Drag(document.getElementById(“obj”));
注意的一点,为了防止选中拖拽元素中的文字,通过onselectstart事件处理程序return false来处理这个问题。
弹框的顶部是可以进行拖拽操作的,内容区域是不可拖拽的,怎么实现这样的效果呢:
首先优化拖拽元素对象如下,增加一个目标元素target,表示被拖拽对象,在上图的登录框中,就是整个登录窗口。
被记录和设置坐标的拖拽元素就是这个目标元素,但是它并不是整个部分都是拖拽的有效部分。我们在html结构中为拖拽的有效区域添加类draggable表示有效拖拽区域:
<div id="obj1" class="dialog" style="position:relative;left:50px">
<div class="header draggable">
拖拽的有效元素
</div>
<div class="content">
拖拽对象1
</div>
</div>
然后修改Drag方法如下:
function drag(ele) {
var dragNode = (ele.querySelector(".draggable") || ele);
dom.on(dragNode, "mousedown", function (event) {
var dragElement = draggableConfig.dragElement = new DragElement(ele);
draggableConfig.mouse.setXY(event.clientX, event.clientY);
draggableConfig.dragElement
.setXY(dragElement.target.style.left, dragElement.target.style.top)
.setTargetCss({
"zIndex": draggableConfig.zIndex++,
"position": "relative"
});
}).on(dragNode, "mouseover", function () {
dom.setCss(this, draggableStyle.dragging);
}).on(dragNode, "mouseout", function () {
dom.setCss(this, draggableStyle.defaults);
});
}
主要修改的是绑定mousedown的节点变成了包含draggable类的有效元素,如果不含有draggable,则整个元素都是有效元素。
性能优化和总结
由于onmousemove在一直调用,会造成一些性能问题,我们可以通过setTimout来延迟绑定onmousemove事件,改进move函数如下
function move(event) {
if (draggableConfig.dragElement) {
var mouse = draggableConfig.mouse,
dragElement = draggableConfig.dragElement;
dragElement.setTargetCss({
left: parseInt(event.clientX - mouse.x + dragElement.x) + "px",
top: parseInt(event.clientY - mouse.y + dragElement.y) + "px",
});
dom.off(document, "mousemove", move);
setTimeout(function () {
dom.on(document, "mousemove", move);
}, 25);
}
}
编写UI组件
一般情况,如果一个js仅仅是处理一个逻辑,我们称之为插件,但如果与dom和css有关系并且具备一定的交互性,一般叫做组件。当然这没有什么明显的区分,只是一种习惯性叫法。
利用原型链,可以将一些UI层面的业务代码封装在一个小组件中,并利用js实现组件的交互性。
现有一个这样的需求:
- 实现一个弹层,此弹层可以显示一些文字提示性的信息;
- 弹层右上角必须有一个关闭按扭,点击之后弹层消失;
- 弹层底部必有一个“确定”按扭,然后根据需求,可以配置多一个“取消”按扭;
- 点击“确定”按扭之后,可以触发一个事件;
- 点击关闭/“取消”按扭后,可以触发一个事件。
根据需求,我们先写出dom结构:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
<link rel="stylesheet" type="text/css" href="index.css">
</head>
<body>
<div class="mydialog">
<span class="close">×</span>
<div class="mydialog-cont">
<div class="cont">hello world!</div>
</div>
<div class="footer">
<span class="btn">确定</span>
<span class="btn">取消</span>
</div>
</div>
<script src="index.js"></script>
</body>
</html>
* { padding: 0; margin: 0; }
.mydialog { background: #fff; box-shadow: 0 1px 10px 0 rgba(0, 0, 0, 0.3); overflow: hidden; width: 300px; height: 180px; border: 1px solid #dcdcdc; position: absolute; top: 0; right: 0; bottom: 0; left: 0; margin: auto; }
.close { position: absolute; right: 5px; top: 5px; width: 16px; height: 16px; line-height: 16px; text-align: center; font-size: 18px; cursor: pointer; }
.mydialog-cont { padding: 0 0 50px; display: table; width: 100%; height: 100%; }
.mydialog-cont .cont { display: table-cell; text-align: center; vertical-align: middle; width: 100%; height: 100%; }
.footer { display: table; table-layout: fixed; width: 100%; position: absolute; bottom: 0; left: 0; border-top: 1px solid #dcdcdc; }
.footer .btn { display: table-cell; width: 50%; height: 50px; line-height: 50px; text-align: center; cursor: pointer; }
.footer .btn:last-child { display: table-cell; width: 50%; height: 50px; line-height: 50px; text-align: center; cursor: pointer; border-left: 1px solid #dcdcdc; }
接下来,我们开始编写我们的交互插件。
我们假设组件的弹出层就是一个对象。则这个对象是包含了我们的交互、样式、结构及渲染的过程。于是我们定义了一个构造方法:
function MyDialog(){} // MyDialog就是我们的组件对象了
对象MyDialog就相当于一个绳子,我们只要往这个绳子上不断地挂上钩子就是一个组件了。于是我们的组件就可以表示为:
function MyDialog(){}
MyDialog.prototype = {
constructor: this,
_initial: function(){},
_parseTpl: function(){},
_parseToDom: function(){},
show: function(){},
hide: function(){},
css: function(){},
...
}
然后就可以将插件的功能都写上。不过中间的业务逻辑,需要自己去一步一步研究。无论如何写,我们最终要做到通过实例化一个MyDialog对象就可以使用我们的插件了。
在编写的过程中,我们得先做一些工具函数:
对象合并函数
// 对象合并
function extend(o,n,override) {
for(var key in n){
if(n.hasOwnProperty(key) && (!o.hasOwnProperty(key) || override)){
o[key]=n[key];
}
}
return o;
}
自定义模板引擎解释函数
// 自定义模板引擎
function templateEngine(html, data) {
var re = /<%([^%>]+)?%>/g,
reExp = /(^( )?(if|for|else|switch|case|break|{|}))(.*)?/g,
code = 'var r=[];\n',
cursor = 0;
var match;
var add = function(line, js) {
js ? (code += line.match(reExp) ? line + '\n' : 'r.push(' + line + ');\n') :
(code += line != '' ? 'r.push("' + line.replace(/"/g, '\\"') + '");\n' : '');
return add;
}
while (match = re.exec(html)) {
add(html.slice(cursor, match.index))(match[1], true);
cursor = match.index + match[0].length;
}
add(html.substr(cursor, html.length - cursor));
code += 'return r.join("");';
return new Function(code.replace(/[\r\t\n]/g, '')).apply(data);
}
查找class获取dom函数
// 通过class查找dom
if(!('getElementsByClass' in HTMLElement)){
HTMLElement.prototype.getElementsByClass = function(n, tar){
var el = [],
_el = (!!tar ? tar : this).getElementsByTagName('*');
for (var i=0; i<_el.length; i++ ) {
if (!!_el[i].className && (typeof _el[i].className == 'string') && _el[i].className.indexOf(n) > -1 ) {
el[el.length] = _el[i];
}
}
return el;
};
((typeof HTMLDocument !== 'undefined') ? HTMLDocument : Document).prototype.getElementsByClass = HTMLElement.prototype.getElementsByClass;
}
结合工具函数,再去实现每一个钩子函数具体逻辑结构:
// plugin.js
;(function(undefined) {
"use strict"
var _global;
...
// 插件构造函数 - 返回数组结构
function MyDialog(opt){
this._initial(opt);
}
MyDialog.prototype = {
constructor: this,
_initial: function(opt) {
// 默认参数
var def = {
ok: true,
ok_txt: '确定',
cancel: false,
cancel_txt: '取消',
confirm: function(){},
close: function(){},
content: '',
tmpId: null
};
this.def = extend(def,opt,true);
this.tpl = this._parseTpl(this.def.tmpId);
this.dom = this._parseToDom(this.tpl)[0];
this.hasDom = false;
},
_parseTpl: function(tmpId) { // 将模板转为字符串
var data = this.def;
var tplStr = document.getElementById(tmpId).innerHTML.trim();
return templateEngine(tplStr,data);
},
_parseToDom: function(str) { // 将字符串转为dom
var div = document.createElement('div');
if(typeof str == 'string') {
div.innerHTML = str;
}
return div.childNodes;
},
show: function(callback){
var _this = this;
if(this.hasDom) return ;
document.body.appendChild(this.dom);
this.hasDom = true;
document.getElementsByClass('close',this.dom)[0].onclick = function(){
_this.hide();
};
document.getElementsByClass('btn-ok',this.dom)[0].onclick = function(){
_this.hide();
};
if(this.def.cancel){
document.getElementsByClass('btn-cancel',this.dom)[0].onclick = function(){
_this.hide();
};
}
callback && callback();
return this;
},
hide: function(callback){
document.body.removeChild(this.dom);
this.hasDom = false;
callback && callback();
return this;
},
modifyTpl: function(template){
if(!!template) {
if(typeof template == 'string'){
this.tpl = template;
} else if(typeof template == 'function'){
this.tpl = template();
} else {
return this;
}
}
// this.tpl = this._parseTpl(this.def.tmpId);
this.dom = this._parseToDom(this.tpl)[0];
return this;
},
css: function(styleObj){
for(var prop in styleObj){
var attr = prop.replace(/[A-Z]/g,function(word){
return '-' + word.toLowerCase();
});
this.dom.style[attr] = styleObj[prop];
}
return this;
},
width: function(val){
this.dom.style.width = val + 'px';
return this;
},
height: function(val){
this.dom.style.height = val + 'px';
return this;
}
}
_global = (function(){ return this || (0, eval)('this'); }());
if (typeof module !== "undefined" && module.exports) {
module.exports = MyDialog;
} else if (typeof define === "function" && define.amd) {
define(function(){return MyDialog;});
} else {
!('MyDialog' in _global) && (_global.MyDialog = MyDialog);
}
}());
到这一步,我们的插件已经达到了基础需求了。我们可以在页面这样调用:
<script type="text/template" id="dialogTpl">
<div class="mydialog">
<span class="close">×</span>
<div class="mydialog-cont">
<div class="cont"><% this.content %></div>
</div>
<div class="footer">
<% if(this.cancel){ %>
<span class="btn btn-ok"><% this.ok_txt %></span>
<span class="btn btn-cancel"><% this.cancel_txt %></span>
<% } else{ %>
<span class="btn btn-ok" style="width: 100%"><% this.ok_txt %></span>
<% } %>
</div>
</div>
</script>
<script src="index.js"></script>
<script>
var mydialog = new MyDialog({
tmpId: 'dialogTpl',
cancel: true,
content: 'hello world!'
});
mydialog.show();
</script>
插件的监听
弹出框插件我们已经实现了基本的显示与隐藏的功能。不过我们在怎么时候弹出,弹出之后可能进行一些操作,实际上还是需要进行一些可控的操作。就好像我们进行事件绑定一样,只有用户点击了按扭,才响应具体的事件。那么,我们的插件,应该也要像事件绑定一样,只有执行了某些操作的时候,调用相应的事件响应。
这种js的设计模式,被称为 订阅/发布模式,也被叫做 观察者模式。我们插件中的也需要用到观察者模式,比如,在打开弹窗之前,我们需要先进行弹窗的内容更新,执行一些判断逻辑等,然后执行完成之后才显示出弹窗。在关闭弹窗之后,我们需要执行关闭之后的一些逻辑,处理业务等。这时候我们需要像平时绑定事件一样,给插件做一些“事件”绑定回调方法。
我们jquery对dom的事件响应是这样的:
$(<dom>).on("click",function(){})
我们照着上面的方式设计了对应的插件响应是这样的:
mydialog.on('show',function(){})
则,我们需要实现一个事件机制,以达到监听插件的事件效果。关于自定义事件监听,可以参考一篇博文:漫谈js自定义事件、DOM/伪DOM自定义事件。在此不进行大篇幅讲自定义事件的问题。
最终我们实现的插件代码为:
// plugin.js
;(function(undefined) {
"use strict"
var _global;
// 工具函数
// 对象合并
function extend(o,n,override) {
for(var key in n){
if(n.hasOwnProperty(key) && (!o.hasOwnProperty(key) || override)){
o[key]=n[key];
}
}
return o;
}
// 自定义模板引擎
function templateEngine(html, data) {
var re = /<%([^%>]+)?%>/g,
reExp = /(^( )?(if|for|else|switch|case|break|{|}))(.*)?/g,
code = 'var r=[];\n',
cursor = 0;
var match;
var add = function(line, js) {
js ? (code += line.match(reExp) ? line + '\n' : 'r.push(' + line + ');\n') :
(code += line != '' ? 'r.push("' + line.replace(/"/g, '\\"') + '");\n' : '');
return add;
}
while (match = re.exec(html)) {
add(html.slice(cursor, match.index))(match[1], true);
cursor = match.index + match[0].length;
}
add(html.substr(cursor, html.length - cursor));
code += 'return r.join("");';
return new Function(code.replace(/[\r\t\n]/g, '')).apply(data);
}
// 通过class查找dom
if(!('getElementsByClass' in HTMLElement)){
HTMLElement.prototype.getElementsByClass = function(n){
var el = [],
_el = this.getElementsByTagName('*');
for (var i=0; i<_el.length; i++ ) {
if (!!_el[i].className && (typeof _el[i].className == 'string') && _el[i].className.indexOf(n) > -1 ) {
el[el.length] = _el[i];
}
}
return el;
};
((typeof HTMLDocument !== 'undefined') ? HTMLDocument : Document).prototype.getElementsByClass = HTMLElement.prototype.getElementsByClass;
}
// 插件构造函数 - 返回数组结构
function MyDialog(opt){
this._initial(opt);
}
MyDialog.prototype = {
constructor: this,
_initial: function(opt) {
// 默认参数
var def = {
ok: true,
ok_txt: '确定',
cancel: false,
cancel_txt: '取消',
confirm: function(){},
close: function(){},
content: '',
tmpId: null
};
this.def = extend(def,opt,true); //配置参数
this.tpl = this._parseTpl(this.def.tmpId); //模板字符串
this.dom = this._parseToDom(this.tpl)[0]; //存放在实例中的节点
this.hasDom = false; //检查dom树中dialog的节点是否存在
this.listeners = []; //自定义事件,用于监听插件的用户交互
this.handlers = {};
},
_parseTpl: function(tmpId) { // 将模板转为字符串
var data = this.def;
var tplStr = document.getElementById(tmpId).innerHTML.trim();
return templateEngine(tplStr,data);
},
_parseToDom: function(str) { // 将字符串转为dom
var div = document.createElement('div');
if(typeof str == 'string') {
div.innerHTML = str;
}
return div.childNodes;
},
show: function(callback){
var _this = this;
if(this.hasDom) return ;
if(this.listeners.indexOf('show') > -1) {
if(!this.emit({type:'show',target: this.dom})) return ;
}
document.body.appendChild(this.dom);
this.hasDom = true;
this.dom.getElementsByClass('close')[0].onclick = function(){
_this.hide();
if(_this.listeners.indexOf('close') > -1) {
_this.emit({type:'close',target: _this.dom})
}
!!_this.def.close && _this.def.close.call(this,_this.dom);
};
this.dom.getElementsByClass('btn-ok')[0].onclick = function(){
_this.hide();
if(_this.listeners.indexOf('confirm') > -1) {
_this.emit({type:'confirm',target: _this.dom})
}
!!_this.def.confirm && _this.def.confirm.call(this,_this.dom);
};
if(this.def.cancel){
this.dom.getElementsByClass('btn-cancel')[0].onclick = function(){
_this.hide();
if(_this.listeners.indexOf('cancel') > -1) {
_this.emit({type:'cancel',target: _this.dom})
}
};
}
callback && callback();
if(this.listeners.indexOf('shown') > -1) {
this.emit({type:'shown',target: this.dom})
}
return this;
},
hide: function(callback){
if(this.listeners.indexOf('hide') > -1) {
if(!this.emit({type:'hide',target: this.dom})) return ;
}
document.body.removeChild(this.dom);
this.hasDom = false;
callback && callback();
if(this.listeners.indexOf('hidden') > -1) {
this.emit({type:'hidden',target: this.dom})
}
return this;
},
modifyTpl: function(template){
if(!!template) {
if(typeof template == 'string'){
this.tpl = template;
} else if(typeof template == 'function'){
this.tpl = template();
} else {
return this;
}
}
this.dom = this._parseToDom(this.tpl)[0];
return this;
},
css: function(styleObj){
for(var prop in styleObj){
var attr = prop.replace(/[A-Z]/g,function(word){
return '-' + word.toLowerCase();
});
this.dom.style[attr] = styleObj[prop];
}
return this;
},
width: function(val){
this.dom.style.width = val + 'px';
return this;
},
height: function(val){
this.dom.style.height = val + 'px';
return this;
},
on: function(type, handler){
// type: show, shown, hide, hidden, close, confirm
if(typeof this.handlers[type] === 'undefined') {
this.handlers[type] = [];
}
this.listeners.push(type);
this.handlers[type].push(handler);
return this;
},
off: function(type, handler){
if(this.handlers[type] instanceof Array) {
var handlers = this.handlers[type];
for(var i = 0, len = handlers.length; i < len; i++) {
if(handlers[i] === handler) {
break;
}
}
this.listeners.splice(i, 1);
handlers.splice(i, 1);
return this;
}
},
emit: function(event){
if(!event.target) {
event.target = this;
}
if(this.handlers[event.type] instanceof Array) {
var handlers = this.handlers[event.type];
for(var i = 0, len = handlers.length; i < len; i++) {
handlers[i](event);
return true;
}
}
return false;
}
}
// 最后将插件对象暴露给全局对象
_global = (function(){ return this || (0, eval)('this'); }());
if (typeof module !== "undefined" && module.exports) {
module.exports = MyDialog;
} else if (typeof define === "function" && define.amd) {
define(function(){return MyDialog;});
} else {
!('MyDialog' in _global) && (_global.MyDialog = MyDialog);
}
}());
然后调用的时候就可以直接使用插件的事件绑定了。
var mydialog = new MyDialog({
tmpId: 'dialogTpl',
cancel: true,
content: 'hello world!'
});
mydialog.on('confirm',function(ev){
console.log('you click confirm!');
// 写你的确定之后的逻辑代码...
});
document.getElementById('test').onclick = function(){
mydialog.show();
}
给出此例子的demo,有需要具体实现的同学可以去查阅。