前面写过什么是面向对象编程以及如何进行面向对象编程:
之前我们采取的是继承的方式来复用代码,假如我们现在需要写多种不同表现形式的对象呢?例如弹窗,可能是登录框,也有可能是广告,或者其他的弹窗形式。这个时候再采取继承就有点不合适了,我们可以采用类似于兄弟关系的形式来提高对象的复用性。
还是用代码来说明。假设现在页面上有四个div,这四个div都有最基本的拖拽功能:
- div1的功能是实现简单的拖拽就可以了;
- div2需要在鼠标按下的时候,修改文档的标题;
- div3则是在鼠标按下及抬起的时候分别修改一次标题;
- div4需要在鼠标抬起的时候修改文档的标题;
window.onload = function () {
var d1 = new Drag();
d1.init('div1');
var d2 = new Drag();
d2.init('div2',function () {
document.title = 'hello';
});
var d3 = new Drag();
d3.init('div3',function () {
document.title = '明天';
},
function () {
document.title = '你好';
});
var d4 = new Drag();
d4.init('div4',function () {
document.title = 'bye~';
});
};
function Drag() {
this.obj = null;
this.disX = 0;
this.disY = 0;
}
Drag.prototype.init = function(id,toDown,toUp) {
this.obj = document.getElementById(id);
var that = this;
this.obj.onmousedown = function (e) {
e = e||window.event;
that.fnDown(e);
toDown();
document.onmousemove = function (e) {
e = e||window.event;
that.fnMove(e);
};
document.onmouseup = function () {
that.fnUp();
toUp();
};
return false;
};
};
Drag.prototype.fnDown = function(e) {
var that = this;
this.disX = e.clientX - this.obj.offsetLeft;
this.disY = e.clientY - this.obj.offsetTop;
};
Drag.prototype.fnMove = function(e) {
this.obj.style.left = e.clientX-this.disX +'px';
this.obj.style.top = e.clientY-this.disY +'px';
};
Drag.prototype.fnUp = function() {
document.onmousemove = null;
document.onmouseup = null;
};
OK,问题来了。
- init中传入了三个参数,并且调用了两个回调函数,那么div1因为没有传参会报错:
toDown is not a function
- div4传入了两个参数,系统无法确认参数的顺序,默认将传入的参数当成
id
和toDown
,虽然我们想要的是toUp
的效果
解决方案:
- 传入的参数采用
json
格式,只传入一个json对象,但是里面可以放很多东西。 - 使用
配置参数
和默认参数
,当有配置参数的时候,采用配置参数;没有配置参数的时候采用默认参数
var d1 = new Drag();
d1.init({ //配置参数
id:'div1',
});
var d2 = new Drag();
d2.init({ //配置参数
id:'div2',
toDown:function () {
document.title = 'hello';
document.body.background = 'black';
}
});
var d3 = new Drag();
d3.init({ //配置参数
id:'div3',
toDown:function () {
document.title = '明天';
},
toUp:function () {
document.title = '你好';
}
});
var d4 = new Drag();
d4.init({ //配置参数
id:'div4',
toUp:function () {
document.title = 'bye~';
}
});
};
function extend(obj1,obj2){
for(var attr in obj2){
obj1[attr] = obj2[attr];
}
}
//构造函数
function Drag() {
this.obj = null;
this.disX = 0;
this.disY = 0;
this.settings={ //默认参数
toDown:function () {},
toUp:function () {}
};
}
//初始化函数
Drag.prototype.init = function(opt) {
this.obj = document.getElementById(opt.id);
extend( this.settings , opt ); // 更新参数
var that = this;
this.obj.onmousedown = function (e) {
e = e||window.event;
that.fnDown(e);
that.settings.toDown();//这里调用默认参数
document.onmousemove = function (e) {
e = e||window.event;
that.fnMove(e);
};
document.onmouseup = function () {
that.fnUp();
that.settings.toUp();//这里调用默认参数
};
return false;
};
};
//下面的代码是一样的就不贴了
代码效果请戳☞[这里]
1.什么是组件?
所以,组件开发到底是什么?
- 对面向对象的深入应用(如:UI组件,功能组件)
- 将配置参数、方法、事件三者进行分离(如JqueryUI)
好的组件都是配置参数、方法、事件三者分离的,之前的拖拽例子并没有完整的实现组件开发。
下面是jqueryUI拖拽组件的API接口
参数和方法我们都知道,那么自定义事件是什么鬼?
(1)什么是自定义事件
自定义事件就是让函数具备事件的某些特性。
直接来栗子吧。
//这是一个正常的函数
function show(){
alert(1);
}
show(); //1
//自定义事件
window.addEventListener('show',function(){
alert(1);
},false);
show(); //1
2.原始类型的自动转换
var str = 'hello';
alert(str.length); //5
str.number = 10;
alert( str.number ); //undefined
3.包装对象自定义方法
var str = 'hello';
String.prototype.lastValue = function(){
return this.charAt(this.length-1);
};
alert( str.lastValue() ); //o