@(作者: Jsaonwong) 以下は私の個人的なブログです。ゲストとして私の記事の間違いを修正してください。
実は、この記事を書く前に、どのトピックについて書こうか、ずっと考えていました。私は仕事関連のトピックについて書きたいので、ですが、仕事で蓄積してきた様々な経験は断片的すぎて記事としてアウトプットするには足りないと常々思っていますので、時間があるときにじっくり整理して皆さんにお伝えしたいと思います。 DocumentFragment ;
おそらく多くの子供たちはこれについて聞いたことがあるし、使い方さえ知っているでしょう。しかし、これの使い方を知っているだけであれば、ソースをトレースすることは、ほとんどの子供たちはそれを本当に理解していないはずだと思います。単に盲目的に使用する場合、これはおそらく作者の意図ではありません。
DocumentFragment をよく理解していない場合は、w3c にアクセスしてそれについて学ぶことができます。これを読んだ後、これが実際には何でもなく、私たちがよく知っている DOM オブジェクトであることが理解できるでしょう。 。
これは比較的単純な概念を持つ DOM オブジェクトですが、非常に実用的です。w3c によれば、DocumentFragment インターフェイスはドキュメントの一部 (または段落) を表します。より正確には、1 つ以上の隣接する Document ノードとそのすべての子孫ノードを表します。実際、これが私が理解している方法です。DocumentFragment はドキュメント フラグメントであり、ドキュメント ツリーの一部を抽出したり、新しいドキュメント フラグメントを作成したりできる軽量のドキュメントです。
しかし、w3c の次の説明では、最初は少し混乱しました。「DocumentFragment ノードはドキュメント ツリーに属しておらず、継承されたparentNode 属性は常に null です。」これはどうでしょうか。文わかりますか?
実際、すべてのノード タイプの中で、DocumentFragment だけがドキュメント内に対応するタグを持ちません。 DOM では、ドキュメント フラグメント (documentfragment) は、ノードを含めて制御できる「軽量」ドキュメントであると規定されていますが、完全なドキュメントのように追加のリソースを占有することはありません。
最も役立つ概念説明は次の段落です: 「つまり、DocumentFragment ノードがドキュメント ツリーに挿入されるように要求された場合、挿入されるのは DocumentFragment 自体ではなく、そのすべての子孫ノードです。これにより、DocumentFragment は、ドキュメントに一度に挿入されるノードを一時的に保存するための便利なプレースホルダーになり、特に Range インターフェイスで使用する場合、ドキュメント内での切り取り、コピー、貼り付けの操作が容易になります。 DocumentFragment の役割は、最後の段落の説明で明確に表現されています。これは DOM 操作には関与しません。DOM に挿入されるノードを一時的にキャッシュするだけの「コンテナ」です。
createDocumentFragment は本当に想像されているほど魔法なのでしょうか?
大幅に向上する
と聞きました。シナリオが次の場合、for ループが本文に div を 10,000 回挿入すると、従来の appendChild の使用では複数のリフローと再描画が発生し、ページのパフォーマンスに必然的に影響します。と熱い気持ちで挑戦してみたのですが、その結果は驚きでした。 私が書いたコードは次のとおりです: (間違っている場合や不公平な場合は修正してください)
最初の段落は for ループの追加のコードです
2 番目の段落は、ドキュメントのフラグメントに追加してから本体に追加する for ループのコードです。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>test for append's performance</title></head> <body> <div id="test1"> </div></body> <script>// per p appendvar start2 = new Date() for(var i = 0; i < 100000; i++) { var p = document.createElement('p'); var oText=document.createTextNode("test2"); p.appendChild(oText); document.body.appendChild(p);}var end2 = new Date() console.log('pappend use: ' + (end2.getTime() - start2.getTime()).toString()); </script> </html>
取得された最終データ。10 セットのデータを取得するためにそれぞれ 10 回試行しました。平均を取って、結果は次のようになります:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>test createDocumentFragment's performance</title></head> <body> <div id="test2"> </div></body> <script>// fregmentvar start1 = new Date(); var fragment = document.createDocumentFragment(); for(var i = 0; i < 100000; i++) { var p = document.createElement('p'); var oText=document.createTextNode("test2"); p.appendChild(oText); fragment.appendChild(p);}document.body.appendChild(fragment); var end1 = new Date() console.log('fragment use: ' + (end1.getTime() - start1.getTime()).toString()); </script> </html>
文書の断片化を使用した場合にかかる平均時間is: 169.25ms
この 2 つのデータに基づくと、パフォーマンスの差は大きくないと思われますが、DocumentFragment は無駄であると言えるでしょうか。答えはもちろん、NONONO です!
パフォーマンス テストを行う場合、テスト環境はさまざまな環境に適応する必要があることは誰もが知っています。私のコードでは、DOM 構造が非常に単純で、パフォーマンスが向上します。 Chrome ブラウザも非常に強力なので、再描画や再描画が非常に高速であるため、この場合に作成されたテスト データは説得力がありません (実際、IE11 のテスト データでは、従来の書き込み方法よりもさらに時間がかかります)。文書の断片化の使用は少なくなります)。
DocumentFragmentにはリフローや再描画によるスプラッシュスクリーンを防ぐ機能しかないということでしょうか?そう言われても私は納得できませんし、DocumentFragment も納得できないので、また争わなければなりません。
那么究竟在什么情境下测试会比较科学一些呢,我沉思半晌突然灵光一闪,既然我在大繁星工作,为什么不在繁星的项目中进行测试呢,繁星整个项目的复杂度已经属于非常复杂的情景了,因此由此测试而得到性能数据是可以值得信服的。
具体的代码其实也就是上面代码块中的js代码,嵌入到了繁星主页面中,而且是window.onload之后方才执行,保证dom已经完全加载完毕;
传统写法的平均耗时为:1168.5ms
使用文档碎片的平均耗时为:686ms
噔噔噔!!果然,在我大繁星下的测试结果,传统写法与使用文档碎片的写法性能高下立判,而且两个值的比还会随着循环的次数越多,document越复杂而逐渐变大。这也证明越是复杂的页面,文档碎片的使用得到的性能提升也往往越大。
更多的数据大家可以自己动手测试一下,毕竟动了手才有发言权,现在最流行的一句话如是说,能动手尽量不BB!
那么接下来就是大家都比较关心的一个问题,这个东西的兼容性如何呢!!!让我们一起来看看
结果如下:( 源自 http://caniuse.com/#search=documentfragment) 综上所述:除了IE8及以下之外都支持这一API,请大家尽情使用createDocumentFragment吧,尤其是移动端更是无往不利。(PS:不过在正确的场景中使用才是正确的做法,任何api和方法都不应该被滥用,否则很有可能会弄巧成拙哦!)
这是本人第一次写博文,错误或许在所难免,如有不正确的地方欢迎指正,如果有严重错误的地方欢迎来喷!最后欢迎大家来我的博客逛一逛 http://jasonwong1991.github.io
最后的最后再说一句,下一篇将会讲关于createDocumentFragment与createElment之间的故事,敬请期待!