一、有這樣一段 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>
複製程式碼
(完)