美文网首页
jQuery之html()的实现

jQuery之html()的实现

作者: 小进进不将就 | 来源:发表于2019-04-02 18:13 被阅读0次

    一、有这样一段 html

    <div class="divOne">
      <p>嘿嘿嘿</p>
    </div>
    <div class="divOne">
      <p>哈哈哈</p>
    </div>
    

    二、jQuery 的 html() 方法
    (1)当直接调用 $().html()时,.html()的作用是只读取第一个目标元素的innerHTML

    简单实现:

      function customHtml(value) {
        //默认是选取第一个目标元素
        let elem = this[0] || {},
          i = 0,
          l = this.length;
        //如果是html(),即使读取目标元素的innerHTML的话
        if (value === undefined && elem.nodeType === 1) {
          return elem.innerHTML;
        }
        //xxx
        //xxx
      }
    

    (2)当调用$().html(value)时,.html()的作用是为每一个符合条件的目标元素的innerHTML设置为 value

    简单实现:

      function customHtml(value) {
        //默认是选取第一个目标元素
        let elem = this[0] || {},
          i = 0,
          l = this.length;
        //如果是html(),即使读取目标元素的innerHTML的话
        if (value === undefined && elem.nodeType === 1) {
          return elem.innerHTML;
        }
        //根据目标元素的个数,依次对符合条件的目标元素赋值
        for (; i < l; i++) {
          elem = this[i] || {};
          if (elem.nodeType === 1) {
            elem.innerHTML = value;
          }
        }
      }
    

    (3)源码实现
    源码:

      // html()方法设置或返回被选元素的内容(innerHTML)
      // 当该方法用于返回内容时,则返回第一个匹配元素的内容
      // 当该方法用于设置内容时,则重写所有匹配元素的内容
      // http://www.runoob.com/jquery/html-html.html
      // 源码6203行左右
      function html( value ) {
        //调用$().html()方法,即调用access()方法
        //关于access()方法的讲解,请看:https://www.cnblogs.com/gongshunkai/p/5905917.html
        //access(this,function(),null,value,arguments.length)
        return jQuery.access( this, function( value ) {
          //读的话(.html())只读第一个匹配的目标元素的内容所以是this[0]
          //写的话(.html(xxx))会循环每个匹配的目标并将其innerHTML置为value
          var elem = this[ 0 ] || {},
            i = 0,
            l = this.length;
          //当直接调用html(),并且目标元素是元素节点时,$().html()的本质是 selector.innerHTML
          if ( value === undefined && elem.nodeType === 1 ) {
            return elem.innerHTML;
          }
    
          // See if we can take a shortcut and just use innerHTML
          //如果能直接使用innerHTML来解析的话
          //注意:IE的innerHTML会忽略开头的无作用域元素
          if ( typeof value === "string" &&
            !rnoInnerhtml.test( value ) &&
            !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
            //Hello <b>world</b>!
            value = jQuery.htmlPrefilter( value );
            console.log(value,'value6235')
            try {
              for ( ; i < l; i++ ) {
                elem = this[ i ] || {};
    
                // Remove element nodes and prevent memory leaks
    
                if ( elem.nodeType === 1 ) {
                  console.log(3333,'node6261')
                  // getAll( elem, false ):获取原本selector内部的内容(标签)
                  //先移除元素节点和注册的事件以防止内存泄漏
                  jQuery.cleanData( getAll( elem, false ) );
    
                  elem.innerHTML = value;
                }
              }
              //将elem置为0,是防止执行下面的if(elem)...
              elem = 0;
    
              // If using innerHTML throws an exception, use the fallback method
            } catch ( e ) {}
          }
    
          if ( elem ) {
            this.empty().append( value )
          }
        }, null, value, arguments.length )
      }
    

    源码解析:
    ① 调用html(),实际上是调用access()
    access部分源码:

      //$().html():access(this,function(),null,value,arguments.length)
      //源码4051行
      //关于access()方法的讲解,请看:https://www.cnblogs.com/gongshunkai/p/5905917.html
      var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
        var i = 0,
          //1
          len = elems.length,
          //true
          bulk = key == null;
    
        // Sets many values
        if ( toType( key ) === "object" ) {
            //xxx
        } else if ( value !== undefined ) {
          console.log('access->value!==undefined','value4053')
          chainable = true;
          //xxx
          if ( bulk ) {
            // Bulk operations run against the entire set
            //走这边
            if ( raw ) {
              // 将elems/selector,value传入function并执行
              // call(this,param)
              fn.call( elems, value );
              //这里将 function 置为空值后,就不会执行 if(fn)...了
              fn = null;
              // ...except when executing function values
            }
            //不走这边
            else {
              bulk = fn;
              fn = function( elem, key, value ) {
                return bulk.call( jQuery( elem ), value );
              };
            }
          }
        //xxx
        //xxx
        //xxx
      };
    

    也就是说:调用jQuery.access()相当于调用了fn.call( elems, value ),即自定义的方法jQuery.access(this, function(value) {xxx})

    .html()的情况调用这部分源码:

          if ( value === undefined && elem.nodeType === 1 ) {
            return elem.innerHTML;
          }
    

    .html("字符串")/.html("<p>这也是字符串</p>")的情况调用这部分源码:

            // See if we can take a shortcut and just use innerHTML
            //如果能直接使用innerHTML来解析的话
            //注意:IE的innerHTML会忽略开头的无作用域元素
            if ( typeof value === "string" && 
              !rnoInnerhtml.test( value ) &&
              !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
              //Hello <b>world</b>!
              value = jQuery.htmlPrefilter( value );
              console.log(value,'value6235')
              try {
                for ( ; i < l; i++ ) {
                  elem = this[ i ] || {};
                  // Remove element nodes and prevent memory leaks
                  if ( elem.nodeType === 1 ) {
                    console.log(3333,'node6261')
                    // getAll( elem, false ):获取原本selector内部的内容(标签)
                    //先移除元素节点和注册的事件以防止内存泄漏
                    jQuery.cleanData( getAll( elem, false ) );
                    elem.innerHTML = value;
                  }
                }
                //将elem置为0,是防止执行下面的if(elem)...
                elem = 0;
                // If using innerHTML throws an exception, use the fallback method
              } catch ( e ) {}
            }
    

    .html(这里面是标签)的情况调用这部分源码:
    标签:

      let p=document.createElement('p')
      p.innerText='哈哈哈'
      $(".divOne").html(p)
    

    源码:

          if ( elem ) {
            this.empty().append( value );
          }
    

    ⑤ 总结
    $(".divOne").html()本质$(".divOne")[0].innerHTML

    $(".divOne").html("Hello <b>world</b>!")本质$(".divOne")[i].innerHTML="Hello <b>world</b>!"

    $(".divOne").html(标签)本质$(".divOne").empty().append(标签)

    源码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>jQuery之html()</title>
    </head>
    <body>
    <script src="jQuery.js"></script>
    <div class="divOne">
      <p>嘿嘿嘿</p>
    </div>
    <div class="divOne">
      <p>嘿嘿嘿</p>
    </div>
    <input type="text" id="inputOne">
    <script>
      function customHtml(value) {
        //默认是选取第一个目标元素
        let elem = this[0] || {},
          i = 0,
          l = this.length;
        //如果是html(),即使读取目标元素的innerHTML的话
        if (value === undefined && elem.nodeType === 1) {
          return elem.innerHTML;
        }
        //根据目标元素的个数,依次对符合条件的目标元素赋值
        for (; i < l; i++) {
          elem = this[i] || {};
          if (elem.nodeType === 1) {
            elem.innerHTML = value;
          }
        }
      }
      // html()方法设置或返回被选元素的内容(innerHTML)
      // 当该方法用于返回内容时,则返回第一个匹配元素的内容
      // 当该方法用于设置内容时,则重写所有匹配元素的内容
      // http://www.runoob.com/jquery/html-html.html
      // 源码6203行左右
      function html( value ) {
        //调用$().html()方法,即调用access()方法
        //关于access()方法的讲解,请看:https://www.cnblogs.com/gongshunkai/p/5905917.html
        //access(this,function(),null,value,arguments.length)
        return jQuery.access( this, function( value ) {
          //读的话(.html())只读第一个匹配的目标元素的内容所以是this[0]
          //写的话(.html(xxx))会循环每个匹配的目标并将其innerHTML置为value
          var elem = this[ 0 ] || {},
            i = 0,
            l = this.length;
          //当直接调用html(),并且目标元素是元素节点时,$().html()的本质是 selector.innerHTML
          if ( value === undefined && elem.nodeType === 1 ) {
            return elem.innerHTML;
          }
    
          // See if we can take a shortcut and just use innerHTML
          //如果能直接使用innerHTML来解析的话
          //注意:IE的innerHTML会忽略开头的无作用域元素
          if ( typeof value === "string" &&
            !rnoInnerhtml.test( value ) &&
            !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
            //Hello <b>world</b>!
            value = jQuery.htmlPrefilter( value );
            console.log(value,'value6235')
            try {
              for ( ; i < l; i++ ) {
                elem = this[ i ] || {};
    
                // Remove element nodes and prevent memory leaks
    
                if ( elem.nodeType === 1 ) {
                  console.log(3333,'node6261')
                  // getAll( elem, false ):获取原本selector内部的内容(标签)
                  //先移除元素节点和注册的事件以防止内存泄漏
                  jQuery.cleanData( getAll( elem, false ) );
    
                  elem.innerHTML = value;
                }
              }
              //将elem置为0,是防止执行下面的if(elem)...
              elem = 0;
    
              // If using innerHTML throws an exception, use the fallback method
            } catch ( e ) {}
          }
    
          if ( elem ) {
            this.empty().append( value );
          }
        }, null, value, arguments.length );
      }
    
    
      customHtml.call(document.querySelectorAll(".divOne"))
      customHtml.call(document.querySelectorAll(".divOne"),"Hello <b>world</b>!")
      // console.log($(".divOne").html())
      // $(".divOne").html("Hello <b>world</b>!")
      // let p=document.createElement('p')
      // p.innerText='哈哈哈gggg'
      // $(".divOne").html(p)
      // console.log(p,'p19')
      // $("#divOne").text('<p>aaaa</p>')
      // $("#divOne").text(p)
    
    </script>
    </body>
    </html>
    

    (完)

    相关文章

      网友评论

          本文标题:jQuery之html()的实现

          本文链接:https://www.haomeiwen.com/subject/kocwbqtx.html