1. 文件结构
2. 样式文件:index.css
.tab {
width: 500;
height: 500px;
margin: 50px auto;
border: 1px solid #000;
}
.tab .nav {
height: 50px;
border-bottom: 1px solid #000;
}
.tab .nav-item {
float: left;
width: 33.33%;
height: 100%;
text-align: center;
line-height: 50px;
}
.tab .nav-item.current {
background-color: #000;
color: #fff;
}
.tab .page {
position: relative;
height: 450px;
}
.tab .page-item {
display: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
text-align: center;
line-height: 450px;
font-size: 100px;
}
.tab .page-item.current {
display: block;
}
3. html文件:index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="css/index.css">
</head>
<body>
<div class="tab J_tab">
<div class="nav">
<div class="nav-item current">选项1</div>
<div class="nav-item">选项2</div>
<div class="nav-item">选项3</div>
</div>
<div class="page">
<div class="page-item current">页面1</div>
<div class="page-item">页面2</div>
<div class="page-item">页面3</div>
</div>
</div>
<script src="utils/tools.js"></script>
<script src="js/index.js"></script>
<script type="text/javascript">
var tab = new Tab().init();
</script>
</body>
</html>
4. 工具函数:tools.js
var initToolsModule = (function () {
// 获取目标事件元素
function getTarget(ev) {
// IE 浏览器是在window.event去找(主要考虑兼容性)
var e = ev || window.event
return e.target || e.srcElement
}
return {
getTarget: getTarget
}
})();
5. js文件:index.js
;(function (doc, tools) {
// doc -> 临时变量(与document互为映射)
var Tab = function () {
var oTab = doc.getElementsByClassName('J_tab')[0],
oPage = oTab.getElementsByClassName('page')[0]
this.oNav = oTab.getElementsByClassName('nav')[0]
this.oNavItems = this.oNav.getElementsByClassName('nav-item')
this.oPageItems = oPage.getElementsByClassName('page-item')
this.curIdx = 0
}
Tab.prototype.init = function () {
this.bindEvent()
}
Tab.prototype.bindEvent = function () {
// this 默认是指向被绑定事件处理函数的元素的
// 那么我们其实其实希望事件处理函数内部的this是指向实例化对像的
// bind 会返回一个新的函数,不能使用call/apply 因为会执行函数
this.oNav.addEventListener('click', this.onNavClick.bind(this), false)
}
Tab.prototype.onNavClick = function (ev) {
// var e = ev || window.event,
// tar = e.target || e.srcElement,
var tar = tools.getTarget(ev),
className = tar.className
if (className === 'nav-item') {
console.log(1);
// this.oNavItems[this.curIdx].className = 'nav-item'
// this.oPageItems[this.curIdx].className = 'page-item'
this.setCurrent(this.curIdx, 'remove')
this.curIdx = [].indexOf.call(this.oNavItems, tar)
// this.oNavItems[this.curIdx].className += ' current'
// this.oPageItems[this.curIdx].className += ' current'
this.setCurrent(this.curIdx, 'add')
}
}
Tab.prototype.setCurrent = function (index, field) {
switch (field) {
case 'add':
this.oNavItems[index].className += ' current'
this.oPageItems[index].className += ' current'
break
case 'remove':
this.oNavItems[index].className = 'nav-item'
this.oPageItems[index].className = 'page-item'
break
default:
break
}
}
window.Tab = Tab
})(document, initToolsModule);
// 其他笔记:
// 构造函数通过实例化生成对象
// fn -> new fn() -> { }
// function Test () {
// this.a = 1;
// this.b = 2;
// // new -> Test(this) -> window ->{a: 1, b: 2}
// }
// Test.prototype = {
// c: function () {
// // this 指向Test实例化对象
// // 还可以继承对象的原型链
// }
// }
// new Test()
// 构造函数内部 挂载到this -> 可配置 属性变量
// 构造函数原型属性挂载的是方法 -> 静态 不变的 不用配置
6. 最终实现效果