鏈式調用
鏈式調用其實只不過是一種語法招數。它能讓你通過重用一個初始操作來達到用少量代碼表達復雜操作的目的。該技術包括兩個部分:
一個創建代表HTML元素的對象的工廠。
一批對這個HTML元素執行某些操作的方法。
調用鏈的結構
$函數負責創建支持鏈式調用的對象
復制代碼 代碼如下:
(function() {
/*
* 創建一個私有class
* @param {Object} els arguments 所有參數組成的類數組
*/
function _$(els) {
this.elements = []; //存放HTML元素
for(var i=0, len=els.length; i<len; i++) {
var element = els[i];
if(typeof element === 'string') {
element = document.getElementById(element);
}
this.elements.push(element);
}
}
//對HTML元素可執行的操作
_$.prototype = {
each: function() {},
setStyle: function() {},
show: function() {},
addEvent: function() {},
};
//對外開放的接口
window.$ = function() {
return new _$(arguments);
};
})();
由於所有對象都會繼承其原型對象的屬性和方法,所以我們可以讓定義在原型對象中的那些方法都返回用以調用方法的實例對象的引用,這樣就可以對那些方法進行鏈式調用了。
復制代碼 代碼如下:
(function() {
/*
* 創建一個私有class
* @param {Object} els arguments 所有參數組成的類數組
*/
function _$(els) {
//...
}
//對HTML元素可執行的操作
_$.prototype = {
each: function(fn) { //fn 回調函數
for(var i=0; i<this.elements.length; i++) {
//執行len次,每次把一個元素elements[i]作為參數傳遞過去
fn.call(this, this.elements[i]);
}
return this;
},
setStyle: function(prop, value) {
this.each(function(el) {
el.style[prop] = value;
});
return this;
},
show: function() {
var that = this;
this.each(function(el) {
that.setStyle('display', 'block');
});
return this;
},
addEvent: function(type, fn) {
var addHandle = function(el) {
if(document.addEventListener) {
el.addEventListener(type, fn, false);
}else if(document.attachEvent) {
el.attachEvent('on'+type, fn);
}
};
this.each(function(el) {
addHandle(el);
});
return this;
}
};
//對外開放的接口
window.$ = function() {
return new _$(arguments);
}
})();
//----------------------- test --------
$(window).addEvent('load', function() {
$('test-1', 'test-2').show()
.setStyle('color', 'red')
.addEvent('click', function() {
$(this).setStyle('color', 'green');
});
})
鏈式調用的方法獲取數據
使用回調函數從支持鏈式調用的方法獲取數據。鏈式調用很適合賦值器方法,但對於取值器方法,你可能希望他們返回你要的數據而不是this(調用該方法的對象).解決方案:利用回調技術返回所要的數據.
復制代碼 代碼如下:
window.API = window.API || function() {
var name = 'mackxu';
//特權方法
this.setName = function(name0) {
name = name0;
return this;
};
this.getName = function(callback) {
callback.call(this, name);
return this;
};
};
//------------- test ---
var obj = new API();
obj.getName(console.log).setName('zhangsan').getName(console.log);
設計一個支持方法鏈式調用的JS庫
JS庫特征:
事件: 添加和刪除事件監聽器、對事件對象進行規劃化處理
DOM: 類名管理、樣式管理
Ajax: 對XMLHttpRequest進行規范化處理
復制代碼 代碼如下:
Function.prototype.method = function(name, fn) {
this.prototype[name] = fn;
return this;
};
(function() {
function _$(els) {
//...
}
/*
* Events
* addEvent
* removeEvent
*/
_$.method('addEvent', function(type, fn) {
//...
}).method('removeEvent', function(type, fn) {
})
/*
* DOM
* addClass
* removeClass
* hover
* hasClass
* getClass
* getStyle
* setStyle
*/
.method('addClass', function(classname) {
//...
}).method('removeClass', function(classname) {
//...
}).method('hover', function(newclass, oldclass) {
//...
}).method('hasClass', function(classname) {
//...
}).method('getClass', function(classname) {
//...
}).method('getStyle', function(prop) {
//...
}).method('setStyle', function(prop, val) {
//...
})
/*
* AJAX
* ajax
*/
.method('ajax', function(url, method) {
//...
});
window.$ = function() {
return new _$(arguments);
};
//解決JS庫命名沖突問題
window.installHelper = function(scope, interface) {
scope[interface] = function() {
return _$(arguments)
}
}
})();
小結:
鏈式調用有助於簡化代碼的編寫工作,並在某種程度上可以讓代碼更加簡潔、易讀。很多時候使用鏈式調用可以避免多次重復使用一個對象變量,從而減少代碼量。如果想讓類的接口保持一致,讓賦值器和取值器都支持鏈式調用,那麼你可以在取值器中使用回調函數來解決獲取數據問題。