清除浮动的三种方式 |
1.overflow: hidden; 清除子元素的浮动对父元素的影响
2.clear: both; 清除哥哥元素的浮动对弟弟元素的影响
3.:after{ display: block; content: “”; clear: both; }
基本样式代码 |
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>选项卡</title>
<style type="text/css">
* {
margin: 0px;
padding: 0px;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 14px;
-webkit-user-select: none;
}
ul, li {
list-style: none;
}
.box {
width: 500px;
margin: 10px auto;
}
.box ul {
/*overflow: hidden; !*清除子元素的浮动对父元素的影响*!*/
position: relative;
top: 1px;
}
.box ul:after {
display: block;
content: "";
clear: both;
}
.box ul li {
float: left;
margin-right: 15px;
width: 100px;
height: 30px;
border: 1px solid #337ab7;
line-height: 30px;
text-align: center;
cursor: pointer;
}
.box ul li.select {
background: #5bc0de;
border-bottom-color: #5bc0de;
}
.box div {
display: none;
height: 150px;
text-align: center;
line-height: 150px;
background: #5bc0de;
border: 1px solid #9783b9;
/*clear: both; 清除哥哥元素的浮动对弟弟元素的影响*!*/
}
.box div.select {
display: block;
}
</style>
</head>
<div class="box" id="tabFir">
<ul>
<li class="select">页卡一</li>
<li>页卡二</li>
<li>页卡三</li>
</ul>
<div class="select">内容一</div>
<div>内容二</div>
<div>内容三</div>
</div>
<script type="text/javascript">
</script>
</body>
</html>
预览图:
js代码——点击事件 |
获取元素:
var tabFir = document.getElementById("tabFir"),
oLis = tabFir.getElementsByTagName("li"),
oDivs = tabFir.getElementsByTagName("div");
在操作点击事件时,容易把代码写成下面这种情况:
for (var i = 0; i < oLis.length; i++) {
oLis[i].onclick = function () {
changeTab(i);
}
}
但是这样是不对的,原因有三点:
1、js中所有的事件绑定都是异步编程的,开始只是给元素的点击胸围绑定了一个方法,但是需要手动点击才会执行这个方法,在此期间,不会干等着,继续下一次循环,当点击的时候循环早已经结束
2、在给元素绑定事件的时候,绑定的这个方法还只是定义的部分,此时方法中存储的都是字符串,我们看到的i只是一个字符
3、当点击的时候,执行对应的绑定方法,形成一个私有的作用域,在A中会使用到变量i,而i不是自己私有的,是上级作用域window下的i,此时windoew下的i已经变为oLis.length
解决此问题可以有两种方式:使用自定义属性的方式和闭包
自定义属性方式代码:
for (var i = 0; i < oLis.length; i++) {
oLis[i].index = i; //给对象增加一个属性名index
oLis[i].onclick = function () {
changeTab(this.index);
}
}
闭包方式代码:
//第一种:
for (var i = 0; i < oLis.length; i++) {
~function (i) {
oLis[i].onclick = function () {
changeTab(i);
}
}(i);
}
//第二种:
for (var i = 0; i < oLis.length; i++) {
oLis[i].onclick = (function (i) {
return function () {
changeTab(i);
}
})(i);
}
HTML+JavaScript代码如下,其中utils中方法见:http://blog.youkuaiyun.com/ruirui_1996/article/details/78116836
<div class="box" id="tabFir">
<ul id="tabOptions">
<li class="select">页卡一</li>
<li>页卡二</li>
<li>页卡三</li>
</ul>
<div class="select">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
</div>
<div>内容二</div>
<div>内容三</div>
</div>
<script type="text/javascript" src="utils.js"></script>
<script type="text/javascript">
var tabFir = document.getElementById("tabFir"),
tabFirst = utils.firstChild(tabFir), //ul
oLis = utils.children(tabFirst); //三个li
for (var i = 0; i < oLis.length; i++) {
oLis[i].onclick = function () {
//首先把兄弟元素的选中样式都移除掉
var curSiblings = utils.siblings(this); //this是当前事件,即当前绑定的li,siblings获取所有的兄弟元素节点
for (var i = 0; i < curSiblings.length; i++) {
utils.removeClass(curSiblings[i], "select"); //removeClass删除样式类名
}
//再让当前点击这个元素有选中的样式
utils.addClass(this, "select"); //addClass:给元素增加样式类名
//再让当前点击这个li父亲元素的所有的弟弟元素中(三个div)中和当前点击的这个li索引相同的有选中的样式,其余的移除选中样式
var index = utils.index(this); //index:获取当前元素的索引
var divList = utils.nextAll(this.parentNode); //nextAll:获取所有的弟弟元素节点
for (var i = 0; i < divList.length; i++) {
i === index ? utils.addClass(divList[i], "select") : utils.removeClass(divList[i], "select");
}
}
}
</script>
预览图:
但是该段代码只适合一个选项卡的情况,如果选项卡较多的话,最好写成一个插件来封装
样式封装——一个一个绑定 |
单独建立一个“封装.js” 文件:
//实现一个选项卡的封装,只要多个选项卡的主体结构一样,那么每一个实现的思想都是一模一样的,唯一不一样的就是最外层的盒子不一样
~function () {
/*
* tabChange封装一个选项卡插件,只要大结构保持统一,即可实现选项卡功能
* 参数:container:当前要实现选项卡的这个容器
* defaultIndex:默认选中项的索引
*/
function tabChange(container, defaultIndex) {
var tabFirst = utils.firstChild(container), //ul
oLis = utils.children(tabFirst), //三个li
divList = utils.children(container, "div"); //得到div的元素标签
//让defaultIndex对应的页卡选中的样式
defaultIndex = defaultIndex || 0;
utils.addClass(oLis[defaultIndex], "select");
utils.addClass(divList[defaultIndex], "select");
//实现具体的切换功能
for (var i = 0; i < oLis.length; i++) {
oLis[i].onclick = function () {
var curSiblings = utils.siblings(this);
for (var i = 0; i < curSiblings.length; i++) {
utils.removeClass(curSiblings[i], "select");
}
utils.addClass(this, "select");
var index = utils.index(this);
for (var i = 0; i < divList.length; i++) {
i === index ? utils.addClass(divList[i], "select") : utils.removeClass(divList[i], "select");
}
}
}
}
//在闭包里面,如果想让外部使用,可以暴露一个接口selectTab
window.selectTab = tabChange;
}();
html文件中的js代码为:
<script type="text/javascript" src="utils.js"></script>
<script type="text/javascript" src="封装.js"></script>
<script type="text/javascript">
var boxList = utils.getElementsByClass("box"); //getElementsByClass:通过元素的样式类名获取一组元素集合(兼容所有浏览器)
for (var i = 0; i < boxList.length; i++) {
selectTab(boxList[i]);
}
</script>
可实现选项卡效果。
样式封装——事件委托 |
“封装.js” 代码:
//实现一个选项卡的封装,只要多个选项卡的主体结构一样,那么每一个实现的思想都是一模一样的,唯一不一样的就是最外层的盒子不一样
~function () {
/*
* tabChange封装一个选项卡插件,只要大结构保持统一,即可实现选项卡功能
* 参数:container:当前要实现选项卡的这个容器
* defaultIndex:默认选中项的索引
*/
function tabChange(container, defaultIndex) {
var tabFirst = utils.firstChild(container), //ul
oLis = utils.children(tabFirst), //三个li
divList = utils.children(container, "div"); //得到div的元素标签
//使用时间委托来优化点击操作
tabFirst.onclick = function (e) {
e = e || window.event;
e.target = e.target || e.srcElement;
if (e.target.tagName.toLowerCase() === "li") { //说明当前点击的是li标签
detailFn.call(e.target, oLis, divList);
}
};
//让defaultIndex对应的页卡选中的样式
defaultIndex = defaultIndex || 0;
utils.addClass(oLis[defaultIndex], "select");
utils.addClass(divList[defaultIndex], "select");
}
function detailFn(oLis, divList) {
//保证this是当前点击的li
var index = utils.index(this);
utils.addClass(this, "select");
for (var i = 0; i < divList.length; i++) {
i === index ? utils.addClass(divList[i], "select") : (utils.removeClass(divList[i], "select"), utils.removeClass(oLis[i], "select"));
}
}
//在闭包里面,如果想让外部使用,可以暴露一个接口selectTab
window.selectTab = tabChange;
}();
HTML中js代码:
<script type="text/javascript">
var boxList = utils.getElementsByClass("box"); //getElementsByClass:通过元素的样式类名获取一组元素集合(兼容所有浏览器)
for (var i = 0; i < boxList.length; i++) {
selectTab(boxList[i]);
}
</script>
样式封装——构造函数面向对象 |
“封装.js” 代码:
//实现一个选项卡的封装,只要多个选项卡的主体结构一样,那么每一个实现的思想都是一模一样的,唯一不一样的就是最外层的盒子不一样
~function () {
function TabChange(container, defaultIndex) {
return this.init(container, defaultIndex);
}
TabChange.prototype = {
constructor: TabChange,
//按照索引来设置默认选中的页卡
defaultIndexEven: function () {
utils.addClass(this.oLis[this.defaultIndex], "select");
utils.addClass(this.divList[this.defaultIndex], "select");
},
//事件委托实现绑定切换
liveClick: function () {
var _this = this;
this.tabFirst.onclick = function (e) {
e = e || window.event;
e.target = e.target || e.srcElement;
if (e.target.tagName.toLowerCase() === "li") {
_this.detailFn(e.target);
}
};
},
detailFn: function (curEle) {
var index = utils.index(curEle);
utils.addClass(curEle, "select");
for (var i = 0; i < this.divList.length; i++) {
i === index ? utils.addClass(this.divList[i], "select") : (utils.removeClass(this.divList[i], "select"), utils.removeClass(this.oLis[i], "select"));
}
},
//初始化效果,也是当前插件的唯一入口
init: function (container, defaultIndex) {
this.container = container || null;
this.defaultIndex = defaultIndex || 0;
this.tabFirst = utils.firstChild(this.container);
this.oLis = utils.children(this.tabFirst);
this.divList = utils.children(this.container, "div");
this.defaultIndexEven();
this.liveClick();
return this;
}
};
window.selectTab = TabChange;
}();
HTML中js代码:
<script type="text/javascript">
var boxList = utils.getElementsByClass("box"); //getElementsByClass:通过元素的样式类名获取一组元素集合(兼容所有浏览器)
var box1 = new selectTab(boxList[0],0);
var box1 = new selectTab(boxList[1],1);
var box1 = new selectTab(boxList[2],2);
</script>