什么是面向对象
/*
* 什么是面向对象编程?
* - 用对象的思想去写代码,就是面向对象编程
* - 过程式写法
* - 面向对象写法
* */
面向对象编程的特点
/*
* OP编程的特点
* - 抽象:抓住核心问题
* - 封装:只能通过对象来访问方法
* - 继承:从已有对象上继承出新的对象
* - 多态:多对象的不同形态
* */
面向对象的基本写法和组成
/*
* 有两部分组成
* - 方法[可以去做某件事]
* - 属性[对象下面的方法] //不加括号是是属性,加括号是方法
*
* */
//var obj = {};//创建了一个json
var obj = new Object();//和上面的一样。创建了一个空的对象
obj.name = '小明';//属性
obj.showName = function(){//方法
alert(obj.name);
// alert(this.name);
}
/*
* this 谁调用的this就会指向谁
* */
obj.showName();
工厂方式和构造函数
/*
* 工厂方式就相当于封装函数
*
* 创建的对象new在里面,系统对象直接new
* 系统对象第一个是大写
* */
function createPerson(name){
var obj = new Object();
obj.name = name;
obj.showName = function(){
alert(this.name);
};
return obj;
}
createPerson('小明').showName();
createPerson('小强').showName();
/*
* 工厂方式就相当于封装函数
*
* 创建的对象new在里面,系统对象直接new
* 系统对象第一个是大写
*
* 当new去调用一个函数:这个时候函数中的this就是创建出来的对象,而且函数的返回值直接就是this[隐式返回],不用谢return
new后面的函数叫做构造函数
* */
function CreatePerson(name){
this.name = name;
this.showName = function(){
alert(this.name);
};
}
var p1 = new CreatePerson('小明');
p1.showName();
var p2 = new CreatePerson('小强');
p2.showName();
对象引用是什么和它的问题
alert(p1.showName == p2.showName);//false
基本类型和对象类型的复制区别:复制和引用
对象的值和引用都相同才行
如何让同样的方法只存在一份?
使用原型:去改写对象下面公用的方法或属性,让公用的东西在内存中只存在一份[好处就是提高性能]
面向对象之原型学习
/*原型:去改写对象下面公用的方法或者属性,让公用的方法火属性在内存中存在一份[提高性能]*/
/*
*
*
* 概念:重写对象方法,让相同的方法在内存中存在一份[提高性能]
* 类比:CSS中的class
* 通过原型改写工厂方法
* > 相同的属性和方法可以加载在原型上
* > 混合的编程模式
*
* 总结面向对象方法
* - 构造函数加属性,原型和方法
* */
/*
* 原型:prototype 要写在构造函数下面
* */
/* var arr = [1,2,3,4,5];
var arr2 = [1,2,3,4,5];
arr.sum = function(){
var result = 0;
for(var i=0;i<this.length;i++){
result+=this[i];
}
return result;
}
console.log(arr.sum());
//console.log(arr2.sum());//这样是会报错的*/
var arr = [1,2,3,4,5];
var arr2 = [1,2,43,4,5];
Array.prototype.sum = function(){
var result = 0;
for(var i=0;i<this.length;i++){
result+=this[i];
}
return result;
}
alert(arr.sum());
alert(arr2.sum());
//类比:style的优先级要比class的优先级要高.[遵从就近属性]
var arr = [];
arr.number = 10;
Array.prototype.number = 20;
alert(arr.number);
//显示的就是true
// 原型上面的东西是公用的
function createPerson(name){
this.name = name;
}
createPerson.prototype.showName = function(){
alert(this.name);
}
var p1 = new createPerson('小强');
p1.showName();
var p2 = new createPerson('小红');
p2.showName();
alert(p1.showName == p2.showName);//false
传统的过程式编写选项卡
/*
* 先变型,变型的原则:
* 尽量不要出现函数嵌套函数
* 可以有全局变量
* 把onload中不是赋值的语句放到单独函数中
*
* */
init();//初始化方法
用面向对象封装通用选项卡
/*
* 先变型:
* 尽量不要出现函数嵌套函数
* 可以有全局变量
* 把onload中不是赋值的语句放到单独函数中
*
* 改成面向对象:
* 全局变量其实就是属性,
* 函数就是方法,
* onload中就是创建对象
* 改this指向问题,尽量让面向对象中的this指向对象
* */
window.onload = function(){
var ti = new Tab();
ti.init();
}
function Tab(){
this.getDiv = document.getElementById('div1');
this.getSonDiv= this.getDiv.getElementsByTagName('div');
this.getSonInput= this.getDiv.getElementsByTagName('input');
}
Tab.prototype.init = function(){
This = this;
for(var i=0;i<this.getSonInput.length;i++){
this.getSonInput[i].index = i;
this.getSonInput[i].onclick = function(){
This.change(this);
};
}
}
Tab.prototype.change = function(obj){
for(var i =0;i<this.getSonInput.length;i++){
this.getSonInput[i].className = '';
this.getSonDiv[i].style.display = 'none';
}
this.getSonDiv[obj.index].style.display = 'block';
obj.className = 'active';
}
控制多个选项卡自动播放
<script>
window.onload = function(){
var t1 = new Tab('div1');
t1.init();
var t2 = new Tab('div2');
t2.init();
t2.autoPlay();
}
function Tab(id){
this.getDiv = document.getElementById(id);
console.log(this);
this.getSonDiv= this.getDiv.getElementsByTagName('div');
this.getSonInput= this.getDiv.getElementsByTagName('input');
this.iNow = 0;
}
Tab.prototype.init = function(){
var This = this;
for(var i=0;i<this.getSonInput.length;i++){
this.getSonInput[i].index = i;
this.getSonInput[i].onclick = function(){
This.change(this);
};
}
}
Tab.prototype.change = function(obj){
for(var i =0;i<this.getSonInput.length;i++){
this.getSonInput[i].className = '';
this.getSonDiv[i].style.display = 'none';
}
this.getSonDiv[obj.index].style.display = 'block';
obj.className = 'active';
}
Tab.prototype.autoPlay = function(){
var This = this;
setInterval(function(){
This.iNow++;
This.iNow%=This.getSonInput.length;
for(var i =0;i<This.getSonInput.length;i++){
This.getSonInput[i].className = '';
This.getSonDiv[i].style.display = 'none';
}
This.getSonInput[This.iNow].className = 'active';
This.getSonDiv[This.iNow].style.display = 'block';
},1000);
}
</script>
在定时器中,this会指向window
用面向对象编写拖拽
/*
* 原则是使得this指向此对象
* */
window.onload = function(){
var t1 = new Tab('div1');
t1.init();
var t2 = new Tab('div2');
t2.init();
}
function Tab(id){
this.getDiv = document.getElementById(id);
this.disX = 0;
this.disY = 0;
}
Tab.prototype.init = function(){
/*
* 在监听器与定时器上面容易出现问题。现在this指向的是div
* */
var This = this;
this.getDiv.onmousedown = function(ev){
var ev = ev||event;
This.fnDown(ev);
return false;
};
}
Tab.prototype.fnDown=function(ev){
var This = this;
this.disX = ev.clientX - this.getDiv.offsetLeft;
this.disY = ev.clientY - this.getDiv.offsetTop;
document.onmousemove = function(){
var ev = ev||event;
This.fnMove(ev);
};
document.onmouseup = this.fnUp;
}
Tab.prototype.fnMove=function(ev){
this.getDiv.style.left = ev.clientX - this.disX +'px';
this.getDiv.style.top = ev.clientY - this.disY +'px';
}
Tab.prototype.fnUp = function(){
document.onmouseup = document.onmousemove = null;
}
/*
* 尽量不要出现嵌套函数
* 可以有全局变量
* 把onload中不是赋值的语句放到淡出的函数中去
* */
JS是基于原型的程序
var num = [1,2,3];
Array.prototype.push = function(){
for(var i=0;i<arguments.length;i++){
this[this.length]= arguments[i];
}
return this.length;
}
console.log(num.push(4,5,6));
console.log(num);
/*
*
* 系统对象也是基于原型的程序
*
* 千万不要修改系统方法
* */
什么是包装对象
/*
*
*
*
* 包装对象:基本类型都有自己对应的包装对象
* 除了null,undefined。
* */
var str = 'hello';
alert(typeof str);
str.charAt();//基本类型会找到对应的包装对象类型,然后包装对象把所有的属性和方法给了基本类型,然后包装对象消失。
//特别像送快递
/*
* 通过new创建的都是基本对象
* */
//String.prototype.charAt = function(){}
String.prototype.lastValue = function(){
return this.charAt(this.length-1);
}
alert(str.lastValue());//自己创建的方法
var str = 'hello';
str.num =10;
alert(str.num);
/*
* 基本类型想要添加一个属性,就会在基本而类型的包装对象上去创建一个对象,然后包装对象消失。
*
* 而原型下面的方法是共享的
* */
面向对象中的原型链
aaa.prototype.num = 10; //这个时候num是挂在在aaa的原型下面
为什么对象可以找到原型下面的东西?
是通过原型链_proto_找到的
/*
* 实例对象与原型之间的连接,叫做原型链
*
* 原型链的最外层是 Object.prototype
* */
function aaa(){
// this.num = 'missXiao';
}
// aaa.prototype.num = 10;
Object.prototype.num = '666';
var a1 = new aaa();
console.log(a1.num);
hasOwnProperty和constructor的使用
/*
*
* 面向对象的一些属性和方法
* - hasOwnProperty():看是不是对象自身下面的属性
* - constructor:查看对象的构造函数
* - 每个原型都会自动添加constructor属性
* - 避免修改construtor属性
*
* - instanceof 运算符
* - 对象与构造函数在原型链上是否有关系
*
* - toString();object上的方法
* */
var arr = [];
// arr.num = 10;
arr.num=10;
Array.prototype.num2 = function(){
alert(66);
};
//看看是不是对象自身下面的属性
console.log(arr.hasOwnProperty('num'));//true
console.log(arr.hasOwnProperty('num2'));//false
//constructor查看对象的构造函数。[和原型没有关系]
console.log(arr.constructor);
function newFn(){
this.color = 'color';
this.red = 'red';
}
var fn = new newFn();
console.log(fn.constructor);
//创建完函数之后,程序会自动的添加这句话
function newFn(){
this.color = 'color';
this.red = 'red';
}
newFn.prototype.constructor = Array;//如果修改的话就会改回Array[每一个函数都会有的,都是自动生成的]
newFn.prototype.constructor = newFn;
hasOwnProperty
是调用最外层Object
上面。
console.log(fn.hasOwnProperty == Object.prototype.hasOwnProperty);
//返回的是true
function aaa(){
}
// aaa.prototype.name = '小明';
// aaa.prototype.age = 18;
aaa.prototype = {
constructor:aaa,//一定要把原型给修正过来
'name':'小明',
'age':18
}//这样写不会覆盖constructor,因为是往原型上添加的
var t1 = new aaa();
console.log(t1.name);
使用for-in
,系统自带的属性有些是找不到的。
//这样做只能够弹出一个name[即使修改constructor,也是找不到的]
bbb.prototype.name =66;
for(var attr in bbb.prototype){
console.log(attr);
}
instanceof运算符的使用
//instanceof其实是一个运算符。对象与构造函数在原型链上是否有关系
function Aa(){
}
var a1 = new Aa();
console.log(a1 instanceof Aa);
console.log(a1 instanceof Object);
constructor和instanceof也能查看类型,但是最好的查看方法是tostring
利用toString做类型判断
var arr = [];
console.log(arr.toString);
function Aaa(){
}
var a1 = new Aaa();
/*
* 系统下面的toString是自带的,自己写的对象都是通过原型链进行查找的
*
* */
console.log(arr.toString == Object.prototype.toString);//结果是false。
console.log(a1.toString == Object.prototype.toString);//结果是true
//toString()把对象转成字符串
var arr =[1,2,3];
console.log(arr.toString());//转换成字符串
Array.prototype.toString = function(){//自定义转换成字符串
return this.join('+');
}
console.log( arr.toString());
/*
* 进行进制转换
* */
var num =255;
console.log(num.toString(16));
/*
* 做类型判断
* */
var arr = [];
/*建议使用这一个来判断*/
/*
* 跨域情况下,进行判断会错误
* */
console.log(Object.prototype.toString.call(arr)=='[object Array]');
什么是面向对象的继承
这里方法的继承有问题
/*
* 什么是继承[复用代码的一种形式]
* 在原有对象的基础上,略作修改,得到一个新的对象
* 不影响原有对象的功能
*
* 如何添加继承
* 属性 call
* 方法 for in
*
* */
/*
* 属性的继承:调用父类的构造函数 call
*
* 方法的继承:父类的原型赋给子类的原型
* */
function CreatePerson(name,sex){
this.name = name;
this.sex = sex;
}
CreatePerson.prototype.showName = function(){
console.log(this.name);
}
function CreateStar(name,sex,job){
CreatePerson.call(this,name,sex);
this.job = job;
}
CreateStar.prototype = CreatePerson.prototype;
var p1 = new CreatePerson('小明','男');
p1.showName();
var p2 = new CreatePerson('黄晓明','男','演员');
p2.showName();
面向对象之拷贝继承
/*
* 什么是继承[复用代码的一种形式]
* 在原有对象的基础上,略作修改,得到一个新的对象
* 不影响原有对象的功能
*
* 如何添加继承
* 属性 call
* 方法 for in[拷贝继承]
*
* */
/*
* 属性的继承:调用父类的构造函数 call
*
* 方法的继承:父类的原型赋给子类的原型
* */
function CreatePerson(name,sex){
this.name = name;
this.sex = sex;
}
CreatePerson.prototype.showName = function(){
console.log(this.name);
}
function CreateStar(name,sex,job){
CreatePerson.call(this,name,sex);
this.job = job;
}
extend(CreateStar.prototype,CreatePerson.prototype);
// CreateStar.prototype = CreatePerson.prototype;
var p1 = new CreatePerson('小明','男');
p1.showName();
var p2 = new CreateStar('黄晓明','男','演员');
p2.showName();
function extend(obj1,obj2){
for(var attr in obj2){
obj1[attr] = obj2[attr];
}
}
console.log(p1)
console.log(p2)
函数不能被修改,如果一赋值就会被改变链条
var a = [1,2,3];
var b =a;
b = [1,2,3,4];
编写继承的拖拽
window.onload = function(){
var t1 = new Tab('div1');
t1.init();
var t2 = new TabSon('div2');
t2.init();
}
function Tab(id){
this.div = document.getElementById(id);
this.disX = 0;
this.disY = 0;
}
Tab.prototype.init = function(){
var This = this;
this.div.onmousedown = function(ev){
var ev = ev||event;
This.disX = ev.clientX - this.offsetLeft;
This.disY = ev.clientY - this.offsetTop;
console.log(This.disX);
document.onmousemove = function(ev){
var ev = ev||event;
This.fnMove(ev);
}
document.onmouseup = This.fnUp;
}
}
Tab.prototype.fnMove = function(ev){
this.div.style.left = ev.clientX - this.disX +'px';
this.div.style.top = ev.clientY - this.disY +'px';
}
Tab.prototype.fnUp = function(){
document.onmouseup = document.onmousemove = null;
}
/*
*
* 继承
* */
function TabSon(id){
Tab.call(this,id);
}
extend(TabSon.prototype,Tab.prototype);
TabSon.prototype.fnMove = function(ev){
var L = ev.clientX - this.disX;
var T = ev.clientY - this.disY;
console.log(document.documentElement.clientHeight);
if(L<0){
L=0;
}else if(L>document.documentElement.clientWidth - this.div.offsetWidth){
L = document.documentElement.offsetWidth - this.div.offsetWidth;
}
if(T<0){
T=0;
}else if(T>document.documentElement.clientHeight - this.div.offsetHeight){
T = document.documentElement.clientHeight - this.div.offsetHeight;
}
this.div.style.left = L +'px';
this.div.style.top = T +'px';
}
/*
* 继承函数
* */
function extend(obj1,obj2){
for(var attr in obj2){
obj1[attr] = obj2[attr];
}
}
继承的其他形式之类式继承
/*
*
* 继承的其他形式
* - 类式继承
* - 利用构造函数[类]继承的方法
* - 原型继承
* - 借助原型来实现对象继承对象
*
*
*在JS里是没有类的概念的,可以把构造函数想象成类
* */
function Aaa(){
this.name = [1,2,3];
}
Aaa.prototype.showName = function(){
console.log(this.name);
}
function Bbb(){
Aaa.call(this);
}
/*至少需要四句话。
* 目的是只继承方法,而不继承属性
* */
var F = function(){};
F.prototype = Aaa.prototype;
Bbb.prototype = new F();
Bbb.prototype.constructor = Bbb;
var b1 = new Bbb();
b1.showName();
b1.name.push(1);
console.log(b1);
var b2 = new Bbb();
console.log(b2);
继承的其他形式之原型继承
借助原型来实现对象继承对象
//原型继承
var a = {
name:'小明'
}
var b= cloneObj(a);
alert(b.name);//小明
b.name = '666';
alert(b.name);//666
alert(a.name);//小明
function cloneObj(obj){
/*三句话组合到一起就是原型继承*/
var F = function(){};
F.prototype = obj;
return new F();
}
原型也是对象
/*
* 拷贝继承:通用型的 [有new或者无new都适用]
*
* 类式继承:适用于new构造函数形式
*
* 原型继承:适用于无new的对象
* */
组件开发是什么
<script>
/*
*
* 需求:黄的按下的时候title是有变化的,而红的是没有变化的
*
* */
/*
*
* 参数报错和参数顺序问题
*
* */
window.onload = function () {
var t1 = new Tab();
t1.init('div1');
var t2 = new Tab();
t2.init('div2',function (){
document.title = 'hello';
});
};
/*传参可以写到构造函数当中,也可以写到初始化当中*/
function Tab(){
this.div = null;
this.disX = 0;
this.disY = 0;
}
Tab.prototype.init = function(id,todown){
this.div = document.getElementById(id);
var This = this;
this.div.onmousedown = function(ev){
var ev = ev||event;
This.disX = ev.clientX - this.offsetLeft;
This.disY = ev.clientY - this.offsetTop;
todown&&todown();
document.onmousemove = function(ev){
var ev = ev||event;
This.fnMove(ev);
}
document.onmouseup = This.fnUp;
}
}
Tab.prototype.fnMove = function(ev){
this.div.style.left = ev.clientX - this.disX +'px';
this.div.style.top = ev.clientY - this.disY +'px';
}
Tab.prototype.fnUp = function(){
document.onmouseup = document.onmousemove = null;
}
/*
* 组件开发更像是一种兄弟的关系
* 用同一套代码满足不同的产品需要求
*
* 好处:
* - 提高产品的复用性
* - 如何配置参数和默认参数
*
* */
// 组件开发:多组对象,像兄弟之间的关系[代码复用的一种形式]
/*
* 继承函数
* */
function extend(obj1,obj2){
for(var attr in obj2){
obj1[attr] = obj2[attr];
}
}
</script>
给拖拽组件配置不同参数
<script>
/*
* 可以利用json的特性,使得一个参数代表多个值。json整体是一个参数
*
* */
var a = {//a在程序中叫做配置参数
// name:'小明'
}
var b = {//默认参数
name:'小强'
}
extend(b,a);
console.log(b.name);//现在b的name等于小明,说明被覆盖掉
function extend(obj1,obj2){
for(var attr in obj2){
obj1[attr] =obj2[attr];
}
}
</script>
<script>
/*
* 解决的是两个问题:
* - 参数顺序问题?
* - 使用json
* - 如果为空怎么办?
* - 配置参数
* */
window.onload = function () {
var t1 = new Tab();
t1.init({//配置参数
id:'div1'
});
var t2 = new Tab();
t2.init({//配置参数
id:'div2',
toDown:function(){
document.title = 'hello'
}
});
var t3 = new Tab();
t3.init({//配置参数
id:'div3',
toDown:function(){
document.title = 'miaov'
},
toUp:function(){
document.title = '课堂'
}
});
var t4 = new Tab();
t4.init({//配置参数
id:'div4',
toUp:function(){
document.title = '拜拜'
}
});
};
function Tab(){
this.div = null;
this.disX = 0;
this.disY = 0;
this.settingss = {//默认参数.[id是没有默认参数的,是必选项]
toDown:function(){},
toUp:function(){}
}
}
Tab.prototype.init = function(opt){
this.div = document.getElementById(opt.id);
var This = this;
extend(this.settingss,opt);//配置赋给默认
this.div.onmousedown = function(ev){
var ev = ev||event;
This.disX = ev.clientX - this.offsetLeft;
This.disY = ev.clientY - this.offsetTop;
This.settingss.toDown();
document.onmousemove = function(ev){
var ev = ev||event;
This.fnMove(ev);
}
document.onmouseup = function() {
This.settingss.toUp();
This.fnUp();
}
}
}
Tab.prototype.fnMove = function(ev){
this.div.style.left = ev.clientX - this.disX +'px';
this.div.style.top = ev.clientY - this.disY +'px';
}
Tab.prototype.fnUp = function(){
document.onmouseup = document.onmousemove = null;
}
/*
* 组件开发更像是一种兄弟的关系
* 用同一套代码满足不同的产品需要求
*
* 好处:
* - 提高产品的复用性
* - 如何配置参数和默认参数
*
* */
// 组件开发:多组对象,像兄弟之间的关系[代码复用的一种形式]
/*
* 继承函数
* */
function extend(obj1,obj2){
for(var attr in obj2){
obj1[attr] = obj2[attr];
}
}
</script>
封装弹框组件
<script>
//采用的是动态创建的形式
window.onload = function(){
var aInput = document.getElementsByTagName('input');
aInput[0].onclick = function(){
var d1 = new Dialog();
d1.init({//传入配置参数
title:'登陆'
});
}
aInput[1].onclick = function(){
var d1 = new Dialog();
d1.init({//传入配置参数
w:100,
h:400,
dir:'right',
title:'公告'
});
}
}
function Dialog(){
this.settings = {//所有参数都走默认
w:300,
h:300,
dir:'center',
title:'标题'
}
}
Dialog.prototype.init = function(opt){
this.oLogin = null;
extend(this.settings,opt);
this.create();
}
Dialog.prototype.create = function(){
this.oLogin = document.createElement('div');
this.oLogin.className = 'login';
this.oLogin.innerHTML = ' <div class="title"> <span>'+this.settings.title+'</span><span class="close">X</span> </div> <div class="content"></div> ';
document.body.appendChild(this.oLogin);
this.setData();
}
Dialog.prototype.setData = function(){
this.oLogin.style.width = this.settings.w+'px';
this.oLogin.style.height = this.settings.h+'px';
if(this.settings.dir == 'center'){
this.oLogin.style.left = (viewWidth() - this.oLogin.offsetWidth)/2+'px';
this.oLogin.style.top = (viewHeight() - this.oLogin.offsetHeight)/2+'px';
}else if(this.settings.dir == 'right'){
this.oLogin.style.left = (viewWidth() - this.oLogin.offsetWidth)+'px';
this.oLogin.style.top = (viewHeight() - this.oLogin.offsetHeight)+'px';
}
}
function extend(obj1,obj2){//obj1是空,obj2是被
for(var attr in obj2){
obj1[attr] = obj2[attr];
}
}
function viewWidth(){
return document.documentElement.clientWidth;
}
function viewHeight(){
return document.documentElement.clientHeight;
}
</script>
使用对象标记已弹出弹框
只让执行一次的过程是单体模式
<script>
//采用的是动态创建的形式
window.onload = function(){
var aInput = document.getElementsByTagName('input');
aInput[0].onclick = function(){
var d1 = new Dialog();
d1.init({//传入配置参数
iNow:0,
title:'登陆'
});
}
aInput[1].onclick = function(){
var d1 = new Dialog();
d1.init({//传入配置参数
iNow:1,
w:100,
h:400,
dir:'right',
title:'公告'
});
}
aInput[2].onclick = function(){
var d1 = new Dialog();
d1.init({//传入配置参数
iNow:2,
mark:true
});
}
}
function Dialog(){
this.settings = {//所有参数都走默认
w:300,
h:300,
dir:'center',
title:'默认',
mark:false//默认遮罩是没有的
}
}
Dialog.prototype.json = {//使用json来达到只能够走一次的效果
};
Dialog.prototype.init = function(opt){
this.oLogin = null;
extend(this.settings,opt);
//console.log(this.json[opt.iNow] == undefined);//这里有一个重要区别,一定要注意
/*
* 把opt换成this.settings?
* */
if(this.json[opt.iNow]==undefined) {
this.json[opt.iNow] = true;
}
if(this.json[opt.iNow]){
this.create();
this.fnClose();
// console.log(this.settings.mark);
this.settings.mark && this.createMark();
this.json[opt.iNow] = false;
}
}
Dialog.prototype.create = function(){
this.oLogin = document.createElement('div');
this.oLogin.className = 'login';
this.oLogin.innerHTML = ' <div class="title"> <span>'+this.settings.title+'</span><span class="close">X</span> </div> <div class="content"></div> ';
document.body.appendChild(this.oLogin);
this.setData();
}
Dialog.prototype.setData = function(){
this.oLogin.style.width = this.settings.w+'px';
this.oLogin.style.height = this.settings.h+'px';
if(this.settings.dir == 'center'){
this.oLogin.style.left = (viewWidth() - this.oLogin.offsetWidth)/2+'px';
this.oLogin.style.top = (viewHeight() - this.oLogin.offsetHeight)/2+'px';
}else if(this.settings.dir == 'right'){
this.oLogin.style.left = (viewWidth() - this.oLogin.offsetWidth)+'px';
this.oLogin.style.top = (viewHeight() - this.oLogin.offsetHeight)+'px';
}
}
Dialog.prototype.fnClose = function(){
var oClose = this.oLogin.getElementsByTagName('span')[1];
var This = this;
oClose.onclick = function(){
this.parentNode.parentNode.remove();
if(This.settings.mark){
document.body.removeChild(This.oMark);
}
console.log(This.json[This.settings.iNow]);
This.json[This.settings.iNow] = true;
}
}
Dialog.prototype.createMark = function(){
var oMark = document.createElement('div');
oMark.id = 'mark';
this.oMark = oMark;//通过动作可以生成属性
oMark.style.width = viewWidth()+'px';
oMark.style.height = viewHeight()+'px';
document.body.appendChild(oMark);
}
function extend(obj1,obj2){//obj1是空,obj2是被
for(var attr in obj2){
obj1[attr] = obj2[attr];
}
}
function viewWidth(){
return document.documentElement.clientWidth;
}
function viewHeight(){
return document.documentElement.clientHeight;
}
</script>
复杂组件开发之自定义事件
<script>
/*
* 什么是组件?
* - 对面向对象的深入应用(UI组件 功能组件)
* - 将配置参数,方法,事件,三者进行分离
*
* 创建自定义事件:[主要是和函数有关系,就是让函数能够具备事件的某些特性]
*
* - 有利于多人协作开发代码
* - 如何去挂载自定义事件与事件函数
* */
var btn1 = document.getElementById('btn1');
btn1.addEventListener('show',function(){
alert(1);
},false);
btn1.addEventListener('show',function(){
alert(2);
},false);
btn1.addEventListener('show',function(){
alert(3);
},false);
btn1.addEventListener('show',function(){
alert(4);
},false);
show();//主动触发自定义事件
</script>
原生JS实现自定义事件
简述一下,这里的自定义事件就相当于楼层->书架->书的关系。json就是一个楼层,他通过元素的自定义属性挂载在元素身上,数组就相当于书架,存在与json之中。而书就是一个个函数啦
<script>
/*
* 绑定事件的特点就是互相不会覆盖
* */
/*
*
* 自定义事件是函数,一个是函数名,一个是函数内容
* */
window.onload = function(){
var oDiv = document.getElementsByTagName('div')[0];
var oSpan = document.getElementsByTagName('span')[0];
bindEvent(oDiv,'click',function(){
alert(1);
})
bindEvent(oSpan,'show',function(){
alert(4);
});
bindEvent(oSpan,'hide',function(){
alert(5);
});
fireEvent(oDiv,'click');//希望弹出的结果是3,4
}
/*
* 封装绑定事件
* */
function bindEvent(obj,events,fn){
/*
* obj->楼层
*event->书架
* fn ->书
* */
obj.listeners = obj.listeners||{};//如果没有就会走后面。[相当于楼层]
obj.listeners[events] = obj.listeners[events]||[];//[相当于书架]
obj.listeners[events].push(fn);
if(obj.addEventListener){
obj.addEventListener(events,fn,false);
}else{
obj.attachEvent('on'+events,fn);
}
}
/*
* 进行主动触发自定义事件,一般主动触发的函数名叫做fireEvent
*
* */
function fireEvent(obj,events){
for(var i=0;i<obj.listeners[events].length;i++){
obj.listeners[events][i]();//主动触发
}
}
</script>
自定义事件实例
<script>
/*需求:
* - 采用组件开发的模式
* - 并且使用自定义事件,方便多人协同开发
*
*
* */
window.onload = function(){
var t1 = new Tab();
t1.init({
elem:'div1',
});
//寒暑假上括号,表示已经执行
bindEvent(t1,'Mdown',function(){
document.title = 'This is T1 mouseDown';
});
bindEvent(t1,'Mup',function(){
document.title = 'This is T1 mouseDown';
});
//这里是执行的
console.log(fireEvent(t1,'Mup'));
}
//对象
function Tab(){
this.obj = null;
this.disX = 0;
this.disY = 0;
this.settings ={
};
}
Tab.prototype.init = function(opt){
var This = this;
extend(this.settings,opt);//固定函数替换完毕
this.obj = document.getElementById(this.settings['elem']);
console.log(fireEvent(this,'Mup'));
this.obj.onmousedown = function(ev){
fireEvent(This,'Mdown');
// This.settings.elemDown();
This.disX = ev.clientX - this.offsetLeft;
This.disY = ev.clientY - this.offsetTop;
document.onmousemove = function(){//这里会发生一个指向性错误
This.FnMove();
};
document.onmouseup = function(){
This.FnUp();
fireEvent(This,'Mup');
// This.settings.elemUp();
};
}
}
/*
* 对象的移动动作
* */
Tab.prototype.FnMove = function(ev){
var ev = ev||event;
this.obj.style.left = ev.clientX - this.disX + 'px';
this.obj.style.top = ev.clientY - this.disY + 'px';
}
/*
* 对象的清空动作
* */
Tab.prototype.FnUp = function(){
document.onmouseup = document.onmousemove = null;
}
/*
* 多参数函数
* */
function extend(obj1,obj2){
for(var attr in obj2){
obj1[attr] = obj2[attr];
}
}
/*自定义事件函数,并且注册函数事件*/
function bindEvent(obj,events,fn){
obj.listeners = obj.listeners||{};
obj.listeners[events] = obj.listeners[events] ||[];
obj.listeners[events].push(fn);
if(obj.nodeType){
if(obj.addEventListener){
obj.addEventListener(events,fn,false);
}else{
obj.attachEvent('on'+events,fn);
}
}
}
/*处理注册事件函数*/
function fireEvent(obj,events){
console.log(obj.listeners);
if(obj.listeners&&obj.listeners[events]){
for(var i =0;i<obj.listeners[events].length;i++){
obj.listeners[events][i]();
}
}
}
</script>
基于JQ的选项卡组件开发
未学习,之后学习。/
图片放大镜效果
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>30_基于JQ的选项卡组件开发</title>
<style>
/* *{
margin: 0px;
padding: 0px;
}*/
#div1{
width: 180px;
height: 180px;
overflow: hidden;
position: relative;
}
#div1 span{
width: 100px;
height: 100px;
background-color: yellow;
opacity: 0.5;
position: absolute;
left: 0px;
top: 0px;
display: none;
}
</style>
</head>
<body>
<div id="div1">
<img src="images/b2.jpg" alt="">
<span></span><!--表示遮罩-->
</div>
<script>
window.onload = function(){
var oDiv = document.getElementById('div1');
var oSpan =oDiv.getElementsByTagName('span')[0];
oDiv.onmouseover = function(){
oSpan.style.display = 'block';
}
oDiv.onmouseout = function(){
oSpan.style.display = 'none';
}
oDiv.onmousemove = function(ev){
var ev = ev||event;
/*left与top是相对于父级来进行定位的*/
console.log(oDiv.offsetLeft);//是相当于屏幕左边
oSpan.style.left = ev.clientX - oDiv.offsetLeft - oSpan.clientWidth/2 +'px';
oSpan.style.top = ev.clientY - oDiv.offsetTop-oSpan.clientHeight/2+'px';
}
}
</script>
</body>
</html>
/*
* 移入是1,移出是2
* */
//如果移到黄色方块上是 1,2,1.
// 移入1.移出2.之后是移到黄色方块上,进行冒泡移入显示1
//与 onmouseout与onmouseover 事件不同,只有在鼠标指针离开被选元素时,才会触发 mouseleave 事件。他们俩通常是在一起用
//子集就相当于空气
/*
*
* 解决方案有两种
* - JS:使用onmouseenter与onmouseleave。这两个的特点就是子集不会影响到父级[他俩不支持冒泡。与over与out的作用是相同的 [但是他们两个有兼容性问题,在老版本上]
*
* - CSS:使用遮罩
* */
/*
*
* 使用:嵌套,并且子集有运动
* */
<div id="mark"></div><!--后添加的优先级要高。他们中间隔了一层透明的层,所以无法触发-->