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="background-color:blue;"></div>
    <div style="background-color:rgb(15,99,30);"></div>
    <div style="background-color:#123456;"></div>
    <div style="background-color:#f11;"></div>
    <script src="mQuery.js"></script>
    <script>
    $("div").click(function(){
     $("#result").html("背景颜色是 " + $(this).css("background-color"));
    })
    </script> 

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

      

  • 相关阅读:
    LeetCode Missing Number (简单题)
    LeetCode Valid Anagram (简单题)
    LeetCode Single Number III (xor)
    LeetCode Best Time to Buy and Sell Stock II (简单题)
    LeetCode Move Zeroes (简单题)
    LeetCode Add Digits (规律题)
    DependencyProperty深入浅出
    SQL Server存储机制二
    WPF自定义RoutedEvent事件示例代码
    ViewModel命令ICommand对象定义
  • 原文地址:https://www.cnblogs.com/xiaohuochai/p/7526278.html
Copyright © 2011-2022 走看看