前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >jQuery之html()的实现

jQuery之html()的实现

作者头像
进击的小进进
发布2022-03-28 14:48:12
1.4K0
发布2022-03-28 14:48:12
举报

一、有这样一段 html

代码语言:javascript
复制
<div class="divOne">
  <p>嘿嘿嘿</p>
</div>
<div class="divOne">
  <p>哈哈哈</p>
</div>

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

简单实现:

代码语言:javascript
复制
  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

简单实现:

代码语言:javascript
复制
  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)源码实现 源码:

代码语言:javascript
复制
  // 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部分源码:

代码语言:javascript
复制
  //$().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()的情况调用这部分源码:

代码语言:javascript
复制
      if ( value === undefined && elem.nodeType === 1 ) {
        return elem.innerHTML;
      }

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

代码语言:javascript
复制
        // 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(这里面是标签)的情况调用这部分源码: 标签:

代码语言:javascript
复制
  let p=document.createElement('p')
  p.innerText='哈哈哈'
  $(".divOne").html(p)

源码:

代码语言:javascript
复制
      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(标签)

源码:

代码语言:javascript
复制
<!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>
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-04-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 webchen 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档