js中簡易選項卡的實現(3種方法實現樣式的封裝)
阿新 • • 發佈:2019-02-14
清除浮動的三種方式 |
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);
}
<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>