解析时,jQuery 会忽略任何不是表格的内容,并且文档会删除表格标签

Posted

技术标签:

【中文标题】解析时,jQuery 会忽略任何不是表格的内容,并且文档会删除表格标签【英文标题】:When parsing, jQuery ignores anything that isn't a table and document removes the table tag 【发布时间】:2018-06-04 20:26:30 【问题描述】:

不确定这是错误还是功能。使用表格外的表格元素解析 html 时,jQuery 会忽略非表格元素。

<tr><td>table data</td></tr>
<div>div after will be ignored</div>

传入$(html)变成

<tr><td>table data</td></tr>

当将相同的 html 传递给纯 javascript 时,element.innerHTML = html 变为

table data
<div>div after will be ignored</div>

它正在行动https://codepen.io/addbrick/pen/mprBgP

编辑:在发布此内容后,我意识到 jQuery 正在删除表格元素,因为 dom 中的行为相反。

【问题讨论】:

【参考方案1】:

首先,这不是一个有效的 HTML。

是的。 Jquery 解析器清理了那个。

如果您仔细查看source code jquery,html 函数会在实际设置innerHTML 之前使用 parseHTML。

而 parseHTML 正在调用 buildFragment 并删除字符串中的所有虚假元素。

下面是buildFragment函数的部分源码

// Add nodes directly
            if ( jQuery.type( elem ) === "object" ) 
                jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );

            // Convert non-html into a text node
             else if ( !rhtml.test( elem ) ) 
                nodes.push( context.createTextNode( elem ) );

            // Convert html into DOM nodes
             else 
                tmp = tmp || safe.appendChild( context.createElement( "div" ) );

                // Deserialize a standard representation
                tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
                wrap = wrapMap[ tag ] || wrapMap._default;

                tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];

                // Descend through wrappers to the right content
                j = wrap[ 0 ];
                while ( j-- ) 
                    tmp = tmp.lastChild;
                



// Manually add leading whitespace removed by IE
            if ( !support.leadingWhitespace && rleadingWhitespace.test( elem ) ) 
                nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[ 0 ] ) );
            

            // Remove IE's autoinserted <tbody> from table fragments
            if ( !support.tbody ) 

                // String was a <table>, *may* have spurious <tbody>
                elem = tag === "table" && !rtbody.test( elem ) ?
                    tmp.firstChild :

                    // String was a bare <thead> or <tfoot>
                    wrap[ 1 ] === "<table>" && !rtbody.test( elem ) ?
                        tmp :
                        0;

是的,这是您实际传递的字符串被评估并创建 DOM 节点的地方。

最后,div 不应该直接用作表格内的元素。可以包裹在tdtr 中。

那么为什么 jquery 完全忽略了它?因为那不是真实有效的html。如果您仔细查看html specification of Table,您只能拥有给定的标签。在表格标签中,

<!ELEMENT TABLE - -
     (CAPTION?, (COL*|COLGROUP*), THEAD?, TFOOT?, TBODY+)>
<!ATTLIST TABLE                        -- table element --
  %attrs;                              -- %coreattrs, %i18n, %events --
  summary     %Text;         #IMPLIED  -- purpose/structure for speech output--
  width       %Length;       #IMPLIED  -- table width --
  border      %Pixels;       #IMPLIED  -- controls frame width around table --
  frame       %TFrame;       #IMPLIED  -- which parts of frame to render --
  rules       %TRules;       #IMPLIED  -- rulings between rows and cols --
  cellspacing %Length;       #IMPLIED  -- spacing between cells --
  cellpadding %Length;       #IMPLIED  -- spacing within cells --
  >

在每个标签里面

<!ELEMENT THEAD    - O (TR)+           -- table header -->
<!ELEMENT TFOOT    - O (TR)+           -- table footer --> 

如您所见,没有直接允许使用 div 标签。

但是,在 vanilla javascript innerHTML 的情况下,不会发生这样的解析,浏览器会直接解释提供给 dom 节点的字符串并将它们添加到文档中。

删除元素的所有子元素,解析内容字符串并将结果节点分配为元素的子元素。

【讨论】:

以上是关于解析时,jQuery 会忽略任何不是表格的内容,并且文档会删除表格标签的主要内容,如果未能解决你的问题,请参考以下文章

Jquery在点击时选择表格行不起作用

用jquery怎么检索表格里的内容与文本输入框的里内容是不是相等,相等的话数据所在的行变颜色显示

使用 Jquery:比较两个数组以进行任何匹配

关于非排序 jQuery 数据表的问题

从jquery确定表格内容

忽略UITableViewCell内的垂直滚动