一、有这样一段 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>(完)