firstChild 把我玩了

加班两三个小时,就是因为被一个 DWR 的函数给玩了。dwr.util.removeAllRows(ele, options) 这个函数可以把 ele 元素下的所有子元素删除,但允许你添加例外。我试图把一个 <table> 下的一行保留下来。
<table>
	<tr id="row">
		<td>a</td>
	</tr>
	<tr id="row1">
		<td>a</td>
	</tr>
	<tr id="row2">
		<td>a</td>
	</tr>
	<tr id="row3">
		<td>a</td>
	</tr>
</table>

用这样的 JavaScript 代码来做的:
	dwr.util.removeAllRows("tbl", { filter:function(tr) {
		return tr.id != "row";
	}});

照说这样应该就可以了。可结果是 "row" 行还是保留不下来。找到 removeAllRows 的源码来看一下。
dwr.util.removeAllRows = function(ele, options) {
  ele = dwr.util._getElementById(ele, "removeAllRows()");
  if (ele == null) return;
  if (!options) options = {};
  if (!options.filter) options.filter = function() { return true; };
  if (!dwr.util._isHTMLElement(ele, ["table", "tbody", "thead", "tfoot"])) {
    dwr.util._debug("removeAllRows() can only be used with table, tbody, thead and tfoot elements. Attempt to use: " + dwr.util._detailedTypeOf(ele));
    return;
  }
  var child = ele.firstChild;
  var next;
  while (child != null) {
    // 注意这个 alert()
    alert(child.innerHTML);
    next = child.nextSibling;
    if (options.filter(child)) {
      ele.removeChild(child);
    }
    child = next;
  }
};

里面的 alert 是我自己为了调试加的。调试的结果出乎我的意料,获取的子元素竟然只有一个,而且是所有的 <tr>!难怪 filter 回调不好使。对于我来说,解决的方法也挺意外。只需要在 <table> 里添加一个 <tbody> 就可以。
<table>
	<tbody id="tbl">
		<tr id="row">
			<td>a</td>
		</tr>
		<tr id="row1">
			<td>a</td>
		</tr>
		<tr id="row2">
			<td>a</td>
		</tr>
		<tr id="row3">
			<td>a</td>
		</tr>
	</tbody>
</table>

removeAllRows 函数里面关键是 ele.firstChild。没想到在没有 tbody 的情况下,竟然返回所有的行。这个行为在 IE 和 Firefox 下是一致的。看来 <table> 天生应该内嵌 <tbody>,只是我不知道。既然这样,为什么 removeAllRows 还允许 table 传进来?我认为这是这个函数的设计问题。

你可能感兴趣的:(first)