zoukankan      html  css  js  c++  java
  • jQuery学习之路(7)- 用原生JavaScript实现jQuery的某些简单功能

    ▓▓▓▓▓▓ 大致介绍

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

        定义自己的函数库lQuery

    ▓▓▓▓▓▓ $()选择器的实现

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

     1 // 定义lQuery对象
     2 function lQuery(lArg){
     3 
     4 
     5 }
     6 
     7 function lQ(lArg){
     8     return new lQuery(lArg);
     9 
    10 }
    11 
    12 // css()方法
    13 lQuery.prototype.css = function(){};
    14 
    15 // html()方法
    16 lQuery.prototype.html = function(){};

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

     1 // 定义lQuery对象
     2 function lQuery(lArg){
     3 
     4     // 用typeof判断参数的类型是 function 、
     5     switch( typeof lArg){
     6         case 'function':
     7             //  如果采用这种写法,给lQ绑定相同的函数,但是只会执行一次
     8             // window.onload = lArg;
     9             // break;
    10     }
    11 
    12 }

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

     1         lQ(function(){
     2 
     3             alert(1);
     4 
     5         });
     6         lQ(function(){
     7 
     8             alert(2);
     9 
    10         });

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

     1 // 绑定事件函数
     2 function lQbind(obj,eventName,fn){
     3     // 标准浏览器
     4     if(obj.addEventListener){
     5         obj.addEventListener(eventName,fn,false);
     6     }else{
     7         // IE浏览器
     8         obj.attachEvent('on'+eventName,fn);
     9     }
    10 }

        可以使用这样调用

    1     switch( typeof lArg){
    2         case 'function':
    3             //  如果采用这种写法,给lQ绑定相同的函数,但是只会执行一次
    4             // window.onload = lArg;
    5             // break;
    6             lQbind(window,'load',lArg);
    7             break;
    8     }

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

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

        先来仿写$('.div')

    1                     // '.div'
    2                 case '.':
    3                     this.elements = getClass(document,lArg.substring(1));
    4                     break;

        由于getElementsByClassName()是HTML5里的方法,像IE8以下不兼容所以我们自己写了一个简单的getClass方法

     1 // 获取class属性
     2 function getClass(obj,name){
     3     var arr = [];
     4     var elems = obj.getElementsByTagName('*');
     5     for(var i=0;i<elems.length;i++){
     6         if(elems[i].className == name){
     7             arr.push(elems[i]);
     8         }
     9     }
    10     return arr;
    11 }

        仿写$('#div')

    1                 case '#':
    2                     this.elements.push(document.getElementById(lArg.substring(1)));
    3                     break;
    4                     // '.div'
    5                 case '.':

        仿写$('div')

    1                 default:
    2                     // getElementsByTagName返回的是一个类数组NodeList,为了防止以后出现麻烦,要把他转为一个
    3                     // 数组
    4                     this.elements = toArray(document.getElementsByTagName(lArg));
    5                     break;

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

    1 // 将一个类数组转为真正的数组
    2 function toArray(lickArr){
    3     var arr = [];
    4     for(var i=0;i<lickArr.length;i++){
    5         arr.push(lickArr[i]);
    6     }
    7     return arr;
    8 }

        仿写$(对象)的方法

    1         // window  document
    2         case 'object':
    3             this.elements.push(lArg);
    4             break;

     

    ▓▓▓▓▓▓ html()的实现

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

     1 // html()方法
     2 lQuery.prototype.html = function(str){
     3 
     4     if(str){  //设置
     5         for(var i=0;i<this.elements.length;i++){
     6             this.elements[i].innerHTML = str;
     7         }
     8     }else{
     9         return this.elements[0].innerHTML;
    10     }
    11     return this;
    12     
    13 };

    ▓▓▓▓▓▓ on()方法的实现

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

    1 lQuery.prototype.on = function(eventName,fn){
    2     for(var i=0;i<this.elements.length;i++){
    3         lQbind(this.elements[i],eventName,fn);
    4     }
    5 }

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

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

     1 // click()方法
     2 lQuery.prototype.click = function(fn){
     3     this.on('click',fn);
     4     return this;
     5 }
     6 
     7 // mouseover()方法
     8 lQuery.prototype.mouseover = function(fn){
     9     this.on('mouseover',fn);
    10     return this;
    11 }

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

     1 // hide()方法
     2 lQuery.prototype.hide = function(){
     3 
     4     for(var i=0;i<this.elements.length;i++){
     5         this.elements[i].style.display = 'none';
     6     }
     7     return this;
     8 }
     9 
    10 // show()方法
    11 lQuery.prototype.show = function(){
    12 
    13     for(var i=0;i<this.elements.length;i++){
    14         this.elements[i].style.display = 'block';
    15     }
    16     return this;
    17 }

    ▓▓▓▓▓▓ hover()方法的实现

    1 // hover()方法
    2 lQuery.prototype.hover = function(fnover,fnout){
    3     this.on('mouseover',fnover);
    4     this.on('mouseout',fnout);
    5     return this;
    6 }

    ▓▓▓▓▓▓ css()方法的实现

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

     1 lQuery.prototype.css = function(attr,value){
     2     if(arguments.length == 2){
     3         for(var i=0;i<this.elements.length;i++){
     4             this.elements[i].attr = value;
     5         }
     6     }
     7 
     8     if(arguments.length == 1){
     9         return getStyle(this.elements[0],attr);
    10     }
    11 }

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

    1 // 获取属性
    2 function getStyle(obj,attr){
    3     if(obj.currentStyle[attr]){
    4         obj.currentStyle[attr];
    5     }else{
    6         obj.getComputedStyle(obj,false)[attr];
    7     }
    8 }

    ▓▓▓▓▓▓ attr()方法的实现

        用了和css()不同的方法

     1 // attr()方法
     2 lquery.prototype.attr = function(attr,value){
     3 
     4     if(arguments.length == 2){  //设置
     5         for(var i=0;i<this.elements.length;i++){
     6             this.elements[i].setAttribute(attr,value);
     7         }
     8     }
     9     else if(arguments.length == 1){ //获取
    10         return this.elements[0].getAttribute(attr);
    11     }
    12     return this;
    13 };

    ▓▓▓▓▓▓ eq()方法的实现

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

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

    1         lQuery.prototype.eq = function(num){
    2             return lQ(this.elements[num]);
    3         };

    ▓▓▓▓▓▓ index()方法的实现

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

     1         lQuery.prototype.index = function(){
     2         
     3         var elems = this.elements[0].parentNode.children;
     4         
     5         for(var i=0;i<elems.length;i++){
     6             if( elems[i] == this.elements[0] ){
     7                 return i;
     8             }
     9         }
    10     };    

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

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

     1     function lQbind(obj,events,fn){
     2             if(obj.addEventListener){
     3                 obj.addEventListener(events,function(ev){
     4                     
     5                     if( fn() == false ){
     6                         ev.preventDefault();
     7                         ev.cancelBubble = true;
     8                     }
     9                     
    10                 },false);
    11             }
    12             else{
    13                 obj.attachEvent('on'+events,function(){
    14                     
    15                     if( fn() == false ){
    16                         window.event.cancelBubble = true;
    17                         return false;
    18                     }
    19                     
    20                 });
    21             }
    22         }

    ▓▓▓▓▓▓ find()方法的实现

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

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

     1         lQuery.prototype.find = function(sel){
     2             
     3             var arr = [];
     4             
     5             if( sel.charAt(0) == '.' ){ 
     6                 for(var i=0;i<this.elements.length;i++){    
     7                     arr = arr.concat(getClass( this.elements[i] , sel.substring(1) ));
     8                 }
     9             }
    10             else{  
    11                 for(var i=0;i<this.elements.length;i++){    
    12                     arr = arr.concat(toArray(this.elements[i].getElementsByTagName(sel)));
    13                 }
    14             }
    15             return lQ(arr);    
    16         };

        

  • 相关阅读:
    mysql优化之索引优化
    mysqld --debug-sync
    mysql.cnf 配制文件详解
    my.cnf 中字符集设置
    tcp_tw_reuse 与 net.ipv4.tcp_tw_recycle
    mysql init_connect 参数的其他用处
    监控mysql索引使用效率的脚本
    mysql 源代码学习 博客 [lock..]
    mysqld with valgrind
    思维导图软件
  • 原文地址:https://www.cnblogs.com/qqandfqr/p/6187520.html
Copyright © 2011-2022 走看看