JQuery source code parsing addClass (), removeClass (), toggleClass () and hasClass ()

Time:2019-8-13

First,$().addClass()
Effect:
Add one or more class names to the target element

Source code:

// Add one or more class names to the target element
    // Source 8401 lines
    addClass: function( value ) {
      var classes, elem, cur, curValue, clazz, j, finalValue,
        i = 0;
      // If the value of addClass (value) is a function
      // Then call the target element this to call the function
      if ( isFunction( value ) ) {
        return this.each( function( j ) {
          // function(index,currentclass)
          // index corresponds to j, and its function is to obtain subscripts of multiple target elements.
          // CurrtClass corresponds to getClass (this). Its purpose is to get the class name of the current element and add spaces easily.
          jQuery( this ).addClass( value.call( this, j, getClass( this ) ) );
        } );
      }
      // Convert (multiple) class names to array form
      classes = classesToArray( value );
      if ( classes.length ) {
        // Multiple target elements
        while ( ( elem = this[ i++ ] ) ) {
          // Get the current value
          curValue = getClass( elem );
          // If the target element is an element node, wrap "+value+" around the space.
          cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );

          if ( cur ) {
            j = 0;
            // One class name after another
            while ( ( clazz = classes[ j++ ] ) ) {
              // If the current element does not repeat the class name to be added, add it
              if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
                cur += clazz + " ";
              }
            }
            // Finally, confirm whether the processed set of class names is the same as the pre-processed set of class names.
            // If the same, set Attribute, re-render, otherwise no re-rendering (performance optimization)
            // Only assign if different to avoid unneeded rendering.
            finalValue = stripAndCollapse( cur );
            if ( curValue !== finalValue ) {
              // Finally, add the class name through setAttribute
              elem.setAttribute( "class", finalValue );
            }
          }
        }
      }
      return this;
    },

Analysis:
(1)getClass()
Effect:
Get the class name of the target element

Source code:

// Source code 8377 lines
  function getClass( elem ) {
    return elem.getAttribute && elem.getAttribute( "class" ) || "";
  }

(2)classesToArray
Effect:
Convert (multiple) class names to array form

Source code:

// Source code 8382 lines
  function classesToArray( value ) {
    // The element's className, if it has more than one class name, is saved as an array, and is returned directly.
    if ( Array.isArray( value ) ) {
      return value;
    }
    // If the element class name is string type
    if ( typeof value === "string" ) {
      return value.match( rnothtmlwhite ) || [];
    }
    return [];
  }

(3)stripAndCollapse
Effect:
Separate vaues with spaces and then stitch them together with spaces

Source code:

// Source code 8370 lines
  // Strip and collapse whitespace according to HTML spec
  // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace
  function stripAndCollapse( value ) {
    var tokens = value.match( rnothtmlwhite ) || [];
    return tokens.join( " " );
  }

To sum up:
You can see that the idea of addClass () is:
(1) Get the current set of class names of elements a
(2) If the class name B to be added does not repeat, add B to a
(3) Final useelem.setAttribute("class",a)complete

Two.$().removeClass
Effect:
Remove the class, if there are no parameters, remove all class names of the target element

Source code:

// Source 8449 lines
    removeClass: function( value ) {
      var classes, elem, cur, curValue, clazz, j, finalValue,
        i = 0;
      // Ibid.
      if ( isFunction( value ) ) {
        return this.each( function( j ) {
          jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );
        } );
      }
      // If no parameters are specified, all classes are deleted
      if ( !arguments.length ) {
        return this.attr( "class", "" );
      }
      // Convert (multiple) class names to array form
      classes = classesToArray( value );

      if ( classes.length ) {
        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++ ] ) ) {
              // If there are classes to be removed from the class name of the current element,
              // Replace this class with ""
              // Remove *all* instances
              while ( cur.indexOf( " " + clazz + " " ) > -1 ) {
                cur = cur.replace( " " + clazz + " ", " " );
              }
            }
            // Ibid.
            // Only assign if different to avoid unneeded rendering.
            finalValue = stripAndCollapse( cur );
            if ( curValue !== finalValue ) {
              elem.setAttribute( "class", finalValue );
            }
          }
        }
      }
      return this;
    },

You can see that the idea of addClass () is:
(1) Get the current set of class names of elements a
(2) If the class name B to be removed does not repeat, replace the B in a with the space “.”
(3) Final useelem.setAttribute("class",a)Complete removing class names

Three.$().toggleClass
Effect:
Switching class

Source code:

// If stateVal is true, classes are added and classes are removed by false.
    // Source 8497 lines
    toggleClass: function( value, stateVal ) {
      var type = typeof value,
        // If value is string type or array type, it is true and vice versa false
        isValidValue = type === "string" || Array.isArray( value );
      // true adds classes, false removes classes
      if ( typeof stateVal === "boolean" && isValidValue ) {
        return stateVal ? this.addClass( value ) : this.removeClass( value );
      }
      // Ibid.
      if ( 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 ( isValidValue ) {

          // Toggle individual class names
          i = 0;
          self = jQuery( this );
          classNames = classesToArray( value );

          while ( ( className = classNames[ i++ ] ) ) {
            // If the target element already has a className for toggle, remove it
            // Check each className given, space separated list
            if ( self.hasClass( className ) ) {
              self.removeClass( className );
            } else {
              // Otherwise, add classes
              self.addClass( className );
            }
          }

          // Toggle whole class name
        }
        // If $. toggleClass () has no value or the value is Boolean
        else if ( value === undefined || type === "boolean" ) {
          className = getClass( this );
          // If the target element has a class, save the class name first with the _className_ attribute
          if ( className ) {

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

          // If the element has a class name or if we're passed `false`,
          // then remove the whole classname (if there was one, the above saved it).
          // Otherwise bring back whatever was previously saved (if anything),
          // falling back to the empty string if nothing was stored.
          // If there is a setAttribute method for the target element
          if ( this.setAttribute ) {
            // If the class name / value = false already exists, remove all class names
            // If there is no class name and value = true,
            // Retrieve the previously saved _className_ as the class name of the target element from dataPriv
            this.setAttribute( "class",
              className || value === false ?
                "" :
                dataPriv.get( this, "__className__" ) || ""
            );
          }
        }
      } );
    },

Analysis:
Mainly two if
(1) if ( typeof stateVal === “boolean” && isValidValue )
Here it is.$()The function of the second parameter of the toggleClass (value, truefalse)
True is addClass (), false is removeClass ()

(2)if(isValidValue )
This is the case where there is only one parameter.
Use hasClass to determine whether to add/remove Class

(3) If $. toggleClass () has no value or the first value is true
If the target element has a class name, usedataPrivTo save the class name,
If the target element hassetAttributeIf so, set the className todataPrivValues saved in.

Four.$().hasClass
Effect:
Check whether the target element contains the specified class

Source code:

// Source code 8568 lines
    hasClass: function( selector ) {
      var className, elem,
        i = 0;

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

      return false;
    }

This code is quite simple, so it won’t be parsed.


(End)

Recommended Today

Docker learning (5) basic command of dockerfile

To learn dockerfile, you need to understand its basic commands From – base image Try to use the official reference image [x] From Tomcat: 8.5.50-jdk8-openjdk 񖓿 make reference image (based on Tomcat: 8.5.50-jdk8-openjdk) [x] From CentOS ා make a base image based on CentOS: latest [x] From scratch? Does not depend on any reference image […]