1、有這樣一段 htmlhtml
<div class="divOne"> <p>嘿嘿嘿</p> </div> <div class="divOne"> <p>哈哈哈</p> </div>
2、jQuery 的 text() 方法node
(1)當直接調用 $().text()
時,.text()
的做用是(循環)讀取(多個)目標元素的textContent/nodeValue
jquery
簡單實現:api
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
設置爲 valuedom
簡單實現:this
writeText():spa
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():code
function customEmpty() { let elem, i = 0; //注意for循環的寫法 for (; (elem = this[i]) != null; i++) { //若是是元素節點的話,清空該節點的全部內容 if (elem.nodeType === 1) { elem.textContent = ""; } } return this; }
(3)源碼實現htm
源碼:事件
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
部分源碼見:https://www.jianshu.com/p/645b3b4461c5
也就是說:調用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 標籤!
參考:http://api.jquery.com/text/
完整代碼:
<!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>
(完)