`
devil13th
  • 浏览: 42094 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

自己的js框架

阅读更多

 模仿jquery,写了自己的框架,只不过jquery的选择器是css的选择器功能没有实现,这个感觉有点困难,毕竟都是正则表达式,在写自己的框架的同时,也能了解一下jquery的工作原理,更好的进行开发

 

事先声明:此js比不了jquery只是在编写的过程中以个人的思路模仿jquery的部分功能 - 插件是怎么开发的,扩展是如何实现的,等等。jquery有自己强大的类似于css的选择器,我只做了id的功能


最外层的是通过
(function(){
......... //代码
})()
包装起来,为了防止和其他js声明的变量冲突

构造函数 _T = function(obj){........} 封装了DOM Element 对象,以便可以使用自己定义的方法(函数)去对这个对象进行各种原生js的操作. obj这个参数可以是DOM element的id 也可以是DOM element本身 或者是 _T创建的对象。

通过 window.t = window.ThirdteenDevil = function(obj){return new _T(obj)} 来返回由_T封装的对象,把window.t定义成返回一个由_T创建的对象的函数,使用的时候类似于t("id"),就是jquery中的$("#id"),这样可以获取到_T类创建的对象,以便使用自定义的各种方法

通过prototype属性为_T添加各种方法
_T.prototype={
    css:function(){},
    attr:function(){},
    data:function(){},
    ...
     
}
这样一来,通过t(obj)得到的对象就可以使用以上css,attr,data....等各种方法操作obj对象了。方法可以由使用此js的人自己扩展,类似于jquery的方法扩展。这个扩展功能依然是使用prototype来实现的。
至于插件,同jquery的插件扩展
扩展格式:
(function(t){
    t.plugs.自定义的插件名称 = function(){
          ......
          ......
          .....//内容
    }
})(t)
使用上面的格式依然是防止和其他变量冲突可以在(function(){....})()的作用域中定义自己的变量。
t.plugs是已经定义好的一个空的对象,通过给这个对象赋属性来扩展插件。


以下是代码  源文件和例子在附件中

/*
* thd-simple.js
* begin : 2010-11-12
* author : ThirdteenDevil
* e-mail : thirdteendevil@163.com
* qq : 181907667
*/

(function(){
	var _T = function(obj){

		//原生DOM element
		this.el = null;

		//ThirdteenDevil对象的标记
		this.constructor = "ThirdteenDevil";

		//如果是ThirdteenDevil对象则返回形式参数
		if(obj.constructor == "ThirdteenDevil"){
			return obj;
		}
		
		
		if(typeof(obj) == "string"){
			if(document.getElementById(obj)){
				this.el = document.getElementById(obj);
			}
		}else{
			this.el = obj;
		}
	}

	window.t = window.ThirdteenDevil = function(obj){return new _T(obj)}

	_T.prototype = {
		
		/*
		*回调函数,用于处理所有方法中function类型的参数
		*@param obj 任何类型
		*@return 如果@param obj是一个函数类型的对象,则返回这个函数的返回值,如果是其他类型则直接返回@param obj
		*/
		_preFormCallBack : function(obj){
			var _this = this;
			var ret = obj;
			if(typeof(obj) == "function"){
				ret = obj.call(_this.el,_this.el);
			}
			return ret;
		},
		
		/*
		*如果是无参数调用 .html()
		*@return 对象的innerHTML属性
		*---------------------------------------
		*如果是.html(str)
		*@param str 设置对象的innerHTML值
		*@return this 用于链式调用
		*/		
		html : function(v){
			if(v == undefined){
				return this.el.innerHTML;
			}else{
				var v = this._preFormCallBack(v);
				this.el.innerHTML = v;
				return this;
			}
		},		
		
		/*
		*如果是一个参数调用 .attr(str)
		*@param str DOM element的属性名
		*@return Dom element名为@param str属性的值
		*----------------------------------------
		*如果是二个参数 .attr(str,v)
		*@param str DOM element的属性名
		*@param v Dom element @param str 属性的值
		*@return this 用于链式调用
		*/
		attr : function(){
			if(arguments.length == 1){
				return this.el.getAttribute(arguments[0]);
			}
			if(arguments.length == 2){
				this.el.setAttribute(arguments[0],arguments[1]);
				return this;
			}
		},
		
		/*
		*除去DOM element的属性
		*@param str DOM element的属性名称
		*@return this 用于链式调用
		*/
		removeAttr : function(str){
			this.el.removeAttribute(str);
			return this;
		},

		/*
		*如果是无参调用 .css()
		*@return DOM element 的所有css属性
		*-----------------------------------------
		*如果是.css(str)
		*@param str css属性名 可以根据.css()方法来查询
		*@return 获取参数对应的css属性
		*----------------------------------------
		*如果是.css(str,value)
		*@param str css属性名  可以根据.css()方法来查询
		*@value 设置@param str的值为@value
		*@return this 用于链式调用
		*/
		css : function(){
			var CurrentStyle = function(element){return element.currentStyle || document.defaultView.getComputedStyle(element, null);}
			if( (arguments.length < 1) || (arguments.length > 2) ){
				if(arguments.length == 0){
					var cssAttrMap = [];
					for(var pro in CurrentStyle(this.el)){
						cssAttrMap.push([pro,CurrentStyle(this.el)[pro]]);
					}
					return cssAttrMap;
				}else{
					throw new Error("css function arguments must be between 1 and 2 ! ");
				}
			}else{
				if(arguments.length == 1){
					return CurrentStyle(this.el)[arguments[0]];
				}else{
					this.el.style[arguments[0]] = this._preFormCallBack(arguments[1]);
					return this;
				}
			}
		},
				
		/*
		*如果是无参调用 .hasClass()
		*@return className属性值 
		*-----------------------------------
		*如果是.hasClass(v)
		*@param v className,
		*@return 判断DOM element是否含有名为@param v的className属性
		*/		
		hasClass : function(v){
			if(v == undefined){
				return this.el.className;
			}else{
				if(this.el.className != undefined){
					var classStr = " " + this.el.className + " ";
					var rep = new RegExp(" " +v+ " ","gi");
					return rep.test(classStr);
				}else{
					return false;
				}
			}
		},
		
		/*
		*为DOM element添加className属性值
		*@param v 要添加的className属性值
		*@return this用于链式调用
		*/
		addClass : function(str){
			var v = this._preFormCallBack(str);
			if(this.hasClass(v)){
				return this;
			}else{
				if(this.el.className){
					this.el.className += (" "+v);
					return ;
				}else{
					this.el.className = v;
				}
			}
		},
		
		/*
		*为Dom element删除className属性值
		*@param v 要删除的className属性值
		*@return this用于链式调用
		*/
		removeClass : function(v){
			if(this.hasClass(v)){
				var classStr = " " + this.el.className + " ";				
				var rep = new RegExp(" " + v + " ","gi");
				this.el.className = classStr.replace(rep," ");
			}else{
				return this;
			}
		},

		/*
		*为DOM element 添加/删除一个className属性值,有则删除,无则添加
		*@param str className的属性值也可以是一个回调函数,返回className的属性值
		*@return this 用于链式调用
		*/
		toggleClass : function(str){
			var v = this._preFormCallBack(str);
			if(this.hasClass(v)){
				this.removeClass(v);
			}else{
				this.addClass(v);
			}
			return this;
		},
		
		/*
		*如果无参调用 .scrollTop()
		*@return DOM element scrollTop属性值
		*----------------------------------------------
		*一个参数调用 .scrollTop(x)
		*@param x DOM element scrollTop属性值
		*@return this 用于链式调用
		*/
		scrollTop : function(){
			if(arguments.length == 1){
				this.el.scrollTop = arguments[0];
			}else{
				return this.el.scrollTop;
			}
		},

		/*
		*如果无参调用 .scrollLeft()
		*@return DOM element的scrollLeft属性值
		*----------------------------------------------
		*一个参数调用 .scrollLeft(x)
		*@param x DOM element scrollLeft属性值
		*@return this 用于立案时调用
		*/
		scrollLeft : function(){
			if(arguments.length == 1){
				this.el.scrollLeft = arguments[0];
			}else{
				return this.el.scrollLeft;
			}
		},
		
		/*
		*为DOM element添加事件
		*@param act : 事件名 click,mouseover,mouseout ....
		*@param cb : Function类型的回调函数
		*@param pObj : json格式的参数,回调函数中调用
		*/
		on : function(act,cb,pObj){
			var _this = this;
			if(window.addEventListener){//FF ...
				this.el.addEventListener(act,function(e){
					var e = e ? e : event;					
					//e.stopPropagation();//清冒泡
					cb.call(_this.el,e,_this.el,pObj)},false);
			}else if(window.attachEvent){//IE
				this.el.attachEvent("on"+act,function(e){
				var e = e ? e : event;
				//window.event.cancelBubble = true;//清冒泡
				cb.call(_this.el,e,_this.el,pObj)});
			}
			return this;
		},
		
		/*
		*把DOM element添加到this.el对象中
		*@param obj 可以是ThirdteenDevil对象 也可以是id字符串 或者是DOM element本身
		*@return this 用于链式调用
		*/
		append : function(obj){
			//把obj转成ThirdteenDevil对象后操作
			this.el.appendChild(new _T(obj).el);
		},		

		/*
		*把this.el对象添加到DOM element中
		*@param obj 可以是ThirdteenDevil对象 也可以是id字符串 或者是DOM element本身
		*@return this 用于链式调用
		*/
		appendTo : function(obj){
			//把obj转成ThirdteenDevil对象后操作
			new _T(obj).el.appendChild(this.el);
		},
		
		/*
		*getElementsByTagName实现
		*@param tag 元素标签名
		*@return 获取子元素标签是@param tag的所有子元素(已转成数组类型)
		*/
		getElementsByTagName : function(tag){
			var childs = this.el.getElementsByTagName(tag);
			var childArray = []
			for(var i = 0 , j = childs.length ; i < j ; i++){
				childArray.push(childs[i]);
			}
			return childArray;
		},
		
		/*
		*获取ThirdteenDevil中el对象的子对象有name属性为形参的对象集合
		*@param nameStr name属性的值
		*@return ThirdteenDevil中el对象的子对象有name属性为形参的对象集合(已转成数组)
		*/
		getElementsByName : function(nameStr){
			var els = []
			this.getElementsByTagName("*").each(function(o,i){
				if(nameStr == new _T(o).attr("name")){
					els.push(o);
				}
			})
			return els;
		},

		/*
		*如果是无参调用 .data()
		*@return Dom Element的data属性
		*----------------------------------
		*如果是一个字符串类型的参数 .data(str)
		*@param str data的属性名
		*@return data中@param str的属性值
		*----------------------------------
		*如果是一个对象类型的参数 .data(obj)
		*@param obj 拷贝obj的所有属性刀data中
		*@return this 用于链式调用
		*----------------------------------
		*如果是2个参数 .data(str,obj)
		*@param str 设置data中的属性
		*@param obj data中名为@param str的值
		*@return this 用于链式调用
		*/
		data : function(){			
			if(this.el.getAttribute("data") == undefined){
				this.el.setAttribute("data",{});
			}
			if(arguments.length == 1){
				if(typeof(arguments[0]) == "string"){
					return this.el.getAttribute("data")[arguments[0]];
				}else if(typeof(arguments[0]) == "object"){
					for(var pro in arguments[0]){
						this.el.getAttribute("data")[pro] = arguments[0][pro];
					}
					return this;
				}
			}
			if(arguments.length == 2){
				this.el.getAttribute("data")[arguments[0]] = arguments[1];
				return this;
			}
			if(arguments.length == 0){
				return this.el.getAttribute("data");
			}
		}
	}//_T.prototype end

	
	/*
	*扩展_T方法
	*
	*如果是一个参数 .extend(obj)
	*@param obj 封装好将要扩展的属性或方法集合
	*------------------------------------------
	*如果是二个参数 .extend(str,v)
	*@param str 扩展的属性名
	*@param v 扩展的属性名@param str的值或方法
	*
	*如果自定义的属性和_T中的属性重名 不会覆盖原有属性
	*/
	ThirdteenDevil.extend = function(){
		if(arguments.length == 1){
			for(var pro in arguments[0]){
				_T.prototype[pro] = arguments[0][pro];
			}
		}
		if(arguments.length == 2){
			_T.prototype[arguments[0]] = arguments[1];
		}
	}


	//插件
	ThirdteenDevil.plugs = {};

	
})()

//数组循环执行
Array.prototype.each = function(cb){
	for(var i = 0 , j = this.length ; i < j ; i++){
		cb.call(this[i],this[i],i);
	}
}


//数组移除某个值
Array.prototype.remove = function(obj){
	var r = null;
	for(var i = 0 , j = this.length ; i < j ; i++){
		if(obj == this[i]){
			r = this.splice(i,1);
			break;
		};
	}
	return r;
}

//得到数组中某个元素在数组中的索引值
Array.prototype.index = function(obj){
	for(var i = 0 , j = this.length ; i < j ; i++){
		if(obj == this[i]){
			return i;
		};
	}
}

//字符串去除前后空格
String.prototype.trim= function(){
    return this.replace(/(^\s*)|(\s*$)/g, "");  
}

 

 

 

方法的扩展:

t.extend("tt",function(){
	alert(this.el.value)
})

t("a").on("keyup",function(e,o){
	t(this).tt();
})




t.extend({
	t1: 1,
	t2: 2,
	id : "a",
	el : "1",//属性相同不会被覆盖
	m1 : function(){
		alert(this.el)
		alert(this.el.id);
		alert(this.t1);
	}
})


t("b").on("click",function(e,o){
	t(this).m1();
	alert("t1 :" + t(this).t1)
})

 

插件的编写:

(function(t){

	t.plugs.ScrollDoor = function(obj){
		this.menus = obj.menus;
		this.contents = obj.contents;
		this.hoverClass = obj.hover;
		this.blurClass = obj.blur;
		this.focusClass = obj.focus;
		this.evt = "click" || obj.evt;
	}

	t.plugs.ScrollDoor.prototype = {
		_clear : function(){
			var _this = this;
			this.menus.each(function(m,i){
				t(m).removeClass(_this.hoverClass);
				t(m).removeClass(_this.focusClass);
			})
			if((this.contents != undefined) && (this.contents.length != 0)){
				this.contents.each(function(m,i){
					t(m).css("display","none");
				})
			}
		},

		_hasContents : function(){
			if((this.contents != undefined) && (this.contents.length != 0)){
				return true;
			}else{
				return false;
			}
		},
		
		focus : function(index){
			this._clear();
			t(this.menus[index]).addClass(this.focusClass);
			if((this.contents[index] != undefined) && (this.contents.length != 0)){
				t(this.contents[index]).css("display","block");
			}
		},

		run : function(){
			var _this = this;
			this.menus.each(function(m,i){
				t(m).on(_this.evt,function(e,o){
					_this.focus(i);
				})
			})
		},

		add : function(){
			this.menus.push(arguments[0]);
			if(this._hasContents()){
				this.contents.push(arguments[1]);
			}
			this.run();
			this.focus(this.menus.length - 1);
		}

		
	}
	
})(ThirdteenDevil)


var sd = new t.plugs.ScrollDoor({
	menus : ["m01","m02","m03"],
	contents : ["c01","c02","c03"],
	hover : "hover",
	focus : "focus",
	blur : "blur",
	evt : "click"
})

sd.run();
sd.add("m04","c04");

 

所有文件都在附件中,详细例子见附件

 

0
0
分享到:
评论
2 楼 devil13th 2010-11-19  
谢谢 兄弟 ,学js的时候jquery还没有出。。。 一点一点学的 呵呵
1 楼 87399126 2010-11-18  
JS没啥实际经验,但平时挺喜欢看这种书籍,发下我的读后感吧
1,append 函数跟appendTo貌似忘记返回this了
2 , 为什么不添加个each函数,这样可以把你的包装器T函数扩展为接受一个dom对象数组(比如以常见的“,”分割接受多个id值),反正只是自己用的方便库总共也就10几20个函数  每个函数利用个each函数为包装器中的所有dom对象做一次操作比如(挑个简单的)
append : function(var){
      this.each(function(eli){
             eli.appendChild(new _T(var));
      })
}
关于each函数(each:function(fn){..............})的实现无非就是对包装器对象里的对象数组的一次遍历,有个关键点就是类似你这个事件添加函数的做法用fn.call(this,this.le[i]),使之fn第一个参数指向当前遍历到的dom对象。
而且既然你在后面已经添加了byTagName等返回Dom数组的方法,有了each函数就可以返回一个包装器对象了,这样在形式上也统一一点。
3,事件添加函数,没那个json参数会好读非常多。可能看的书还不够深入,但是我还是觉得这个参数在实际应用中出现的概率不会太大。
4,看了你整理的库还是学到了很多东西,你是直接看的jquery的库学习javascript的吗?
你的博客写的很好,不想别的人东西基本都是挪来挪去的。

相关推荐

Global site tag (gtag.js) - Google Analytics