欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

详解用原生JavaScript实现jQuery的某些简单功能

程序员文章站 2023-08-19 10:51:55
大致介绍 学习了妙味,用原生的javascript实现jquery中的某些部分功能 定义自己的函数库lquery $()选择器的实现 jquery是面向对象的,所以...

大致介绍

学习了妙味,用原生的javascript实现jquery中的某些部分功能

定义自己的函数库lquery

$()选择器的实现

jquery是面向对象的,所以自己编写的也要是面向对象的,看看基本的结构

// 定义lquery对象
function lquery(larg){
}
function lq(larg){
 return new lquery(larg);
}
// css()方法
lquery.prototype.css = function(){};
// html()方法
lquery.prototype.html = function(){};

先来仿写jquery中的$(函数)的方法

// 定义lquery对象
function lquery(larg){
 // 用typeof判断参数的类型是 function 、
 switch( typeof larg){
 case 'function':
  // 如果采用这种写法,给lq绑定相同的函数,但是只会执行一次
  // window.onload = larg;
  // break;
 }
}

如果写出这样的函数就会出现问题

lq(function(){
  alert(1);
 });
 lq(function(){
  alert(2);
 });

这样就只会弹出'2',但是在jquery中都会弹出,所以上面的方法不对,我们采用事件绑定的形式来解决这个问题

// 绑定事件函数
function lqbind(obj,eventname,fn){
 // 标准浏览器
 if(obj.addeventlistener){
 obj.addeventlistener(eventname,fn,false);
 }else{
 // ie浏览器
 obj.attachevent('on'+eventname,fn);
 }
}

可以使用这样调用

switch( typeof larg){
 case 'function':
  // 如果采用这种写法,给lq绑定相同的函数,但是只会执行一次
  // window.onload = larg;
  // break;
  lqbind(window,'load',larg);
  break;
 }

仿写jquery中的$('.div')、$('#div')、$('div')三种方法

这三种方法的区别是第一个字符的不同,所以我们可以根据第一个字符的不同来进行区别对待

先来仿写$('.div')

   // '.div'
  case '.':
  this.elements = getclass(document,larg.substring(1));
   break;

由于getelementsbyclassname()是html5里的方法,像ie8以下不兼容所以我们自己写了一个简单的getclass方法

 // 获取class属性
function getclass(obj,name){
 var arr = [];
 var elems = obj.getelementsbytagname('*');
 for(var i=0;i<elems.length;i++){
 if(elems[i].classname == name){
  arr.push(elems[i]);
 }
 }
 return arr;
}

仿写$('#div')

  case '#':
   this.elements.push(document.getelementbyid(larg.substring(1)));
   break;
   // '.div'
  case '.':

仿写$('div')

default:
 // getelementsbytagname返回的是一个类数组nodelist,为了防止以后出现麻烦,要把他转为一个
 // 数组
 this.elements = toarray(document.getelementsbytagname(larg));
 break;

由于getelementsbytagname返回的是一个类数组nodelist,为了防止以后出现麻烦,要把他转为一个数组,自定义了一个toarray方法

// 将一个类数组转为真正的数组
function toarray(lickarr){
 var arr = [];
 for(var i=0;i<lickarr.length;i++){
 arr.push(lickarr[i]);
 }
 return arr;
}

仿写$(对象)的方法

      // window  document
      case 'object':
          this.elements.push(larg);
          break;

html()的实现

html()方法分为有参和无参

// html()方法
lquery.prototype.html = function(str){
 if(str){ //设置
 for(var i=0;i<this.elements.length;i++){
  this.elements[i].innerhtml = str;
 }
 }else{
 return this.elements[0].innerhtml;
 }
 return this;
};

on()方法的实现

利用前面实现的绑定函数可以很容易的实现

 lquery.prototype.on = function(eventname,fn){
     for(var i=0;i<this.elements.length;i++){
         lqbind(this.elements[i],eventname,fn);
     }
 }

click()和mouseover()方法的实现

利用on()方法可以容易的实现

// click()方法
lquery.prototype.click = function(fn){
 this.on('click',fn);
 return this;
}
// mouseover()方法
lquery.prototype.mouseover = function(fn){
 this.on('mouseover',fn);
 return this;
}

hide()和show()方法的实现

// hide()方法
lquery.prototype.hide = function(){
 for(var i=0;i<this.elements.length;i++){
 this.elements[i].style.display = 'none';
 }
 return this;
}
// show()方法
lquery.prototype.show = function(){
 for(var i=0;i<this.elements.length;i++){
 this.elements[i].style.display = 'block';
 }
 return this;
}

hover()方法的实现

 // hover()方法
 lquery.prototype.hover = function(fnover,fnout){
 this.on('mouseover',fnover);
 this.on('mouseout',fnout);
 return this;
 }

css()方法的实现

实现$('div').css('width')和$('div').css('width','200px')

lquery.prototype.css = function(attr,value){
 if(arguments.length == 2){
 for(var i=0;i<this.elements.length;i++){
  this.elements[i].attr = value;
 }
 }
 if(arguments.length == 1){
 return getstyle(this.elements[0],attr);
 }
}

定义了getstyle()方法是为了能找到行内样式以外的样式

// 获取属性
function getstyle(obj,attr){
 if(obj.currentstyle[attr]){
 obj.currentstyle[attr];
 }else{
 obj.getcomputedstyle(obj,false)[attr];
 }
}

attr()方法的实现

用了和css()不同的方法

// attr()方法
lquery.prototype.attr = function(attr,value){
 if(arguments.length == 2){ //设置
 for(var i=0;i<this.elements.length;i++){
  this.elements[i].setattribute(attr,value);
 }
 }
 else if(arguments.length == 1){ //获取
 return this.elements[0].getattribute(attr);
 }
 return this;
};

eq()方法的实现

 实现$('div').eq(1)

 由于eq()方法返回的对象要操作许多lquery的方法,所以返回的对象必须是lquery对象

 lquery.prototype.eq = function(num){
  return lq(this.elements[num]);
 };

index()方法的实现

实现$('div').index() 返回这个元素在同辈元素中的位置

lquery.prototype.index = function(){
 var elems = this.elements[0].parentnode.children;
 for(var i=0;i<elems.length;i++){
  if( elems[i] == this.elements[0] ){
  return i;
  }
 }
 };

阻止默认事件和阻止事件冒泡

在jquery中 return false 是阻止默认事件和事件冒泡,所以我们要对lqbind函数进行修改,通过判断绑定的函数的返回值是否为false来判断是否要进行阻止默认事件和阻止事件冒泡

function lqbind(obj,events,fn){
  if(obj.addeventlistener){
  obj.addeventlistener(events,function(ev){ 
   if( fn() == false ){
   ev.preventdefault();
   ev.cancelbubble = true;
   }
  },false);
  }
  else{
  obj.attachevent('on'+events,function(){
   if( fn() == false ){
   window.event.cancelbubble = true;
   return false;
   }
  });
  }
 }

find()方法的实现

仿写$('div').find('.box')和$('div').find('#box')方法

这里涉及到通过判断find()参数第一个字符的方法来进行不同的操作和$()方法差不多,在循环时要使用concat()方法来连接数组,最后返回一个lquery对象

lquery.prototype.find = function(sel){
  var arr = [];
  if( sel.charat(0) == '.' ){ 
  for(var i=0;i<this.elements.length;i++){ 
   arr = arr.concat(getclass( this.elements[i] , sel.substring(1) ));
  }
  }
  else{ 
  for(var i=0;i<this.elements.length;i++){ 
   arr = arr.concat(toarray(this.elements[i].getelementsbytagname(sel)));
  }
  }
  return lq(arr); 
 };

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!