博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
由莫名其妙的错误开始---浅谈jquery的dom节点创建
阅读量:6340 次
发布时间:2019-06-22

本文共 2181 字,大约阅读时间需要 7 分钟。

本来没准备今天发博客的,在一个前端群中,一位老大哥风自由提出了一个简单却很奇特的问题:

有一个字符串是这样的:var s = '<html lang="en" class="js no-touch discourse-no-touch">'+ '<head><meta name="csrf-token" content="Oul7WqVh4FBVse2yGeY8ZkqoN5/9/2ImxohJvUYEJYc="/></head><body></body></html>';

怎么通过jquery得到其中content的值?

本来觉得这个问题蛮简单的,既可以通过正则获取,也可以通过jquery的$将这个字符串变成一个jq对象来获取。但是也正是后来这个方法,却带来了问题。

以我的理解,定位content的方法应该为$(s).find("meta").attr("content"),但是这么去获取结果确并不正确。

于是做了简单的尝试:

var s = ''+ '
';$(s);//[
​]

得到的并不是所详细的结果,而是meta标签。

这就有点奇怪了,风大猜测是因为外面有<html></html>,可能jquery不能把<html>标签变为dom。而在字符串外层套一层div则确实能够正确的获取结果。
但是,这个结果真的正确么?
又做了一个简单的尝试:
var s = '
'+ '
';$(s);//[
​]

结果并不是我们所想象的那样,而是仍旧去除了html标签,只不过因为套用了一层div,使$(s).find("meta").attr("content")去正确找寻了节点,并不是保护了html标签。

这个问题的原因,相信只有jq的源码能够给我答案了。写了几行简单的测试代码,去通过断点解读一下jq的处理机制:

(function() {        debugger;        $('');        $('
'); $(''); })();

事实证明,除了第一种方式不能正确的获得结果以外,后两种都能正确的获取结果。通过研读jq的源码中对jq对象创建的代码,终于弄清楚了这个原因。

jq对传入的字符串会进行一次正则:

var parsed = rsingleTag.exec( data );//rsingleTag=/^<(\w+)\s*\/?>(?:<\/\1>|)$/

解释一下这个正则吧:

^<(\w+)\s*\/?

以<开头,至少跟着一个字符和任意个空白字符,之后出现0或1次/
>
这个就不说了,前面这些加起来就是<div >这样或者<meta />这样的
(?:<\/\1>|)$
可以匹配<、一个/或者空白并以之为结尾
这些就是</div>或者跟着<br />这种自闭合标签后面的空

这样如果没有任何属性和子节点的字符串(比如'<html></html>'或者'<div></div>'这样)会通过正则的匹配,当通过正则的匹配后则会通过传入的上下文直接创建一个节点:

if ( parsed ) {            return [ context.createElement( parsed[1] ) ];        }//context为上下文

而未通过节点的字符串,则通过创建一个div节点,将字符串置入div的innerHTML:

tmp = tmp || safe.appendChild( context.createElement("div") );//创建divdom节点tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1>
" ) + wrap[2];//将字符串置入div对象的innerHTML

而浏览器是不允许div内直接包含<html>的,因此会将html标签过滤。

当过滤了html之后,刚才的字符串变成了:

jq会从两端向中间去寻找节点的头尾,在这里闭合标签则被寻找为meta标签。

这就是这次所得到的所有结论,总结一下:

如果你的标签是没有子节点和属性的标签,jq会通过正则判定后在你传入的上下文环境直接创建这个节点。

如果你的标签带有子节点或者属性,jq的正则不过,然后会创建一个div,把你的字符串作为div的innerHTML传入,再对div内部的dom节点遍历属性和节点,去获取class啊id啊之类的,然后再创建这个真正的节点。
但是浏览器不允许任何非frame类元素内部有html标签,会将之过滤。
在过滤了html标签后,head标签和body标签就成了两个标签,而jq是从外向内寻找包裹的标签对的,所以这两个标签没有被识别,而meta标签因为是自闭合标签,而且也是从外往内被包裹的最外层闭合标签,因此就成了获取这个标签。
大概就是这样了。

感谢阅读~同时感谢风大~

转载于:https://www.cnblogs.com/xiao-yao/archive/2013/03/21/2974200.html

你可能感兴趣的文章
Debian下使用OpenLDAP 管理端
查看>>
泛型排序器TComparer
查看>>
9个offer,12家公司,35场面试,从微软到谷歌,应届计算机毕业生的2012求职之路...
查看>>
创建符合标准的、有语意的HTML页面——ASP.NET 2.0 CSS Friendly Control Adapters 1.0发布...
查看>>
Adobe驳斥Flash过度耗电论 称HTML5更耗电
查看>>
No!No!No! It's not fashion!
查看>>
艰困之道中学到的经验教训
查看>>
互联网生态建设落地五大挑战——保险科技生态建设 ...
查看>>
进行短视频app开发工作时,可以加入它来保护青少年 ...
查看>>
25G DAC无源高速线缆和25G光模块之间的区别
查看>>
乐乐茶完成近2亿元Pre-A轮融资,祥峰投资领投
查看>>
clickhouse修改时区
查看>>
CSS_定位
查看>>
第二十四章:页面导航(六)
查看>>
IP_VFR-4-FRAG_TABLE_OVERFLOW【cisco设备报错】碎片***
查看>>
Codeforces Round #256 (Div. 2) D. Multiplication Table 【二分】
查看>>
ARM汇编指令格式
查看>>
HDU-2044-一只小蜜蜂
查看>>
HDU-1394-Minimum Inversion Number
查看>>
京东基于Spark的风控系统架构实践和技术细节
查看>>