zoukankan      html  css  js  c++  java
  • 简易版jQuery——mQuery

     

     

    前面的话

      虽然jQuery已经日渐式微,但它里面的许多思想,如选择器、链式调用、方法函数化、取赋值合体等,有的已经变成了标准,有的一直影响到现在。所以,jQuery是一个伟大的前端框架。前端世界日新月异,由于实在是没有时间去精读源码,于是自己封装一个简易版本的jQuery,来梳理jQuery的核心思路

    基本构架

      由于火柴的英文是match,应该将这个简单框架称为mQuery。使用面向对象的写法来写mQuery,构造函数是Mquery(),调用$()方法,将根据Mquery()构造函数,创建一个实例对象

    //构造函数
    function Mquery(arg){}
    function $(arg){
      return new Mquery(arg);
    } 

      jquery几大特征:

      1、通过$()选择的元素都是一个集合,即使仅仅是一个元素

      因此,创建一个elements属性为一个数组,去接收获取的元素

    //构造函数
    function Mquery(arg){
      //保存所选择的元素
      this.elements = [];
    }

      2、链式调用

      所以,原型函数要返回this,以实现链式调用的效果

    $函数

      $函数根据参数类型的不同,用途也不同

      1、参数为函数时,则直接运行

    $(function(){
        console.log(1)
    })

      2、参数为对象时,则把DOM对象转换为$对象

    $(document.body)

      3、参数为字符串时,则根据字符串选择出元素,并转换为$对象

    $('#box')

      下面根据以上三个分类,来编写Mquery构建函数

    复制代码
    //事件绑定兼容写法
    function _addEvent(target,type,handler){
        if(target.addEventListener){
            target.addEventListener(type,function(e){
              //如果事件函数中出现 return false;则阻止默认事件和阻止冒泡
              if(typeof handler == 'function' && handler() === false){
                e.preventDefault();
                e.cancelBubble = true;
              }
            },false);
        }else{
            target.attachEvent('on'+type,function(event){
              if(typeof handler == 'function' && handler() === false){
                event.cancelBubble = true;
                event.returnValue = false;
              }
                return handler.call(target,event);
            });
        }
    }
    
    //将类数组转换成数组
    function _toArray(arrayLike){
      return Array.prototype.slice.call(arrayLike);
    }
    复制代码
    复制代码
    //构造函数
    function Mquery(arg){
      //保存所选择的元素
      this.elements = [];
      switch(typeof arg){
        //当参数是函数时,如$(function(){})(),直接运行里面的代码
        case 'function':
          _addEvent(window,'load',arg);
          break;
        //当参数是字符串时,选择元素
        case 'string':
          this.elements = _toArray(document.querySelectorAll(arg));              
          break;
        //当参数是DOM对象时,将DOM对象转换为$对象  
        case 'object':
          if(arg.constructor == Array){
            this.elements = arg;
          }else{
            this.elements.push(arg);
          }      
          break;
      }
    }
    复制代码

    HTML、CSS及特性设置

      下面来介绍常用的HTML、CSS及特性设置

    【HTML】

      对于文本内容来说,一般地,有三种方法:html()、text()和val()。本文只实现最常用的html()方法

      当html()方法没有参数时,表示获取内容;有一个参数时,表示设置内容

    复制代码
    //HTML获取与设置
    Mquery.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;
    }
    复制代码

    【CSS】

      对于CSS来说,有两种参数格式:一种是json格式,一种是字符串格式

      当第一个参数为对象时,则判断为json格式,否则为字符串格式

      对于字符串格式来说,只有一个参数时,为获取样式,两个参数时,为设置样式

      获取样式时,仅获取当前集合中第0个元素的样式;设置样式时,则设置当前集合中所有元素的样式

    复制代码
    //获取计算样式兼容写法
    function _getCSS(obj,style){
        if(window.getComputedStyle){
            return getComputedStyle(obj)[style];
        }
        return obj.currentStyle[style];
    }
    复制代码
    复制代码
    //CSS获取与设置
    Mquery.prototype.css = function(attr,value){
      //如果是对象的形式,以对象的形式设置
      if(typeof attr == 'object'){
        for(var att in attr){
          for(var j = 0; j < this.elements.length; j++){
            this.elements[j].style[att] = attr[att];
          }
        }
      //如果不是对象的形式
      }else{
        //设置
        if(arguments.length == 2){
          for(var i = 0; i < this.elements.length; i++){
            this.elements[i].style[attr] = value;
          }
        //获取
        }else if(arguments.length == 1){
          return _getCSS(this.elements[0],attr)
        }
      }
      return this;
    }
    复制代码

    【attr】

      特性设置与获取的思路与CSS类似,只是方法变成了setAttribute()和getAttribute()

    复制代码
    //attr获取与设置
    Mquery.prototype.attr = function(attr,value){
      //如果是对象的形式
      if(typeof attr == 'object'){
        for(var att in attr){
          for(var j = 0; j < this.elements.length; j++){
            this.elements[j].setAttribute(att,attr[att]);
          }
        }
      //如果不是对象的形式
      }else{
        //设置
        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;
    }
    复制代码

    事件绑定

    【on】

      在jQuery中,最常用的事件绑定方法就是on方法。在on方法中要特别注意的是this的绑定,由于函数fn中的this实际上是window,所以应该将fn的this绑定到当前元素

    复制代码
    //事件绑定
    Mquery.prototype.on = function(eventType,fn){
      for(var i = 0; i < this.elements.length; i++){
        _addEvent(this.elements[i],eventType,fn.bind(this.elements[i));
      }
      return this;
    }
    复制代码

    【click和hover】

      click方法是一个简写方法

    Mquery.prototype.click = function(fn){
      this.on('click',fn);
      return this;
    }

      hover方法是mouseover和mouseout的合成方法

    Mquery.prototype.hover = function(fnOver,fnOut){
      this.on('mouseover',fnOver);
      this.on('mouseout',fnOut);
      return this;
    }

    【return false】

      在jQuery中,使用return false可以同时阻止默认行为和阻止冒泡

    复制代码
    //事件绑定兼容写法
    function _addEvent(target,type,handler){
        if(target.addEventListener){
            target.addEventListener(type,function(e){
              //如果事件函数中出现 return false;则阻止默认事件和阻止冒泡
              if(typeof handler == 'function' && handler() === false){
                e.preventDefault();
                e.cancelBubble = true;
              }
            },false);
        }else{
            target.attachEvent('on'+type,function(event){
              if(typeof handler == 'function' && handler() === false){
                event.cancelBubble = true;
                event.returnValue = false;
              }
                return handler.call(target,event);
            });
        }
    }
    复制代码

    其他设置

      jQuery的功能非常强大。下面选择一些常用功能进行实现

    【显示隐藏】

    复制代码
    //隐藏
    Mquery.prototype.hide = function(){
      for(var i = 0; i < this.elements.length; i++){
        //保存当前元素的display值
        this.elements[i].displayValue = this.elements[i].style.display;
        this.elements[i].style.display = 'none';
      }
      return this;
    }
    //显示
    Mquery.prototype.show = function(){
      for(var i = 0; i < this.elements.length; i++){
       this.elements[i].style.display = this.elements[i].displayValue;
       //删除保存的元素的display值
       delete this.elements[i].displayValue;
      }
      return this;
    }
    复制代码

    【插件设置】

    复制代码
    $.extend = function(json){ 
      for(var attr in json){
        $[attr] = json[attr];
      }
    };
    $.fn = {};
    $.fn.extend = function(json){
      for(var attr in json){
        Mquery.prototype[attr] = json[attr];
      } 
    };
    复制代码

    【索引设置】

    复制代码
    //根据索引选择元素
    Mquery.prototype.eq = function(number){
      return $(this.elements[number]);
    }
    
    //根据元素获取索引
    Mquery.prototype.index = function(){
      var elements = this.elements[0].parentNode.children;
      for(var i = 0; i < elements.length; i++){
        if(elements[i] === this.elements[0]){
          return i;
        }
      }
    }
    复制代码

    【子级筛选】

    复制代码
    //筛选出当前匹配的元素集合中每个元素的后代
    Mquery.prototype.find = function(str){
      var arr = [];
      for(var i = 0; i < this.elements.length; i++){
        Array.prototype.push.apply(arr,this.elements[i].querySelectorAll(str));
      }
      return $(arr);
    }
    复制代码

    完整源码

      下面是mQuery的完整源码

    复制代码
    //事件绑定兼容写法
    function _addEvent(target,type,handler){
        if(target.addEventListener){
            target.addEventListener(type,function(e){
              //如果事件函数中出现 return false;则阻止默认事件和阻止冒泡
              if(typeof handler == 'function' && handler() === false){
                e.preventDefault();
                e.cancelBubble = true;
              }
            },false);
        }else{
            target.attachEvent('on'+type,function(event){
              if(typeof handler == 'function' && handler() === false){
                event.cancelBubble = true;
                event.returnValue = false;
              }
                return handler.call(target,event);
            });
        }
    }
    //获取计算样式兼容写法
    function _getCSS(obj,style){
        if(window.getComputedStyle){
            return getComputedStyle(obj)[style];
        }
        return obj.currentStyle[style];
    }
    
    //将类数组转换成数组
    function _toArray(arrayLike){
      return Array.prototype.slice.call(arrayLike);
    }
    //构造函数
    function Mquery(arg){
      //保存所选择的元素
      this.elements = [];
      switch(typeof arg){
        //当参数是函数时,如$(function(){})(),直接运行里面的代码
        case 'function':
          _addEvent(window,'load',arg);
          break;
        //当参数是字符串时,选择元素
        case 'string':
          this.elements = _toArray(document.querySelectorAll(arg));              
          break;
        //当参数是DOM对象时,将DOM对象转换为$对象  
        case 'object':
          if(arg.constructor == Array){
            this.elements = arg;
          }else{
            this.elements.push(arg);
          }      
          break;
      }
    }
    //根据索引选择元素
    Mquery.prototype.eq = function(number){
      return $(this.elements[number]);
    }
    //根据元素获取索引
    Mquery.prototype.index = function(){
      var elements = this.elements[0].parentNode.children;
      for(var i = 0; i < elements.length; i++){
        if(elements[i] === this.elements[0]){
          return i;
        }
      }
    }
    //筛选出当前匹配的元素集合中每个元素的后代
    Mquery.prototype.find = function(str){
      var arr = [];
      for(var i = 0; i < this.elements.length; i++){
        Array.prototype.push.apply(arr,this.elements[i].querySelectorAll(str));
      }
      return $(arr);
    }
    //CSS获取与设置
    Mquery.prototype.css = function(attr,value){
      //如果是对象的形式,以对象的形式设置
      if(typeof attr == 'object'){
        for(var att in attr){
          for(var j = 0; j < this.elements.length; j++){
            this.elements[j].style[att] = attr[att];
          }
        }
      //如果不是对象的形式
      }else{
        //设置
        if(arguments.length == 2){
          for(var i = 0; i < this.elements.length; i++){
            this.elements[i].style[attr] = value;
          }
        //获取
        }else if(arguments.length == 1){
          return _getCSS(this.elements[0],attr)
        }
      }
      return this;
    }
    //attr获取与设置
    Mquery.prototype.attr = function(attr,value){
      //如果是对象的形式
      if(typeof attr == 'object'){
        for(var att in attr){
          for(var j = 0; j < this.elements.length; j++){
            this.elements[j].setAttribute(att,attr[att]);
          }
        }
      //如果不是对象的形式
      }else{
        //设置
        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;
    }
    //HTML获取与设置
    Mquery.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;
    }
    //隐藏
    Mquery.prototype.hide = function(){
      for(var i = 0; i < this.elements.length; i++){
        //保存当前元素的display值
        this.elements[i].displayValue = this.elements[i].style.display;
        this.elements[i].style.display = 'none';
      }
      return this;
    }
    //显示
    Mquery.prototype.show = function(){
      for(var i = 0; i < this.elements.length; i++){
       this.elements[i].style.display = this.elements[i].displayValue;
       //删除保存的元素的display值
       delete this.elements[i].displayValue;
      }
      return this;
    }
    //事件绑定
    Mquery.prototype.on = function(eventType,fn){
      for(var i = 0; i < this.elements.length; i++){
        _addEvent(this.elements[i],eventType,fn.bind(this.elements[i]));
      }
      return this;
    }
    //click简写
    Mquery.prototype.click = function(fn){
      this.on('click',fn);
      return this;
    }
    //鼠标移入移出
    Mquery.prototype.hover = function(fnOver,fnOut){
      this.on('mouseover',fnOver);
      this.on('mouseout',fnOut);
      return this;
    }
    $.extend = function(json){ 
      for(var attr in json){
        $[attr] = json[attr];
      }
    };
    $.fn = {};
    $.fn.extend = function(json){
      for(var attr in json){
        Mquery.prototype[attr] = json[attr];
      } 
    };
    function $(arg){
      return new Mquery(arg);
    } 
    复制代码

    实际应用

      下面使用mQuery来实现一个简单的效果

    复制代码
    <style>
    div { 60px; height:60px; margin:5px; float:left; }
    </style>
    <span id="result"></span>
    <div style=""></div>
    <div style=""></div>
    <div style=""></div>
    <div style=""></div>
    <script src="mQuery.js"></script>
    <script>
    $("div").click(function(){
     $("#result").html("背景颜色是 " + $(this).css("background-color"));
    })
    </script> 
    复制代码

      点击不同颜色的元素块,将在右侧显示具体的颜色值

      

    好的代码像粥一样,都是用时间熬出来的

  • 相关阅读:
    HDU4341 Gold miner 分组背包
    卡特兰数
    欧拉函数
    求一个阶乘数尾零的个数
    线性时间 筛素数,求前n个数的欧拉函数值,求前n个数的约数个数
    HDU4335 What is N? 欧拉函数,欧拉定理
    HDU4336 Card Collector 容斥定理 Or 概率DP
    ie8恶心的bug4个小时的教训
    39个超实用jQuery实例应用特效
    ECSHOP 模板结构说明
  • 原文地址:https://www.cnblogs.com/onesea/p/13202390.html
Copyright © 2011-2022 走看看