欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

jQuery中实现text()的方法

程序员文章站 2022-05-16 11:18:20
一、有这样一段 html

嘿嘿嘿

&...

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

也就是说:调用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>

总结

以上所述是小编给大家介绍的jquery中实现text()的方法,非常不错,具有一定的参考借鉴价值,需要的朋友参考下吧