众所周知,面向对象编程具有以下3大特性:
(1)封装性
(2)继承性
(3)多态性
这里仅就以“封装性”来说明如何在JS里应用面向对象编程思想对比较通用的操作进行封装,以提高代码的重用性。
tab例子
先看下面向过程的写法:
<!DOCTYPE html>
<html>
<head>
<style>
#tabBox input {
background: #F6F3F3;
border: 1px solid #FF0000;
}
#tabBox .active {
background: #E9D4D4;
}
#tabBox div {
width:300px;
height:250px;
display:none;
padding: 10px;
background: #E9D4D4;
border: 1px solid #FF0000;
}
</style>
<meta charset="utf-8" />
<title>选项卡</title>
<script>
window.onload=function(){
var tabBox = document.getElementById('tabBox');
var tabBtns = tabBox.getElementsByTagName('button');
var tabDivs = tabBox.getElementsByTagName('div');
for(var i=0;i<tabBtns.length;i++){
tabBtns[i].index = i;
tabBtns[i].onclick = function (){
for(var j=0;j<tabBtns.length;j++){
tabBtns[j].className='';
tabDivs[j].style.display='none';
}
this.className='active';
tabDivs[this.index].style.display='block';
};
}
};
</script>
</head>
<body>
<div class="tab" id="tabBox">
<button class="active">game</button>
<button>travel</button>
<button>music</button>
<div>LOL</div>
<div>Singapore</div>
<div>ColdPlay</div>
</div>
</body>
</html>
下面一步步改成面向对象的形式。
1.首先将嵌套的函数拿到window.onload外面,不能有函数嵌套,可以有全局变量。
//将在嵌套函数里的变量提取到全局中
var tabBtn = null;
var tabDiv = null;
window.onload = function(){
var tabBox = document.getElementById('tabBox');
tabBtns = tabBox.getElementsByTagName('button');
tabDivs = tabBox.getElementsByTagName('div');
for(var i=0;i<tabBtns.length;i++){
tabBtns[i].index = i;
//此处调用函数即可
tabBtns[i].onclick = clickBtn;
}
};
//将嵌套函数提取到全局中
function clickBtn(){
for(var j=0;j<tabBtns.length;j++){
tabBtns[j].className='';
tabDivs[j].style.display='none';
}
this.className='active';
tabDivs[this.index].style.display='block';
};
2.将全局的变量变为对象的属性,全局的函数变为对象的方法;将Tab的结构与事件绑定抽象成一个“类”Tab,将window.onload里的代码提取到一个构造函数里面,在window.onload里创建对象即可
构造函数里只包含Tab对象实例的属性,即Tab的构成dom元素,并在其中进行相应事件的绑定;在原型对象上添加公用的方法。注意几处this
的指向,要小心处理。
// 构造函数
function Tab(id) {
const tabBox= document.getElementById(id);
this.tabBtns=tabBox.getElementsByTagName('button');
this.tabDivs=tabBox.getElementsByTagName('div');
const _this=this;
for(let i=0,len=this.tabBtns.length;i<len;i++){
this.tabBtns[i].index=i;
// this.tabBtns[i].addEventListener('click',this.btnClickHandler.bind(this,i),false);
this.tabBtns[i].onclick=function () {
// here 'this' points to this.tabBtns[i]
_this.btnClickHandler(this);
}
}
}
Tab.prototype.btnClickHandler=function (btn) {
//console.log(this);
for(let j=0,l=this.tabBtns.length;j<l;j++){
this.tabBtns[j].setAttribute('class','');
this.tabDivs[j].style.display='none';
}
btn.setAttribute('class','active');
this.tabDivs[btn.index].style.display='block';
}
3.可将抽象出来的Tab放到单独的js文件中,再引入,这样在html中就可简洁地使用Tab构造函数来构建需要的结构。
<body>
<div class="tab" id="tabBox1">
<button class="active">game</button>
<button>travel</button>
<button>music</button>
<div>LOL</div>
<div>Singapore</div>
<div>ColdPlay</div>
</div>
<br>
<div class="tab" id="tabBox2">
<button class="active">技术</button>
<button>工具</button>
<button>网站</button>
<div>FE</div>
<div>Vue</div>
<div>https://www.w3school.com</div>
</div>
<script>
window.onload=function(){
let tab1=new Tab('tabBox1');
let tab2=new Tab('tabBox2');
}
</script>
</body>
结果图
两个Tab例子
下面再补个拖动页面 div 元素的面向对象写法例子。这里关于 'this' 的处理更要注意。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>拖拽</title>
<style>
.box{
width:100px;
height:100px;
background: #ff99cc;
position: absolute;
}
</style>
</head>
<body>
<div class="box" id="box1">i'm a box1.</div>
<div class="box" id="box2">i'm a box2.</div>
<script>
window.onload=function () {
let oBox1=new Drag('box1','#FF0000');
let oBox2=new Drag('box2','#00FF00');
}
// 构造函数
function Drag(id,color) {
this.box=document.getElementById(id);
this.box.style.backgroundColor=color;
this.disX=0;
this.disY=0;
const self=this;
this.box.onmousedown=function (e) {
//console.log(this); // the 'box' div
self.fnDown(e);
}
}
Drag.prototype.fnDown=function (e) {
let oEvent=e|| event;
this.disX=oEvent.clientX-this.box.offsetLeft;
this.disY=oEvent.clientY-this.box.offsetTop;
let self=this;// 通过new Box 创建的实例
document.onmousemove=function (e) {
//console.log(this); // the document
self.fnMove(e);
}
document.onmouseup=function (e) {
self.fnUp(e);
}
}
Drag.prototype.fnMove=function (e) {
let oEvent=e|| event;
this.box.style.left=oEvent.clientX-this.disX+'px';
this.box.style.top=oEvent.clientY-this.disY+'px';
}
Drag.prototype.fnUp=function (e) {
document.onmousemove=null;
document.onmouseup=null;
}
</script>
</body>
</html>
结果图
两个可拖拽 div
网友评论