在上一篇 零基礎(chǔ)打造自己的 js 類庫(1) 中岁经,原本只是為了寫個(gè)小案例朋沮,說明一下閉包,js對象的作用缀壤。
后來我隱約有一個(gè)想法樊拓,我是不是可以將miniQuery寫得更完善一些呢。我的意思是說塘慕,盡量使用jQuery的調(diào)用規(guī)則筋夏,看看自己能不能把常用的方法模擬出來?
這個(gè)想法產(chǎn)生以后图呢,我感覺挺興奮条篷,正好可以藉由這個(gè)機(jī)會把js的知識點(diǎn)再復(fù)習(xí)一下。
今后只要有時(shí)間蛤织,我就把miniQuery更新一下赴叹,添加新的api方法進(jìn)去。作為自己的一個(gè)學(xué)習(xí)記錄指蚜。
零基礎(chǔ)打造自己的 js 類庫(1) 寫完后乞巧,我又陸陸續(xù)續(xù)地改了很多代碼,繼而有了下面這個(gè)版本姚炕,暫且就叫做miniQuery v2.0吧,嘿嘿丢烘。
API方法目前大概分為 三個(gè)區(qū)域:
1. dom 相關(guān) : 主要獲取dom元素
2. css 相關(guān):給dom元素設(shè)置css樣式
3. 事件相關(guān) :給元素添加事件
4. 屬性相關(guān):對元素屬性進(jìn)行各種操作
5. 簡易u(yù)i : 額柱宦,目前只寫了一個(gè)按鈕
我利用零碎時(shí)間寫了一個(gè)禮拜,沒想到假模假式的也弄了不少方法了播瞳,當(dāng)然掸刊,這些肯定是遠(yuǎn)遠(yuǎn)不夠的。不夠以后寫案例的時(shí)候我差不多就可以直接調(diào)用這個(gè)miniQuery.js了赢乓,主要方便了自己忧侧,如果覺得有必要石窑,我就可以立即在里面添加新的方法,實(shí)現(xiàn)了訂制功能蚓炬。
當(dāng)然松逊,目前這個(gè)版本功能還比較少,bug估計(jì)還有很多肯夏,不過沒關(guān)系经宏,反正就搞著玩玩,出了問題自己背鍋就行了驯击。主要還是用于培養(yǎng)興趣烁兰,我本身不是做前端開發(fā)的,但是個(gè)人隱約感覺js在未來必定會火徊都,當(dāng)然現(xiàn)在也非常受歡迎了沪斟,我打算繼續(xù)學(xué)下去。
首先來看看miniQuery怎么使用吧暇矫。
來一個(gè)測試頁面主之,引入miniQuery
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="js/miniQuery.js"></script>
<title>測試頁面</title>
<script type="text/javascript">
window.onload = function(){
}
</script>
</head>
<body>
<div class='box'></div>
</body>
</html>
頁面上只畫了一個(gè)div,其他啥也沒有袱耽。
div沒有寬高杀餐。
接下來,我們用miniQuery來拿到這個(gè)對象朱巨。
var $box = $('.box').eq(0);
console.log($box);
可見史翘,返回的并不是一個(gè)dom對象,而是一個(gè)miniQuery對象冀续,具體的原理在上一節(jié)中已經(jīng)闡明琼讽。
OK,我們來給它定義寬高和背景色洪唐。
var $box = $('.box').eq(0);
$box.css({
width : 80 ,
height : 80 ,
background : 'deeppink'
});
效果:
我們在api上還看到有width钻蹬,height,backgroundColor方法凭需,而且miniQuery還支持鏈?zhǔn)秸{(diào)用问欠,所以能這么寫:
$box.height(80).width(80).backgroundColor('deeppink');
效果是一樣的。
然后粒蜈,我們給它添加一個(gè)事件顺献,當(dāng)點(diǎn)擊的時(shí)候就把顏色換為skyblue:
var $box = $('.box').eq(0);
$box.css({
width : 80 ,
height : 80 ,
background : 'deeppink'
}).on('click',function(){
this.css({
background:'skyblue'
});
});
再來看一看簡單的ui。
我們來引入css文件:
<link rel="stylesheet" type="text/css" href="css/mui.css"/>
var $box = $('.box').eq(0);
$box.linkbutton();
按鈕的樣式就出來了枯怖,然后我們來設(shè)置按鈕的屬性注整。
var $box = $('.box').eq(0);
$box.linkbutton({
text : '保存' ,
click : function(){
alert('保存成功!');
}
});
按鈕的大小也自動(dòng)變大了。
至于其他方法肿轨,我就不一一測試了寿冕,問題肯定還是有的,以后慢慢完善吧椒袍。
至于這個(gè)miniQuery的具體實(shí)現(xiàn)驼唱,以后有機(jī)會的話我再開貼記錄吧。
附上目前的源代碼:
mui.css
.linkbutton {
padding: .4em .9em; /*em的好處就是隨著父元素的字體大小而變化槐沼,當(dāng)該元素的字體變化時(shí)曙蒸,會自適應(yīng)*/
border: 1px solid rgba(0,0,0,.1);
background-color: #ac0;
border-radius: .2em;
box-shadow: 0 1px 5px rgba(0,0,0,.5);
color: #fff;
text-shadow: 0 -.06em .24em rgba(0,0,0,.5); /*將陰影設(shè)置為半透明,就無所謂底色了岗钩,都能很好地適應(yīng)*/
font-size: 130%;
line-height: 1.5; /*行高是字號的1.5倍*/
display:inline-block;
cursor:pointer;
font-family: "微軟雅黑";
}
"use strict";
/**
* miniQuery 和 工具類庫
* 版本 2.0 (修正了一部分Bug纽窟,增加了一些方法)
* 作者:剽悍一小兔
*/
// ------------------------ 基本擴(kuò)展, 字符串,數(shù)組等---------------------------------//
function extend_base (){
if(!String.prototype.format ){
String.prototype.format = function() {
var e = arguments;
return this.replace(/{(\d+)}/g,function(t, n) {
return typeof e[n] != "undefined" ? e[n] : t
})
};
}
if (!Array.prototype.forEach && typeof Array.prototype.forEach !== "function") {
Array.prototype.forEach = function(callback, context) {
// 遍歷數(shù)組,在每一項(xiàng)上調(diào)用回調(diào)函數(shù),這里使用原生方法驗(yàn)證數(shù)組兼吓。
if (Object.prototype.toString.call(this) === "[object Array]") {
var i,len;
//遍歷該數(shù)組所有的元素
for (i = 0, len = this.length; i < len; i++) {
if (typeof callback === "function" && Object.prototype.hasOwnProperty.call(this, i)) {
if (callback.call(context, this[i], i, this) === false) {
break; // or return;
}
}
}
}
};
}
if(!String.prototype.format ){
Array.isArray = function(obj){
return obj.constructor.toString().indexOf('Array') != -1;
}
}
}
extend_base();
// ------------------------ 工具包---------------------------------//
var utils = {
center : function(dom){
dom.style.position = 'absolute';
dom.style.top = '50%';
dom.style.left = '50%';
dom.style['margin-top'] = - dom.offsetHeight / 2 + 'px';
dom.style['margin-left'] = - dom.offsetWidth / 2 + 'px';
},
/** dom相關(guān) * */
isDom : ( typeof HTMLElement === 'object' ) ?
function(obj){
return obj instanceof HTMLElement;
} :
function(obj){
return obj && typeof obj === 'object' && obj.nodeType === 1 && typeof obj.nodeName === 'string';
} ,
/** 數(shù)組相關(guān) * */
isArray : function(obj){
return obj.constructor.toString().indexOf('Array') != -1;
}
}
// ------------------------ miniQuery.js ---------------------------------//
;(function(win){
var miniQuery = function(selector){
var miniQuery = null;
var length = 0;
var children = [];
if(!selector) return;
/** 1. 傳入的是id * */
if(selector.toString().indexOf('#') != -1) {
selector = selector.replace('#','');
miniQuery = document.getElementById(selector);
}
/** 2. 傳入的是class * */
else if(selector.toString().indexOf('.') != -1){
selector = selector.replace('.','');
miniQuery = document.getElementsByClassName(selector);
}
/** 3. 傳入的是dom元素 * */
else if(utils.isDom(selector)){
miniQuery = selector;
}
if(!miniQuery) return; //如果本類庫包裝不了臂港,就返回
if(miniQuery.length){ //如果是一個(gè)類數(shù)組元素的話,就獲取他的長度
length = miniQuery.length;
}else{
length = 1; //這種情況视搏,說明成功包裹了元素审孽,但是該元素還是存在的,就將長度設(shè)定為1
}
children = miniQuery.children; //取得所有的孩子節(jié)點(diǎn)
return {
/** 屬性區(qū) */
obj : miniQuery, //返回的dom元素
index : 0 , //默認(rèn)的角標(biāo)(假如 miniquery 是一個(gè)類數(shù)組的話)
length : length, //元素的個(gè)數(shù)(假如 miniquery 是一個(gè)類數(shù)組的話)
children : children,//所有孩子節(jié)點(diǎn)
/** 方法區(qū) */
// ------------------------ dom 相關(guān) ---------------------------------//
/**獲取dom對象本身,返回純粹的dom元素浑娜,而非miniQuery元素*/
getObj : function(){
return this.obj;
} ,
/**獲取元素的長度*/
size : function(){
return this.length;
} ,
/** 假如 miniquery 是一個(gè)類數(shù)組的話佑力,用于返回其中一個(gè)元素 */
eq : function(index){
if(length > 0) {
return $(this.obj[index]); //eq返回的還是miniQuery對象
}else{
return null;
}
} ,
/** 獲得第一個(gè)匹配元素 */
first : function(){
return $(this.obj[0]);
} ,
/** 獲得最后一個(gè)匹配元素 */
last : function(){
return $(this.obj[this.length - 1]);
} ,
/** 獲得最后一個(gè)匹配元素 */
getChildren : function(){
return this.obj.children;
} ,
/** 獲得某一個(gè)孩子節(jié)點(diǎn) */
getChild : function(i){
return $(this.children[i]);
} ,
/** 獲得父節(jié)點(diǎn) */
getParent : function(){
return $(this.obj.parentElement);
} ,
/** 獲得上一個(gè)節(jié)點(diǎn) */
previous : function(){
var parent = this.getParent();
var children = parent.children;
for(var i = 0; i < children.length; i++){
if(this.obj == children[i]) {
return $(children[i - 1]);
}
}
return null;
} ,
/** 獲得下一個(gè)節(jié)點(diǎn) */
next : function(){
var parent = this.getParent();
var children = parent.children;
for(var i = 0; i < children.length; i++){
if(this.obj == children[i]) {
return $(children[i + 1]);
}
}
return null;
} ,
findClassDom : function(className){
this.obj = this.obj.getElementsByClassName(className) ;
return this ;
} ,
findIdDom : function(id){
var $this = this;
var children = this.getChildren();
children = Array.prototype.slice.call(children); //obj 轉(zhuǎn) []
children.forEach(function(item){
//console.log(item.id);
(id === item.id) && ($this = item) ;
});
return this ;
} ,
// ------------------------ css 相關(guān) ---------------------------------//
/** 添加背景色 */
backgroundColor : function(color){
this.obj.style.backgroundColor = color;
return this;
} ,
/** 獲取style */
getStyle : function(){
var styleEle = null;
if(window.getComputedStyle){
styleEle = window.getComputedStyle(this.obj,null);
}else{
styleEle = ht.currentStyle;
}
return styleEle;
} ,
/** 設(shè)置或者拿到高度 */
height : function(h){
if(!h) return this.getStyle().getPropertyValue('height');
(typeof h == 'number') && (h = h + 'px');
this.obj.style.height = h;
return this;
} ,
/** 設(shè)置或者拿到寬度 */
width : function(w){
if(!w) return this.getStyle().getPropertyValue('width');
(typeof w == 'number') && (w = w + 'px');
this.obj.style.width = w;
return this;
} ,
/** 設(shè)置自定義樣式 */
css : function(obj){
if(!obj) return;
for(var key in obj){
//console.log(key + '=========' + obj[key]);
this.obj.style[key] = typeof obj[key] === 'number' ? obj[key] + 'px' : obj[key];
}
return this;
} ,
/** 設(shè)置放大 倍數(shù)*/
scale : function(scaleNumber){
this.css({
scale : scaleNumber
});
return this;
} ,
hasClass : function(cls) {
return this.obj.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
} ,
addClass : function(cls){
if (!this.hasClass(cls)) this.obj.className += " " + cls;
} ,
removeClass : function(cls) {
if (this.hasClass(cls)) {
var reg = new RegExp('(\\s|^)' + cls + '(\\s|$)');
this.obj.className = obj.className.replace(reg, ' ');
}
} ,
toggleClass : function(cls){
if(this.hasClass(cls)){
this.removeClass(cls);
}else{
this.addClass(cls);
}
} ,
// ------------------------ 動(dòng)畫 相關(guān) ---------------------------------//
//TODO
animate : function(){
} ,
// ------------------------ 事件相關(guān) ---------------------------------//
on : function(eventName,callback){
var $this = this;
this.obj['on' + eventName] = function(){
callback.call($this,$this.obj); //context指向$this,參數(shù)傳入dom對象
};
return this;
} ,
// ------------------------ 屬性相關(guān) ---------------------------------//
attr : function(attr){
return this.obj.attributes[attr];
} ,
// ------------------------ ui ---------------------------------//
linkbutton : function(opts){
var opts = opts || {};
/**添加基本樣式* */
this.addClass('linkbutton');
this.on('mouseover' , function(e){
//console.log(e);
this.css({
backgroundColor: '#d4ef50'
});
}).on('mouseout',function(e){
this.css({
backgroundColor: '#ac0'
});
});
opts.text && (this.obj.innerText = opts.text);
opts.click && (this.on('click' , opts.click));
}
}
}
win.$ = miniQuery;
})(window);
我沒具體測試筋遭,如果發(fā)現(xiàn)目前代碼中的bug打颤,歡迎評論或者簡信我哦 _ 。