成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

jQuery 源碼系列(十八)class 相關(guān)操作

BingqiChen / 2949人閱讀

摘要:眼看的源碼就快到頭了,后面還有幾個重要的內(nèi)容,包括和動畫操作,加油把它們看完,百度前端學(xué)院的新一批課程也開始了。,當(dāng)?shù)诙€參數(shù)為的情況,就是,為時,,從源碼來看,就是直接調(diào)用的這兩個函數(shù)。參考源碼分析樣式操作本文在上的源碼地址,歡迎來。

歡迎來我的專欄查看系列文章。

眼看 jQuery 的源碼就快到頭了,后面還有幾個重要的內(nèi)容,包括 ajax 和動畫操作,加油把它們看完,百度前端學(xué)院的新一批課程也開始了。百度前端學(xué)院。

class 的的操作應(yīng)該算是比較愉快的,因為內(nèi)容不是很多,或者說,內(nèi)容涉及到的原生操作不是很大,就一個 className 或 getAttribute,主要還是來看下它涉及到的一些兼容性操作。

class 操作

先來說一個比較有趣的 class 操作,先把鏈接貼上。

js 有一個非常大的缺陷,就是無法控制偽元素的樣式,比如 after 和 before,這樣子會失去很多樂趣(同樣也帶來了很多樂趣)。上面的鏈接是 stackoverflow 的解答。

1. class 方式

通過事先定義 class 的方式來解決:

p:before {
  content: "c1"
}
p.click:before {
  content: "click"
}

// js
$("p").on("click", function(){
  $(this).toggleClass("click");
})

2. 內(nèi)聯(lián) style 方式

這種方式不優(yōu)雅,也是一種解決辦法。

var str = "click";
$("").appendTo("head");

3. jQuery data-attr 來解決

這種方式是依靠 content 的特性:

p:before {
  content: attr(data-click);
}

//js
var str = "click";
$("p").on("click", function(){
  $(this).attr("data-click", str);
})

這種方式應(yīng)該是動態(tài)改變。

jQuery 的應(yīng)用還是挺廣泛的。

fn.hasClass

jQuery 中的 class 操作還是很有意思,會用到很多正則表達式,我超喜歡正則表達式的。

如果讓我用原生的 js 來實現(xiàn) class 操作,我會想到兩種方式,一種是 className,它的兼容性非常好,所有瀏覽器都支持,包括 mobile。第二個是 getAttribute,也是所有瀏覽器都支持(有版本限制)。

先從 hasClass 說起吧:

// 獲取 class-name
function getClass( elem ) {
  return elem.getAttribute && elem.getAttribute( "class" ) || "";
}

// 將 class name 進行處理
function stripAndCollapse( value ) {
  var tokens = value.match( /[^x20	
f]+/g ) || [];
  return tokens.join( " " );
}

jQuery.fn.extend( {
  hasClass: function( selector ) {
    var className, elem,
      i = 0;

    className = " " + selector + " ";
    while ( ( elem = this[ i++ ] ) ) {
      if ( elem.nodeType === 1 &&
        ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) {
          return true;
      }
    }

    return false;
  }
} );

可以看出 getClass 函數(shù)使用的是 getAttribute 方法。

fn.addClass

接下來看一下添加 add:

jQuery.fn.extend( {
  addClass: function( value ) {
    var classes, elem, cur, curValue, clazz, j, finalValue,
      i = 0;
    // 參數(shù)為函數(shù)...
    if ( jQuery.isFunction( value ) ) {
      return this.each( function( j ) {
        jQuery( this ).addClass( value.call( this, j, getClass( this ) ) );
      } );
    }

    if ( typeof value === "string" && value ) {
      // 可以添加多個 class
      classes = value.match( /[^x20	
f]+/g ) || [];

      while ( ( elem = this[ i++ ] ) ) {
        curValue = getClass( elem );
        cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );

        if ( cur ) {
          j = 0;
          while ( ( clazz = classes[ j++ ] ) ) {
            if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
              cur += clazz + " ";
            }
          }

          // 在這里 set class,有個 diff 判斷
          finalValue = stripAndCollapse( cur ); // 去除兩側(cè)空格
          if ( curValue !== finalValue ) {
            elem.setAttribute( "class", finalValue );
          }
        }
      }
    }

    return this;
  }
} );

jQuery 大致處理的思路是這樣的:先把當(dāng)前 elem 中的 class 取出來 cur,要添加的 value 如果在 cur 中 indexOf 的值顯示不存在,就在 cur 后面加上 value。

fn.removeClass

刪除可能要麻煩一點點:

jQuery.fn.extend( {
  removeClass: function( value ) {
    var classes, elem, cur, curValue, clazz, j, finalValue,
      i = 0;
    // 不知道在哪里用到 value 為 function 情況
    if ( jQuery.isFunction( value ) ) {
      return this.each( function( j ) {
        jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );
      } );
    }
    // 無參數(shù)表示 移除所有的 class ...
    if ( !arguments.length ) {
      return this.attr( "class", "" );
    }

    if ( typeof value === "string" && value ) {
      classes = value.match( rnothtmlwhite ) || [];

      while ( ( elem = this[ i++ ] ) ) {
        curValue = getClass( elem );

        // This expression is here for better compressibility (see addClass)
        cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );

        if ( cur ) {
          j = 0;
          while ( ( clazz = classes[ j++ ] ) ) {

            // 移除所有需要移除的 class
            while ( cur.indexOf( " " + clazz + " " ) > -1 ) {
              cur = cur.replace( " " + clazz + " ", " " );
            }
          }

          // Only assign if different to avoid unneeded rendering.
          finalValue = stripAndCollapse( cur );
          if ( curValue !== finalValue ) {
            elem.setAttribute( "class", finalValue );
          }
        }
      }
    }

    return this;
  }
} );

可以看出 remove 的操作基本上和 add 一樣,只不過處理 class 的時候略有不同:

// 這里用 while,是有技巧的
while ( cur.indexOf( " " + clazz + " " ) > -1 ) {
  cur = cur.replace( " " + clazz + " ", " " );
}

用 replace 替換匹配的 clazz 為空格。

fn.toggleClass

toggleClass 使用的頻率也比較高。

先來看看大致用法,你肯定會忽略它的第二個參數(shù)的意思。.toggleClass(),當(dāng)?shù)诙€參數(shù)為 true 的情況,就是 addClass,為 false 時,removeClass,從源碼來看,就是直接調(diào)用的這兩個函數(shù)。

除了兩個參數(shù),還有無參和只有 false 情況,下面也都有明確的處理辦法。

jQuery.fn.extend( {
toggleClass: function( value, stateVal ) {
    var type = typeof value;

    // 第二個參數(shù)為 boolean
    if ( typeof stateVal === "boolean" && type === "string" ) {
      return stateVal ? this.addClass( value ) : this.removeClass( value );
    }

    if ( jQuery.isFunction( value ) ) {
      return this.each( function( i ) {
        jQuery( this ).toggleClass(
          value.call( this, i, getClass( this ), stateVal ),
          stateVal
        );
      } );
    }

    return this.each( function() {
      var className, i, self, classNames;

      if ( type === "string" ) {

        // Toggle individual class names
        i = 0;
        self = jQuery( this );
        classNames = value.match( rnothtmlwhite ) || [];

        while ( ( className = classNames[ i++ ] ) ) {

          // 有則刪,無則加,邏輯很簡單
          if ( self.hasClass( className ) ) {
            self.removeClass( className );
          } else {
            self.addClass( className );
          }
        }

      // 當(dāng)無參或只有一個 false 時,所有 class 都執(zhí)行
      } else if ( value === undefined || type === "boolean" ) {
        className = getClass( this );
        if ( className ) {

          // Store className if set
          dataPriv.set( this, "__className__", className );
        }

        if ( this.setAttribute ) {
          this.setAttribute( "class",
            className || value === false ?
            "" :
            dataPriv.get( this, "__className__" ) || ""
          );
        }
      }
    } );
  }
} );

看得出來,這個邏輯和前面兩個很像,不過當(dāng)無參或只有一個 boolean 且 false 時,先將當(dāng)前的 className 保存到 data cache 中,然后實現(xiàn) toggle 操作:

if ( this.setAttribute ) {
  this.setAttribute( "class",
    className || value === false ? // 判斷條件
    "" : // 有則設(shè)空
    dataPriv.get( this, "__className__" ) || "" // 無則從 data cache 取
  );
}
總結(jié)

感覺 jQuery 中的 class 操作不是很復(fù)雜,難道是我在進步嗎,哈哈。

參考

jQuery 2.0.3 源碼分析 樣式操作
Selecting and manipulating CSS ..
.toggleClass()

本文在 github 上的源碼地址,歡迎來 star。

歡迎來我的博客交流。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/86827.html

相關(guān)文章

  • dubbo源碼解析(四十八)異步化改造

    摘要:大揭秘異步化改造目標(biāo)從源碼的角度分析的新特性中對于異步化的改造原理??丛创a解析四十六消費端發(fā)送請求過程講到的十四的,在以前的邏輯會直接在方法中根據(jù)配置區(qū)分同步異步單向調(diào)用。改為關(guān)于可以參考源碼解析十遠(yuǎn)程通信層的六。 2.7大揭秘——異步化改造 目標(biāo):從源碼的角度分析2.7的新特性中對于異步化的改造原理。 前言 dubbo中提供了很多類型的協(xié)議,關(guān)于協(xié)議的系列可以查看下面的文章: du...

    lijinke666 評論0 收藏0
  • dubbo源碼解析(二十八)遠(yuǎn)程調(diào)用——memcached協(xié)議

    摘要:源碼分析一該類繼承,是協(xié)議實現(xiàn)的核心。屬性默認(rèn)端口號不支持服務(wù)暴露可以看到,服務(wù)暴露方法直接拋出異常。后記該部分相關(guān)的源碼解析地址該文章講解了遠(yuǎn)程調(diào)用中關(guān)于協(xié)議實現(xiàn)的部分,邏輯比較簡單。 遠(yuǎn)程調(diào)用——memcached協(xié)議 目標(biāo):介紹memcached協(xié)議的設(shè)計和實現(xiàn),介紹dubbo-rpc-memcached的源碼。 前言 dubbo實現(xiàn)memcached協(xié)議是基于Memcached...

    Faremax 評論0 收藏0
  • 第二十八章:SpringBoot使用AutoConfiguration自定義Starter

    摘要:代碼如下所示自定義業(yè)務(wù)實現(xiàn)恒宇少年碼云消息內(nèi)容是否顯示消息內(nèi)容,我們內(nèi)的代碼比較簡單,根據(jù)屬性參數(shù)進行返回格式化后的字符串。 在我們學(xué)習(xí)SpringBoot時都已經(jīng)了解到starter是SpringBoot的核心組成部分,SpringBoot為我們提供了盡可能完善的封裝,提供了一系列的自動化配置的starter插件,我們在使用spring-boot-starter-web時只需要在po...

    fasss 評論0 收藏0
  • JavaScript專題系列文章

    摘要:專題系列共計篇,主要研究日常開發(fā)中一些功能點的實現(xiàn),比如防抖節(jié)流去重類型判斷拷貝最值扁平柯里遞歸亂序排序等,特點是研究專題之函數(shù)組合專題系列第十六篇,講解函數(shù)組合,并且使用柯里化和函數(shù)組合實現(xiàn)模式需求我們需要寫一個函數(shù),輸入,返回。 JavaScript 專題之從零實現(xiàn) jQuery 的 extend JavaScritp 專題系列第七篇,講解如何從零實現(xiàn)一個 jQuery 的 ext...

    Maxiye 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<