JS物件導向應用,常見元件的封裝(輪播,tab,曝光載入)
tab切換
用物件導向的寫法如下,建立的物件例項個個獨立,不需要考慮相互影響,只需要考慮自己怎麼實現即可,下面程式碼還可以進行優化
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>元件tab</title>
<style>
ul,
li {
margin: 0;
padding: 0;
}
li {
list-style: none;
}
.clearfix:after {
content: '';
display: block;
clear: both;
}
.tab {
width: 600px;
margin: 20px auto;
border: 1px solid #ccc;
padding: 20px 10px;
border-radius: 4px;
}
.tab-header {
border-bottom: 1px solid #ccc;
}
.tab-header>li {
float: left;
color: brown;
border-top: 1px solid #fff;
border-left: 1px solid #fff;
border-right: 1px solid #fff;
padding: 10px 20px;
cursor: pointer;
}
.tab-header .active {
border: 1px solid #ccc;
border-bottom-color: #fff;
border-radius: 4px 4px 0 0;
color: #333;
margin-bottom: -1px;
}
.tab-container {
padding: 20px 10px;
}
.tab-container>li {
display: none;
}
.tab-container>.active {
display: block;
}
.box {
height: 1000px;
}
</style>
</head>
<body>
<div class="tab">
<ul class="tab-header clearfix">
<li class="active">選項1</li>
<li>選項2</li>
<li>選項3</li>
</ul>
<ul class="tab-container">
<li class="active">內容1
<ul>
<li></li>
</ul>
</li>
<li>內容2</li>
<li>內容3</li>
</ul>
</div>
<div class="tab">
<ul class="tab-header clearfix">
<li class="active">選項1</li>
<li>選項2</li>
<li>選項3</li>
<li>選項4</li>
</ul>
<ul class="tab-container">
<li class="active">內容1
<ul>
<li></li>
</ul>
</li>
<li>內容2</li>
<li>內容3</li>
<li>內容4</li>
</ul>
</div>
<div class="tab">
<ul class="tab-header clearfix">
<li class="active">內容1</li>
<li>內容2</li>
<li>內容3</li>
<li>內容4</li>
</ul>
<ul class="tab-container">
<li class="active">內容1
<ul>
<li></li>
</ul>
</li>
<li>內容2</li>
<li>內容3</li>
<li>內容4</li>
</ul>
</div>
<script src="../jquery-3.2.1.min.js"></script>
<script>
function Tab (ct) {
//思考Tab建構函式裡的屬性和方法,屬性有選項和內容的li
//這部分為初始化的東西
this.option = ct.querySelectorAll('.tab-header>li');
this.content = ct.querySelectorAll('.tab-container>li');
var self = this;
//上面部分為初始化的東西
this.option.forEach(function (option) { //遍歷選項中的每一項
option.addEventListener('click',function (e) { //給每個選項都繫結事件
var target = e.target;
// var index = this.option.indexOf(target);//不能這麼寫。這裡面的this代表當前點選的元素,所以要在外面儲存this
// var index = self.option.indexOf(target); //但是寫成這樣,由於self.option不是一個陣列,沒有indexOf方法,所以還需要使用call/apply
var index = [].indexOf.call(self.option,target); // 所以有2點需要注意,一是this的值,2是call
self.option.forEach(function (option) {
option.classList.remove('active');//把每一項的active類都去掉
})
target.classList.add('active'); //只給當前點選的option加上active類
self.content.forEach(function (content) { //下面的content同理
content.classList.remove('active');
})
self.content[index].classList.add('active');
},false)
})
}
// Tab.prototype.
new Tab(document.querySelectorAll('.tab')[0]);
new Tab(document.querySelectorAll('.tab')[1]);
new Tab(document.querySelectorAll('.tab')[2]);
</script>
</body>
</html>
把初始化的東西封裝到一起,繫結事件的程式碼封裝到一起,都作為方法繫結到原型上,優化之後的程式碼如下:
<script>
function Tab (ct) {
//思考Tab建構函式裡的屬性和方法,屬性有選項和內容的li
this.ct = ct;
this,init();
this.bind();
}
Tab.prototype.init = function () {
//這部分為初始化的東西
this.option = this.ct.querySelectorAll('.tab-header>li');
this.content = this.ct.querySelectorAll('.tab-container>li');
//上面部分為初始化的東西
}
Tab.prototype.bind = function () {
var self = this;
this.option.forEach(function (option) { //遍歷選項中的每一項
option.addEventListener('click',function (e) { //給每個選項都繫結事件
var target = e.target;
// var index = this.option.indexOf(target);//不能這麼寫。這裡面的this代表當前點選的元素,所以要在外面儲存this
// var index = self.option.indexOf(target); //但是寫成這樣,由於self.option不是一個陣列,沒有indexOf方法,所以還需要使用call/apply
var index = [].indexOf.call(self.option,target); // 所以有2點需要注意,一是this的值,2是call
self.option.forEach(function (option) {
option.classList.remove('active');//把每一項的active類都去掉
})
target.classList.add('active'); //只給當前點選的option加上active類
self.content.forEach(function (content) { //下面的content同理
content.classList.remove('active');
})
self.content[index].classList.add('active');
},false)
})
}
new Tab(document.querySelectorAll('.tab')[0]);
new Tab(document.querySelectorAll('.tab')[1]);
new Tab(document.querySelectorAll('.tab')[2]);
</script>
輪播
原始碼地址
進行物件導向的元件化寫法:
整體思路就是把所有的屬性方法都用this關聯起來,這樣就可以只考慮自己了,但是要注意繫結事件還有匿名函式內部的this要注意儲存
<script>
function Carousel ($ct) {
this.$ct = $ct;
this.init();
this.bind();
}
Carousel.prototype.init = function () {
var $imgct = this.$imgct= this.$ct.find('.img-ct');
var $imgs = this.$imgs = this.$ct.find('.img-ct>li');
//獲取寬度和個數
var imgWidth = this.$imgWidth = this.$imgs.width();
var imgCount = this.$imgCount = this.$imgs.length;
var $pre = this.$pre = this.$ct.find('.pre'); //不這麼寫的話,下面bind中是找不到$pre的,元件化的核心思想就是都去使用this去進行操作
var $next = this.$next =this.$ct.find('.next');
var $bullets = this.$bullets =this.$ct.find('.bullet>li');
var pageIndex = this.pageIndex = 0; //記錄當前頁碼
var animating = this.animating = false; //針對連續重複點選,設定變數來監聽是否處於動畫過程中
this.$imgct.append(this.$imgs.first().clone());
this.$imgct.prepend(this.$imgs.last().clone());
this.$imgct.width((this.$imgCount+2) * this.$imgWidth);
this.$imgct.css({
left: -this.$imgWidth,
})
}
Carousel.prototype.bind = function () {
var self = this;
this.$pre.on('click',function () {
self.playPre(1);//這裡面的this不對,是當前點選的元素this.$pre,所以還是需要儲存this
})
this.$next.on('click',function () {
self.playNext(1);
})
this.$bullets.on('click',function () {
var index = $(this).index();
if (index < self.pageIndex) {
self.playPre(self.pageIndex - index);
}
else {
self.playNext(index - self.pageIndex);
}
})
}
Carousel.prototype.playPre = function (num) {
var self = this;
if (this.animating) {
return; //如果還在動畫中,直接return掉
}
this.animating = true; //進入動畫,animating設為true表示正在動畫中
this.$imgct.animate({
left: '+=' + num * this.$imgWidth,
},function () { // 儲存this,因為在匿名函式內部
self.pageIndex -= num;
if (self.pageIndex === -1) {
self.pageIndex = self.$imgCount-1;
self.$imgct.css({
left: -self.$imgCount*self.$imgWidth,
})
}
self.setBullets();
self.animating = false; //動畫結束後重新設定為false
})
}
Carousel.prototype.playNext = function (num) {
var self = this;
if (this.animating) {
return;
}
this.animating = true;
this.$imgct.animate({
left: '-=' + num * this.$imgWidth,
},function () {
self.pageIndex += num;
if (self.pageIndex === self.$imgCount) {
self.pageIndex = 0;
self.$imgct.css({
left: -self.$imgWidth,
})
}
self.setBullets();
self.animating = false;
})
}
Carousel.prototype.setBullets = function () {
this.$bullets.removeClass('active')
.eq(this.pageIndex).addClass('active');
}
var c1 = new Carousel($('.carousel').eq(0));
var c2 = new Carousel($('.carousel').eq(1));
</script>
輪播二次封裝
對於上面封裝的元件,如果想達到使用Carousel2.init($('.carousel'));
就使得所有的carousel都運轉起來的話,就要使用另外一種模組化的方式
首先來看一個區別:
Carousel2 = { //方法1 寫成一個物件
init: function () {//寫成這樣的話 Carousel就是一個物件,只能新增一些屬性方法
console.log(123);
}
}
Carousel2 = (function () { //方法2 寫成一個立即執行函式
var a = 1; //寫成這樣的好處在於可以賦值一些區域性變數,並且這個值外部永遠訪問不到,並且也能在return中新增新的屬性方法
return {
init: function () {
console.log(a);
}
}
})();
上例中,方法2才是真正的封裝。所以我們可以把上面的Calousel建構函式直接放到裡面Carousel2的立即執行函式的區域性作用域裡,然後再return中,遍歷選取到的所有$('.carousel'),給每一個選取到的$('.carousel')new一個Carousel()的例項。
整體思路如下:
Carousel2 = (function () { //方法2 寫成一個立即執行函式
// 將寫好的Carousel建構函式直接放到這個區域性作用域裡 就不會暴露出去
return {
init: function ($ct) {
// 然後只在這裡遍歷選取到的所有目標元素,每一個元素都相應的建立例項
$ct.each(function (index,node) {
new Carousel($(node));
})
}
}
})();
Carousel2.init($('.carousel'));
最後可以將Carousel建構函式放到區域性作用域中,這樣就不會將寫好的建構函式暴露出去了。
<script>
Carousel2 = (function () { //方法2 寫成一個立即執行函式
// 將寫好的Carousel建構函式直接放到這個區域性作用域裡 就不會暴露出去
function Carousel ($ct) {
this.$ct = $ct;
this.init();
this.bind();
}
Carousel.prototype.init = function () {
var $imgct = this.$imgct= this.$ct.find('.img-ct');
var $imgs = this.$imgs = this.$ct.find('.img-ct>li');
//獲取寬度和個數
var imgWidth = this.$imgWidth = this.$imgs.width();
var imgCount = this.$imgCount = this.$imgs.length;
var $pre = this.$pre = this.$ct.find('.pre'); //不這麼寫的話,下面bind中是找不到$pre的,元件化的核心思想就是都去使用this去進行操作
var $next = this.$next =this.$ct.find('.next');
var $bullets = this.$bullets =this.$ct.find('.bullet>li');
var pageIndex = this.pageIndex = 0; //記錄當前頁碼
var animating = this.animating = false; //針對連續重複點選,設定變數來監聽是否處於動畫過程中
this.$imgct.append(this.$imgs.first().clone());
this.$imgct.prepend(this.$imgs.last().clone());
this.$imgct.width((this.$imgCount+2) * this.$imgWidth);
this.$imgct.css({
left: -this.$imgWidth,
})
}
Carousel.prototype.bind = function () {
var self = this;
this.$pre.on('click',function () {
self.playPre(1);//這裡面的this不對,是當前點選的元素this.$pre,所以還是需要儲存this
})
this.$next.on('click',function () {
self.playNext(1);
})
this.$bullets.on('click',function () {
var index = $(this).index();
if (index < self.pageIndex) {
self.playPre(self.pageIndex - index);
}
else {
self.playNext(index - self.pageIndex);
}
})
}
Carousel.prototype.playPre = function (num) {
var self = this;
if (this.animating) {
return; //如果還在動畫中,直接return掉
}
this.animating = true; //進入動畫,animating設為true表示正在動畫中
this.$imgct.animate({
left: '+=' + num * this.$imgWidth,
},function () { // 儲存this,因為在匿名函式內部
self.pageIndex -= num;
if (self.pageIndex === -1) {
self.pageIndex = self.$imgCount-1;
self.$imgct.css({
left: -self.$imgCount*self.$imgWidth,
})
}
self.setBullets();
self.animating = false; //動畫結束後重新設定為false
})
}
Carousel.prototype.playNext = function (num) {
var self = this;
if (this.animating) {
return;
}
this.animating = true;
this.$imgct.animate({
left: '-=' + num * this.$imgWidth,
},function () {
self.pageIndex += num;
if (self.pageIndex === self.$imgCount) {
self.pageIndex = 0;
self.$imgct.css({
left: -self.$imgWidth,
})
}
self.setBullets();
self.animating = false;
})
}
Carousel.prototype.setBullets = function () {
this.$bullets.removeClass('active')
.eq(this.pageIndex).addClass('active');
}
return {
init: function ($ct) {
// 然後只在這裡遍歷選取到的所有目標元素,每一個元素都相應的建立例項
$ct.each(function (index,node) {
new Carousel($(node));
})
}
}
})();
Carousel2.init($('.carousel'));
</script>
懶載入(曝光載入)封裝
相關文章
- 如何用物件導向的思維去封裝一個小型輪播圖外掛物件封裝
- js中用oop思想封裝輪播JSOOP封裝
- 物件導向:封裝,多型物件封裝多型
- 物件導向之封裝(Java)物件封裝Java
- 對FMDB物件導向封裝物件封裝
- js物件導向封裝級聯下拉選單列表JS物件封裝
- JavaScript物件導向之一(封裝)JavaScript物件封裝
- 複習java物件導向(封裝)Java物件封裝
- 物件導向08:封裝詳解物件封裝
- 20. 物件導向之封裝物件封裝
- js物件導向封裝拖動效果程式碼例項JS物件封裝
- 物件導向 -- 三大特性之封裝物件封裝
- [js高手之路]javascript物件導向的常見寫法與優缺點JSJavaScript物件
- java物件導向的三大特徵之封裝Java物件特徵封裝
- javascript物件導向的封裝簡單介紹JavaScript物件封裝
- go物件導向思想:封裝、繼承、多肽Go物件封裝繼承
- javascript物件導向封裝簡單介紹JavaScript物件封裝
- Javascript 物件導向程式設計(一):封裝JavaScript物件程式設計封裝
- 七種常見的物件導向設計原則物件
- [.net 物件導向程式設計基礎] (11) 物件導向三大特性——封裝物件程式設計封裝
- 如何使用JQ封裝輪播圖封裝
- JS物件導向JS物件
- 前端筆記之JavaScript物件導向(四)元件化開發&輪播圖|俄羅斯方塊實戰前端筆記JavaScript物件元件化
- Flutter 封裝一個 Banner 輪播圖Flutter封裝
- java物件導向(異常)Java物件
- PHP 物件導向 (八)類的自動載入PHP物件
- 物件導向三大特性-----封裝、繼承、多型物件封裝繼承多型
- 物件導向三大特徵(封裝/繼承/多型)物件特徵封裝繼承多型
- day11_物件導向(封裝丶static丶this)物件封裝
- JAVA物件導向基礎--封裝 繼承 多型Java物件封裝繼承多型
- ExtJS物件導向JS物件
- Js物件導向(1): 理解物件JS物件
- Cris 的 Scala 筆記整理(八):物件導向中級-封裝筆記物件封裝
- Python 物件導向程式設計之封裝的藝術Python物件程式設計封裝
- Java常見知識點彙總(③)——物件導向基礎Java物件
- Flutter 如何封裝一個 Banner 輪播圖?Flutter封裝
- Vue封裝Swiper實現圖片輪播Vue封裝
- js:物件導向程式設計,帶你認識封裝、繼承和多型JS物件程式設計封裝繼承多型