9

私は常に次のことを信じてきました (ただし、今ではこれらの信念の妥当性を疑っています)。

div.name

よりも高速でした:

.name

しかし最近、ほとんどの CSS セレクター エンジンが右から左に読み取ることを読みました。その場合、最初の例は実際には遅くなりませんか? セレクター エンジンは単純に名前のクラスを持つすべての要素を検索し、それらのどれがdivs であったかを識別しなければならないので?

一般に、CSS セレクター エンジンはどのように読み取りますか? 左から右か右から左か?そして、彼らが一般的に右から左に読む場合、誰かがその理由について説明してくれませんか (セレクターエンジンに関して右から左に読むことがどのように理にかなっているのかわかりません)?

4

2 に答える 2

11

しかし、最近、ほとんどのCSSセレクターエンジンが右から左に読み取ることを読みました。その場合、最初の例は実際には遅くなりませんか?

CSSセレクターエンジンは一般的にどちらの方法で読み取りますか?左から右または右から左?そして、彼らが一般的に右から左に読む場合、誰かが理由について私に説明を提供できますか(セレクターエンジンの観点から右から左に読むことがどのように意味があるのか​​わかりません)?

率直に言って、特定のブラウザーでどのセレクターが遅くなるか、ブラウザー間でどれが遅くなるかを判断することはほぼ不可能です。パフォーマンスは変動する傾向があり、特にそのような微視的スケールや予測不可能なドキュメント構造では、予測不可能です。理論上のパフォーマンスについて話しても、最終的には実装に依存します。

そうは言っても、この他の質問に対するBoris Zbarskyの回答と、あなたの質問に対するGuffaの回答に示されているように、一般的なブラウザー(これは現在、すべての主要なレイアウトエンジンに当てはまります)は要素を受け取り、すべての候補セレクターを評価して、一致するものを確認します。 、特定のセレクターに一致する要素のセットを見つけるのではなく。これは微妙ですが非常に重要な違いです。Borisは、非常に詳細であるだけでなく、信頼できる(Firefoxで使用されるエンジンであるGeckoで作業しているため)技術的な説明を提供しているので、それを読むことを強くお勧めします。

しかし、私はあなたの質問で別の懸念と思われるものに対処する必要があると思いました:

セレクターエンジンは、名前のクラスを持つすべての要素を単純に検索し、それらのどれがdivsであるかを識別しなければならないので?

Patrick McElhaneyのコメントと同様に:

リンクされた質問は、セレクターが一般的に右から左に読み取られる理由を説明しているので、#foo ul.round.fancy li.current読み取られますli.current, ul.round.fancy, #fooが、実際には各要素内で右から左に読み取られます(.current, li, .fancy, .round, ul, #foo)?すべきですか?

私はCSSを実装したことはなく、他のブラウザーがCSSを実装する方法も見たことがありません。上記のリンクされた回答から、ブラウザーは右から左へのマッチングを使用して、セレクター内の>コンビネーター(この例のコンビネーターなど)をウォークスルーすることがわかります。

section > div.second > div.third

要素が。でない場合、その親がaであり、その親が。でdiv.thirdあるかどうかを確認する意味はありません。div.secondsection

ただし、この右から左への順序が単純なセレクターレベルまでドリルダウンするとは思わない。言い換えると、ブラウザは、次のように区切られた一連の複合セレクター全体の右から左への評価内で、単純なセレクターシーケンス(複合セレクターとも呼ばれます)の各部分に右から左への評価を使用するとは思わない。コンビネータ。

たとえば、この不自然で非常に誇張されたセレクターについて考えてみます。

div.name[data-foo="bar"]:nth-child(5):hover::after

現在、ブラウザが要素のこれらの条件を次の順序でチェックする必要があるという保証はありません。

  1. この要素へのポインタはありますか?
  2. この要素はその親の5番目の子ですか?
  3. この要素にdata-fooは値を持つ属性がありますbarか?
  4. この要素にはnameクラスがありますか?
  5. これはdiv要素ですか?

また、このセレクターは、単純なセレクターがごちゃ混ぜになっていることを除いて、上記と機能的に同じであり、必ずしも次の順序で評価されることはありません。

div:hover[data-foo="bar"].name:nth-child(5)::after
  1. この要素はその親の5番目の子ですか?
  2. この要素にはnameクラスがありますか?
  3. この要素にdata-fooは値を持つ属性がありますbarか?
  4. この要素へのポインタはありますか?
  5. これはdiv要素ですか?

パフォーマンス上の理由から、このような注文が強制される理由はまったくありません。実際、シーケンスのどこにあっても、特定の種類の単純なセレクターを最初に選択することで、パフォーマンスが向上すると思います。(また、が考慮されていないことに気付くでしょう。これ::afterは、疑似要素が単純なセレクターではなく、一致する方程式に入ることがないためです。)

たとえば、IDセレクターが最速であることはよく知られています。さて、ボリスはリンクされた質問への彼の答えの最後の段落でこれを言います:

完全に一致しないルールに一致させようとすることさえ回避するために、ブラウザーがすでに行っている他の最適化があることにも注意してください。たとえば、右端のセレクターにIDがあり、そのIDが要素のIDと一致しない場合、Geckoではそのセレクターをその要素と一致させる試みはまったくありません。試行される「IDを持つセレクター」のセットです。要素のIDのハッシュテーブルルックアップから取得されます。したがって、これはルールの70%であり、右端のセレクターのタグ/クラス/ IDだけを考慮した後で、一致する可能性がかなり高くなります。

言い換えると、次のようなセレクターがあるかどうかです。

div#foo.bar:first-child

またはこれ:

div.bar:first-child#foo

Geckoは、シーケンス内のどこに配置されているかに関係なく、常にIDとクラスを最初にチェックします。要素にセレクターと一致するIDとクラスがない場合、その要素は即座に破棄されます。あなたが私に尋ねれば、かなり速いです。

それはほんの一例のGeckoでした。これは実装間でも異なる場合があります(たとえば、GeckoやWebKitはTridentやPrestoとは異なる方法で行う場合があります)。もちろん、ベンダーによって一般的に合意されている戦略とアプローチがあります(最初にIDをチェックすることに違いはないでしょう)が、細部は異なる場合があります。

于 2012-04-11T15:05:22.723 に答える
6

セレクタ エンジンは、ルールを適用する要素を探すのではなく、特定の要素に適用されるルールを探します。したがって、セレクターを右から左に読むのが理にかなっています。

このようなセレクター:

div span.text a.demo

セレクタ エンジンにこれらのチェックを実行させて、セレクタが要素に適用されるかどうかを確認します。

  • aクラスを持つ要素demoですか?
  • spanクラスを持つ要素である祖先を持っていtextますか?
  • その要素には、要素である祖先がありdivますか?
于 2012-04-11T13:02:44.947 に答える