一、面向对象基础介绍
二、写一个面向对象的选项卡
第一步:我先按我们传统的过程式方法写一个选项卡
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用面向对象写选项卡</title>
<style>
#div1 div{width:200px;height:200px;border:1px #000 solid;display:none;}
.active{background:red;}
</style>
<script type="text/javascript">
window.onload = function(){
var oParent = document.getElementById('div1');
var aInput = oParent.getElementsByTagName('input');
var aDiv = oParent.getElementsByTagName('div');
for (var i = 0; i < aInput.length; i++) {
aInput[i].index = i;
aInput[i].onclick = function(){
for (var i = 0; i < aInput.length; i++) {
aInput[i].className = '';
aDiv[i].style.display = 'none';
}
this.className = 'active';
aDiv[this.index].style.display = 'block';
};
}
}
</script>
</head>
<body>
<div id="div1">
<input class="active" type="button" value="1">
<input type="button" value="2">
<input type="button" value="3">
<div style="display:block;">11111</div>
<div>22222</div>
<div>33333</div>
</div>
</body>
</html>
第二步:我在看一下上面提到的,刚开始学习面向对象的原则,普通方法变形
// ①将onload中的变量写成全局变量
var oParent = null;
var aInput = null;
var aDiv = null;
window.onload = function(){
oParent = document.getElementById('div1');
aInput = oParent.getElementsByTagName('input');
aDiv = oParent.getElementsByTagName('div');
// 这里的init函数是初始化函数
init();
};
// ③ 将onload中不是赋值的语句提取出来,在外面封装成单个的函数,并且在onload中调用
function init(){
for (var i = 0; i < aInput.length; i++) {
aInput[i].index = i;
// ②将嵌套的函数提取出去,封装成单个函数,在原地调用
aInput[i].onclick = change;
}
}
function change(){
for (var i = 0; i < aInput.length; i++) {
aInput[i].className = '';
aDiv[i].style.display = 'none';
}
this.className = 'active';
aDiv[this.index].style.display = 'block';
};
第三步:真正的改成面向对象的程序
// ① 创建一个window.onload创建一个选项卡对象
window.onload = function(){
// ②起个构造函数的名字叫Tab,注意首字母要大写
var t1 = new Tab();
t1.init();
};
// 不管是属性还是方法前面都要加上this
// ③写一个构造函数
function Tab(){
// ④ 全局变量就是属性
// 我们在第二步查看一下那些是全局变量,把它们写到这里变形属性
// 注意:面向对象当中属性前面就是不能加var的
this.oParent = document.getElementById('div1');
this.aInput = this.oParent.getElementsByTagName('input');
this.aDiv = this.oParent.getElementsByTagName('div');
}
// ⑤ 函数就是方法,所以将函数写到构造函数原型的下面
Tab.prototype.init = function() {
// ⑥在外面建立一个变量,更改this指向
var This = this;
for (var i = 0; i < this.aInput.length; i++) {
this.aInput[i].index = i;
this.aInput[i].onclick = function(){
//原本这里的this指向的是this.aInput[i]这个按钮,因此我们要使用⑥的方式,更改this的指向
This.change(this);
}
}
}
// ⑤ 函数就是方法,所以将函数写到构造函数原型的下面
Tab.prototype.change = function(obj) {
for (var i = 0; i < this.aInput.length; i++) {
this.aInput[i].className = '';
this.aDiv[i].style.display = 'none';
}
// ⑦ 这里的this也是上面的按钮,因为我们要纠正过来,我可以让上面change函数通过传参将this传递过来
obj.className = 'active';
this.aDiv[obj.index].style.display = 'block';
}
// 更改this的原则:尽量让this指向对象
第四步:拓展——面向对象的复用
比如说我们现在有多组选项卡
<div id="div1">
<input class="active" type="button" value="1">
<input type="button" value="2">
<input type="button" value="3">
<div style="display:block;">11111</div>
<div>22222</div>
<div>33333</div>
</div>
<div id="div2">
<input class="active" type="button" value="1">
<input type="button" value="2">
<input type="button" value="3">
<div style="display:block;">11111</div>
<div>22222</div>
<div>33333</div>
</div>
// 既然要多次复用,这里我们将id形成参数,让后期可以传进来多次调用
function Tab(id){
this.oParent = document.getElementById(id);
this.aInput = this.oParent.getElementsByTagName('input');
this.aDiv = this.oParent.getElementsByTagName('div');
this.iNow = 0;
}
//这时候我们我们只要在onload里面在调用一次就可以了,我们发现两个选项卡就立即生效了,这就是面向对象复用性强大的地方
window.onload = function(){
var t1 = new Tab('div1');
t1.init();
var t2 = new Tab('div2');
t2.init();
};
第五步:面向对象比封装函数更好的一点是它可以很灵活,比如我现在提一个需要,仅让第二的函数自动播放
window.onload = function(){
var t1 = new Tab('div1');
t1.init();
var t2 = new Tab('div2');
t2.init();
// 那么我们就给第二个选项卡加一个自动播放
// 这个方法没有,那么我们就给这个方法去添加这个方法
t2.autoplay();
};
// 添加自动播放的方法
Tab.prototype.autoplay = function(){
// 同上面一样,要注意this的指向问题
var This = this;
setInterval(function(){
if (This.iNow == This.aInput.length-1) {
This.iNow = 0;
}else{
This.iNow++;
}
for (var i = 0; i < This.aInput.length; i++) {
This.aInput[i].className = '';
This.aDiv[i].style.display = 'none';
}
This.aInput[This.iNow].className = 'active';
This.aDiv[This.iNow].style.display = 'block';
},2000);
};
下面贴身本次demo的全部代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用面向对象写选项卡</title>
<style>
#div1 div,#div2 div{width:200px;height:200px;border:1px #000 solid;display:none;}
.active{background:red;}
</style>
<script type="text/javascript">
/*
window.onload = function(){
var oParent = document.getElementById('div1');
var aInput = oParent.getElementsByTagName('input');
var aDiv = oParent.getElementsByTagName('div');
for (var i = 0; i < aInput.length; i++) {
aInput[i].index = i;
aInput[i].onclick = function(){
for (var i = 0; i < aInput.length; i++) {
aInput[i].className = '';
aDiv[i].style.display = 'none';
}
this.className = 'active';
aDiv[this.index].style.display = 'block';
};
}
}
*/
// 变形
/*
var oParent = null;
var aInput = null;
var aDiv = null;
window.onload = function(){
oParent = document.getElementById('div1');
aInput = oParent.getElementsByTagName('input');
aDiv = oParent.getElementsByTagName('div');
init();
};
function init(){
for (var i = 0; i < aInput.length; i++) {
aInput[i].index = i;
aInput[i].onclick = change;
}
}
function change(){
for (var i = 0; i < aInput.length; i++) {
aInput[i].className = '';
aDiv[i].style.display = 'none';
}
this.className = 'active';
aDiv[this.index].style.display = 'block';
};
*/
// 先变型
// 尽量不要出现函数嵌套函数
// 可以有全局变量
// 把onload中不是赋值的语句放到单独函数中
window.onload = function(){
var t1 = new Tab('div1');
t1.init();
var t2 = new Tab('div2');
t2.init();
t2.autoplay();
};
function Tab(id){
this.oParent = document.getElementById(id);
this.aInput = this.oParent.getElementsByTagName('input');
this.aDiv = this.oParent.getElementsByTagName('div');
this.iNow = 0;
}
Tab.prototype.init = function() {
var This = this;
for (var i = 0; i < this.aInput.length; i++) {
this.aInput[i].index = i;
this.aInput[i].onclick = function(){
This.change(this);
}
}
}
Tab.prototype.change = function(obj) {
for (var i = 0; i < this.aInput.length; i++) {
this.aInput[i].className = '';
this.aDiv[i].style.display = 'none';
}
obj.className = 'active';
this.aDiv[obj.index].style.display = 'block';
}
// 改成面向对象
// 全局变量就是属性
// 函数就是方法
// Onload中创建对象
// 改this指向,(在事件或者定时器中容易改变) 让面向对象中的this指向对象
Tab.prototype.autoplay = function(){
var This = this;
setInterval(function(){
if (This.iNow == This.aInput.length-1) {
This.iNow = 0;
}else{
This.iNow++;
}
for (var i = 0; i < This.aInput.length; i++) {
This.aInput[i].className = '';
This.aDiv[i].style.display = 'none';
}
This.aInput[This.iNow].className = 'active';
This.aDiv[This.iNow].style.display = 'block';
},2000);
};
</script>
</head>
<body>
<!--
面向对象的选项卡
原则
- 先写出普通的写法,然后写成面向对象的写法
>> 普通方法的变型
尽量不要出现函数嵌套函数
可以有全局变量
把onload中不是赋值的语句放到单独函数中
>> 改成面向对象
全局变量就是属性
函数就是方法
Onload中创建对象
改this指向问题
-->
<div id="div1">
<input class="active" type="button" value="1">
<input type="button" value="2">
<input type="button" value="3">
<div style="display:block;">11111</div>
<div>22222</div>
<div>33333</div>
</div>
<div id="div2">
<input class="active" type="button" value="1">
<input type="button" value="2">
<input type="button" value="3">
<div style="display:block;">11111</div>
<div>22222</div>
<div>33333</div>
</div>
</body>
</html>