一、有這樣一段 html
<div class="divOne">
<p>嘿嘿嘿</p>
</div>
<div class="divOne">
<p>哈哈哈</p>
</div>
複製程式碼
二、jQuery 的 text() 方法
(1)當直接呼叫 $().text()
時,.text()
的作用是(迴圈)讀取(多個)目標元素的textContent/nodeValue
簡單實現:
function readText(elem) {
let node,
ret = "",
i = 0,
nodeType = elem.nodeType
console.log(nodeType,'nodeType22')
//如果selector是類的話,會有多個目標元素,此時需要分別單個迴圈
//比如document.querySelectorAll('.divOne').nodeType ->undefined
if (!nodeType) {
while ((node = elem[i++])) {
//單個獲取
ret += readText(node)
}
}
//元素節點,文件節點,文件碎片
else if (nodeType === 1 || nodeType === 9 || nodeType === 11) {
//如果目標元素的內容是文字,則直接返回
if (typeof elem.textContent === "string") {
/*jQuery沒有用innerText獲取文字的值,http://bugs.jquery.com/ticket/11153,
大概就是在IE8中新節點插入會保留所有回車。
所以jQuery採用了textContent獲取文字值,
textContent本身是dom3規範的,可以相容火狐下的innerText問題。*/
return elem.textContent
}
//如果節點內容不是文字,則迴圈子節點,並依次獲取它們的文字節點
else {
for (elem = elem.firstChild; elem; elem = elem.nextSibling) {
ret += readText(elem)
}
}
}
//文字節點、一個文件的CDATA部分(沒遇到過這個)
else if (nodeType === 3 || nodeType === 4) {
//返回節點值
return elem.nodeValue;
}
//nodeType:註釋節點 8,處理指令 7
//text()方法不處理這兩個型別節點
return ret
}
複製程式碼
(2)當呼叫$().text(value)
時,.text(value)
的作用是為每一個符合條件的目標元素的textContent
設定為 value
簡單實現:
writeText():
function writeText(value) {
let elem,
i = 0;
//先清空目標元素的內容
customEmpty.call(this)
//迴圈
for (; (elem = this[i]) != null; i++) {
//元素節點,文件碎片,文件節點
if (elem.nodeType === 1 || elem.nodeType === 11 || elem.nodeType === 9) {
// text()方法不會解析標籤
elem.textContent = value;
}
}
//return this 方便鏈式呼叫
return this
}
複製程式碼
customEmpty():
function customEmpty() {
let elem,
i = 0;
//注意for迴圈的寫法
for (; (elem = this[i]) != null; i++) {
//如果是元素節點的話,清空該節點的所有內容
if (elem.nodeType === 1) {
elem.textContent = "";
}
}
return this;
}
複製程式碼
(3)原始碼實現
原始碼:
jQuery.text()總體:
//原始碼6152行
text: function( value ) {
return access( this, function( value ) {
return value === undefined ?
//讀
//如果直接呼叫text()的話,就呼叫Sizzle.getText
jQuery.text( this ) :
//寫
//迴圈
this.empty().each( function() {
//先清空目標元素的內容,然後再賦值
if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
console.log(value,'value6159')
//如果包含標籤的話,需要用html()方法,text()方法不會解析標籤
/*jQuery沒有用innerText獲取文字的值,http://bugs.jquery.com/ticket/11153,
大概就是在IE8中新節點插入會保留所有回車。
所以jQuery採用了textContent獲取文字值,
textContent本身是dom3規範的,可以相容火狐下的innerText問題。*/
this.textContent = value;
}
} )
}, null, value, arguments.length );
},
複製程式碼
原始碼解析:
① 呼叫text()
,實際上是呼叫access()
access
部分原始碼見:www.jianshu.com/p/645b3b446…
也就是說:呼叫jQuery.access()
相當於呼叫了fn.call( elems, value )
,即自定義的方法jQuery.access(this, function(value) {xxx})
② .text()
的情況呼叫這部分原始碼:
jQuery.text()呼叫的其實是Sizzle.getText():
//原始碼2833行
jQuery.text = Sizzle.getText;
複製程式碼
Sizzle.getText():
//原始碼1642行
getText = Sizzle.getText = function( elem ) {
var node,
ret = "",
i = 0,
nodeType = elem.nodeType;
if ( !nodeType ) {
while ( (node = elem[i++]) ) {
// Do not traverse comment nodes
ret += getText( node );
}
}
//元素節點、文件節點、文件碎片
else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
// Use textContent for elements
// innerText usage removed for consistency of new lines (jQuery #11153)
//如果目標元素的子節點是文字節點,則直接返回它的textContent
if ( typeof elem.textContent === "string" ) {
/*jQuery沒有用innerText獲取文字的值,http://bugs.jquery.com/ticket/11153,
大概就是在IE8中新節點插入會保留所有回車。
所以jQuery採用了textContent獲取文字值,
textContent本身是dom3規範的,可以相容火狐下的innerText問題。*/
return elem.textContent;
}
//如果子節點不是文字節點,則迴圈子節點,並依次獲取它們的文字節點
else {
// Traverse its children
for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
ret += getText( elem );
}
}
}
//文字節點、一個文件的CDATA部分(沒遇到過這個)
else if ( nodeType === 3 || nodeType === 4 ) {
return elem.nodeValue;
}
// Do not include comment or processing instruction nodes
return ret;
};
複製程式碼
③ .text(value)
的情況呼叫這部分原始碼:
jQuery.text(value):
//寫
//迴圈
this.empty().each( function() {
//先清空目標元素的內容,然後再賦值
if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
console.log(value,'value6159')
//如果包含標籤的話,需要用html()方法,text()方法不會解析標籤
/*jQuery沒有用innerText獲取文字的值,http://bugs.jquery.com/ticket/11153,
大概就是在IE8中新節點插入會保留所有回車。
所以jQuery採用了textContent獲取文字值,
textContent本身是dom3規範的,可以相容火狐下的innerText問題。*/
this.textContent = value;
}
} )
複製程式碼
empty():
//原始碼6231行
empty: function() {
var elem,
i = 0;
for ( ; ( elem = this[ i ] ) != null; i++ ) {
//如果是元素節點的話
if ( elem.nodeType === 1 ) {
// Prevent memory leaks
//清空內容和事件,防止記憶體洩漏
jQuery.cleanData( getAll( elem, false ) );
// Remove any remaining nodes
//清空節點所有內容
elem.textContent = "";
}
}
return this;
},
複製程式碼
④ 總結
$(".divOne").text()
的本質:
(1)節點內容是文字,返回**$(".divOne")[i].textContent
**
(2)節點內容不是文字,迴圈返回**$(".divOne")[i].element[j].textContent
**
(3)節點內容是文字節點或一個文件的CDATA部分,則返回**$(".divOne")[i]. nodeValue
**
$(".divOne").text("Hello <b>world</b>!")
的本質:
(1)jQuery.cleanData()
(2)$
(".divOne")[i].textContent = ""
(3)$
(".divOne")[i].textContent="Hello world!"
注意:text() 不會去解析 html 標籤!
完整程式碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>jQuery之text()</title>
</head>
<body>
<script src="jQuery.js"></script>
<div class="divOne">
<!--<p id="divTwo">嘿嘿嘿</p>-->
<p>嘿嘿嘿</p>
</div>
<div class="divOne">
<p>哈哈哈</p>
</div>
<input type="text" id="inputOne">
<script>
function readText(elem) {
let node,
ret = "",
i = 0,
nodeType = elem.nodeType
console.log(nodeType,'nodeType22')
//如果selector是類的話,會有多個目標元素,此時需要分別單個迴圈
//比如document.querySelectorAll('.divOne').nodeType ->undefined
if (!nodeType) {
while ((node = elem[i++])) {
//單個獲取
ret += readText(node)
}
}
//元素節點,文件節點,文件碎片
else if (nodeType === 1 || nodeType === 9 || nodeType === 11) {
//如果目標元素的內容是文字,則直接返回
if (typeof elem.textContent === "string") {
/*jQuery沒有用innerText獲取文字的值,http://bugs.jquery.com/ticket/11153,
大概就是在IE8中新節點插入會保留所有回車。
所以jQuery採用了textContent獲取文字值,
textContent本身是dom3規範的,可以相容火狐下的innerText問題。*/
return elem.textContent
}
//如果節點的內容不是文字,則迴圈子節點,並依次獲取它們的文字節點
else {
for (elem = elem.firstChild; elem; elem = elem.nextSibling) {
ret += readText(elem)
}
}
}
//文字節點、一個文件的CDATA部分(沒遇到過這個)
else if (nodeType === 3 || nodeType === 4) {
//返回節點值
return elem.nodeValue;
}
//nodeType:註釋節點 8,處理指令 7
//text()方法不處理這兩個型別節點
return ret
}
function customEmpty() {
let elem,
i = 0;
//注意for迴圈的寫法
for (; (elem = this[i]) != null; i++) {
//如果是元素節點的話,清空該節點的所有內容
if (elem.nodeType === 1) {
elem.textContent = "";
}
}
return this;
}
function writeText(value) {
let elem,
i = 0;
//先清空目標元素的內容
customEmpty.call(this)
//迴圈
for (; (elem = this[i]) != null; i++) {
//元素節點,文件碎片,文件節點
if (elem.nodeType === 1 || elem.nodeType === 11 || elem.nodeType === 9) {
// text()方法不會解析標籤
elem.textContent = value;
}
}
//return this 方便鏈式呼叫
return this
}
function customText(value) {
return value === undefined ?
//讀
readText(this) :
//寫
writeText.call(this, value)
}
customText.call(document.querySelectorAll('.divOne'))
customText.call(document.querySelectorAll('.divOne'),"Hello <b>world</b>!")
// let p=document.createElement('p')
// p.innerText='哈哈哈'
console.log($(".divOne").text())
// customText.call(document.querySelectorAll('.divOne'))
// console.log(document.querySelectorAll('.divOne').nodeType,'childnode81')
// console.log(document.querySelectorAll('.divOne')[0].textContent,'childnode81')
// $("#divOne").text('<p>aaaa</p>')
// console.log(document.querySelector("#divTwo"))
</script>
</body>
</html>
複製程式碼
(完)