Re: querySelector 違反直覺的行為、擬類選擇器 :scope 與 HTML5 style 元素的 scoped 屬性

回文在下
(11/07/22 11:14), OOO wrote:
> 雖然不是直接相關
> 不過超時空回文一下

這篇才隔一個月而已,像是在 WHATWG 的郵件群或是 www-style 上隔三個月隔半
年才回的也很多。啊,這裡應該要道歉一下,我覺得我好像還有很多該回都還沒有
回的,也很多應該有些結果的討論沒有結果,讓我之後慢慢超時空 補一下吧 xd

不管怎麼樣超時空回文是值得鼓勵的(標題錯字也可以幫忙改一下 xdd),我自己
就載了 www-style 十年份的討論以避免討論重複的東西的時候沒用到以前的討
論,我個人是覺得把一個郵件群的文章放到一個目錄做局部搜尋是蠻有用的技巧。

> [恕刪]
>
> 很多有支援快速透過 id 找 node 的 JavaScript Library 都有這問題
> 像是我正在用的 mootools
> mootools 有實作 element node  的 getElementById 事件來讓人方便做這件事情
> 不過結果實作還是去執行 document.getElementById
> 結果我要 query 的 node 還不在 document 內
> 自然是找不到了

那 element.getElementById 會回傳那個 element 樹外的元素嗎?也就是,

<html>
<div id ="a"></div>
<div id="b"></div>
</html>

b.getElementById("a") // 是 null 還是 <div id="a">?
(沒用過 mootools 所以不知道真正的呼叫形式是怎麼樣...歡迎補充)

假如說是 null,就代表 mootools 還是有判斷 document.getElementById 回傳的
東西在不在 element 裡,那我就會覺得 mootools 的 element.getElementById
實作很奇怪,不應該用 document.getElementById 而該用
element.querySelector("#<id>") 來做,這樣就可以直接解決你採到的這個雷,
因為當 element 沒在文件內的時候 querySelector 會去對 element 根節點的樹
執行 CSS 選擇器而不是 element.ownerDocument 的樹,然後 querySelector 本
來就只會選出該 element 的子嗣所以就不需要做額外判斷*可能*可以省時間(不
一定可以,因為 document.getElementById 應該還是快 element.querySelector
很多)

想法?有沒有有興趣去 mootools 的社群討論一下?

ACTION: X 去 mootools 社群討論一下當 element 不在文件內
element.getElementById 的實作問題

其實我對當 element 在文件外 element.querySelector 的行為還蠻意外的,在
timdream 問我之前沒想過這種情形會怎麼樣。本來 element.querySelector 有三
種可能:
1) 對 element 的子樹執行選擇器
2) 對 element.ownerDocument 的樹執行選擇器
3) 對 element 根節點的樹執行選擇器

我想很多人都會覺得 1) 是最自然的,畢竟 jQuery 就是這樣,但是我一開始的原
文已經解釋瀏覽器不是這樣了。我自己個人覺得第二種比較自然(或者一致性比較
高),在這種假設的情形下所有 element 在文件外的情形 querySelector 都會回
傳 null 反而變成一個沒用的功能。目前我試過 WebKit、FF 都是 3),不過就是
注意一下

<!-- 文件外 -->
<div>
  <p><a>連結</a></p>
</div>

p.querySelctor("div a") 還是會回傳 <a>Link</a> 不是 null



目前 Selectors API Level 2 的這個部份[1]非常不清楚

# The term '''matching Element node''' refers to an Element node that
matches the group of selectors
# (selectors) that was passed to the method, according to the rules for
matching elements defined in
# Selectors [SELECT].

它完全沒有提到 matching Element node 跟 context node(呼叫 querySelector
的那個元素)的關係,然後後面引用的 CSS3 Selector 規範本來就是比較底層的
規範 — 給一棵樹,給一個選擇器 CSS3 Selector 給你幫你選一些元素出來。這邊
沒講清楚 Selector API 送什麼樹過去,建議改成:

| The term '''matching Element node''' refers to an Element node that
matches the group of selectors
| (selectors) that was passed to the method, matching against the
'''home subtree''' of the context node
| [SELECT].

其中 home subtree [2]是 HTML5 規範定義的一個名詞(我們還沒翻到 :( ),就
是 3) 的那個意思( 1) 是 Node's subtree 2) 是 Node's document 3) 是
Node's home subtree),我目前還不太明白為什麼這些部份不移到 DOM Core 那
邊[3](DOM Core 是最新的 DOM 的規範,基本上就是瀏覽器專用的 DOM 版本,不
是 Java、Python 那些用的)

ACTION: Y 去 public-webapps[4](Web Applications Working Group 的郵件
群)回報一下 Selectors API 規範在 element 處於文件外的含糊敘述

[1] http://dev.w3.org/2006/webapi/selectors-api2/#the-apis
[2]
http://www.whatwg.org/specs/web-apps/current-work/multipage/infrastructure.html#home-subtree
[3] http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#trees
[4] http://lists.w3.org/Archives/Public/public-webapps/

> 於是我改用 jQuery 的 find 試試看
> 發現他行為一樣
> 如果 selector 內是只有 #id 的話
> jQuery 會走捷徑用 document.getElementById
> 結果一樣變成非預期的

同 mootools 的感想,一般 $("#<id>") 的時候使用 document.getElementById
是無可厚非的,畢竟每一個 document 應該是有一個 id → 元素的字典所以為了效
率應該做這種最佳化沒錯,但是 find 我覺得就應該用
element.querySelector("#<id>") 了,反正我看一般會在 find 裡面用 #id 的情
況應該也蠻少的。

ACTION: Z 去 jQuery 社群討論一下當 element 不在文件內 $.find 的實作問題

> 目前可以用的解決方法是強迫 jQuery 不走捷徑
> 把 selector 改成 *#id

這還真是 hacky....

> 這樣它就會真的去 node tree 下面的子節點找了


此致

呂 康豪(Kenny), 中文興趣小組W3C連絡人
推特: http://twitter.com/kanghaolu
Google+: https://plus.google.com/112088462407783855918/posts
新浪微博: http://t.sina.com.cn/1950042164

Received on Monday, 25 July 2011 03:52:40 UTC