XiaobaiはVue2.xソースコードを学習します

vueデータの動的応答の原則。

1.すべてのデータをObject.definePropertyに変更して、すべてのデータ変換が監視されるようにします。

1)監視には、オブジェクトと配列の2種類があり、オブジェクトと配列の種類に分けられます
。2)ゲッターでデータを収集して、データを監視可能にします。(defineProperty => js組み込みメソッド)
3)監視set and getを使用してオブジェクトの数を直接監視できますが、配列を監視する方法はなく、配列の変更を監視することはできません。
4)ネイティブ配列メソッドは他の効果はありません。監視する場合は、ネイティブjsで独自のメソッドをカプセル化します。

 Array.defineProtype.newPush = function (obj,value) {
    
    
    //这里可以通知变化。 
    console.log('obj新增了数据对象。')
    obj.push(value)
}

5)実際には、新しいメソッドは使用されませんが、メソッドがインターセプトされ、配列内のメソッドがインターセプトされます。

(1)配列メソッドインターセプター。

    实现原理: 将原生的数组里的方法都进行拦截重写, 这也是vue的真实做法。 
    实现局限: 这样做的只能监测到, 通过数组的pop, push。。。等方法, 如果通过下标进行修改就不行了。 
              所以, vue针对这样的情况, 做了vue.$set和vue.$delete方法来弥补。 

2.収集に依存し、各データが依存する必要のあるデータの配列を構築し、関連するデータをその中に入れます。データが変更された場合、このデータに基づいて変更が必要なデータを知ることができます。

3.収集方法と検出方法。

4.依存関係を通知します。

2.仮想DOM

1)仮想DOMは、実際のDOMツリーの代わりにjsを使用することです。このようにして、DOMツリーの変更を監視できます。
2)実際のDOMツリーは非常に複雑であるため、実際にDOMを操作すると問題が発生します。仮想DOMを使用して最初に監視し、変更されたものを確認すると、パフォーマンス出力が低下します。
3)仮想DOMは、DOMのレンダリングと引き換えにjsの計算能力を使用する方法です。
4)diff-Domアルゴリズムは、jsで表されるDOMのDOMツリーを変更し、変更されたものを監視してから、実際にDOMを変更します。
5)VNodeは、仮想DOMを記述するために使用されるデータ形式です。
-1。含まれるデータは、タグ、データ、子、テキスト、elm、コンテキストなど、タグのデータと属性です。
-2。属性を組み合わせることで、さまざまなノードオブジェクトを表現できます。
6)VNodeのタイプ:*コメント、*テキスト、*要素、*コンポーネント、*機能コンポーネント、* VNodeの6つの形式のクローン。
-1。コメントノード:テキストとisCommentの2つの属性。
-2。テキストノード:テキスト属性。
-3。ノードのクローン作成:すべてのノード属性をバインドします。
-4。要素ノード:// VNodeノード
{ tag:'div', data:{}, children:[ { tag:'span', text:'文字内容' } ] }
-5。コンポーネントノード:上記と同じに加えて、componentOptions(コンポーネントprops)とcomponentInstance(コンポーネントvue)の2つの固有のプロパティがあります。
-6。機能コンポーネントノード:コンポーネントノードと比較して、fnContextとfnOptionの2つの属性があります。
7)VNodeの役割:テンプレートが読み込まれると、DOM =>仮想DOMになり、データが受信されるのを待ちます。データが監視されている場合、ビューは自動的に更新されます。
3. DOM-DIffアルゴリズム:-vueの
DOM-Diffアルゴリズムはパッチと呼ばれ、パッチを適用することを意味します。
-新しいノード、それを追加、それを持たないノード、それを削除、同じノード、新しいノード。
-新しいノードをベンチマークとして使用して、古いノードを変換します。

ノードの作成、ノードの削除、ノードの更新

- 创建节点: 先判断是  元素=> 注释 => 文本。 
- 删除节点: 找到父亲节点, 然后删掉子节点(removeChild方法)。 
- 更新节点: (只包含静态节点、文本节点、元素节点)
    1. 如果是静态节点:```javascript <div>你好, 哈哈哈</div>```, 直接跳过。 
    1. 如果是纯文本的: 那就比对, 需要删,就删, 需要更新就更新。 
    2. 如果是元素节点: 1) 如果子为空, 那直接清空
                      2) 如果子不为空, 那么新旧 递归进行对比。 
    3. 如果是克隆节点: 1) 创建一个clone节点,
                      2) 将所有的节点信息放进来, 然后对其更新(包含的所有的节点信息). 

ノードを更新するためのアルゴリズム:

  • 外側と内側のループの2つのレイヤー(外側のループが新しい、内側のループが古い、多くの古いものを直接削除できる)を介して、要素ノードの子ノードを比較します。子ノードが異なる場合は、変更を行う必要があります。 (作成、削除、移動、更新)

    1. 古いはい、新しいいいえ=> removeElement
    2. 古いはい、新しいはい=>同じではなくコンテンツを見て更新します。=>位置を移動する可能性があります。
    3. 古いものはそうではなく、新しいものは=> createElemnt
    4. 古いものも新しいものもない=>処理なし。
  • 新しく作成されたノードは、処理済みノードの後ではなく、未処理ノードの前の(古いDOMツリー)位置に配置されます。

子ノードアルゴリズムの削除:

  • サイクルが終了した後、古いもので処理されていないノードが削除される子ノードであることがわかります。

子ノードアルゴリズムを更新します。

  • newのノードがoldで見つかり、位置が同じである限り、直接更新されます(ここでは、変更されているかどうかに関係なく、パフォーマンス直接更新よりも高い場合があり看内容是否更新ます)

モバイル子ノードアルゴリズム:

  • 古いものと新しいものの両方がありますが、位置が間違っています。たとえば、newはDOMの2番目の子ノードであり、oldはDOMの3番目の子ノードです。次に、oldの3番目の子を2番目の子に移動します。

  • ここで、移動された位置も、処理済みノードの後ではなく、未処理ノードの前の古い位置にあります。そうしないと、挿入時に同じ問題が発生します。

ダブルループのデメリットと改善:

  • ノードの数が多い場合、2層ループによって速度が非常に遅くなり、アルゴリズムで速度を上げる方法がわかります。
  • vueで使用されるメソッドはnewbefore
    => old after、同じ場合、new before newの添え字は+ 1、old after subscriptは-1です。古い投稿は未処理のbeforeに移動されます。Newbefore
    => old before 、同じ場合、新しい前、すべての古いインデックス+1の前。古い前の固定位置
    。-新しい=>古い前、同じ場合、新しい-1の後、+ 1前。古い後移動前。未処理へ。
    未処理の前に新しい=>古いポストした後、同じ、新しいポストであれば、古いポスト-1。オールド・ポスト、移動している。
    それがまだない場合は、作業=>同じダブルループ。
  • 更新された添え字が1ビット前後になるたびに、処理済みノードとしてマークされます。
  • oldStartIdx> oldEndIdxがの場合、残りのすべての新しいものをDOMに挿入する必要があります(つまり、古い)
  • newStartIdx> newEndIdxの場合、残りを削除する必要があります。

テンプレートのコンパイル

  • テンプレートのコンパイルは、DOM-DiffのオブジェクトがVNodeであるため、ユーザーが入力したhtmlコードを変換するプロセスです=> VNode仮想DOM。したがって、これがすべての前提です。
  1. v-ifやv-forなどの非htmlコンテンツをネイティブhtmlコードに変更します。レンダリング関数の役割。

用户模版 => 模版编译 => render函数 => VNode => patch(DOM-Diff) => 视图展示

  • 抽象構文木AST。
    プログラミング言語の構文構造をツリーのような形式で表します。
    1. テンプレート解析段階:テンプレート文字列=>抽象構文木AST。
    2. 最適化段階:ASTをトラバースし、静的ノードを見つけてマークを付けると、更新する必要がなくなります。
    3. コード生成段階:ASTをレンダリング関数に変換します。
  1. html、text、filter、その他のパーサーを含むパーサーが1つだけでなく、メインのパーサーはhtmlパーサーであり、テキストに遭遇したら、パーサーをフィルター処理して、対応するパーサーを呼び出します。

パーサー

||

paeseHtml <== parseText、parseFilters

  1. htmlパーサーは、テキストに遭遇するとcharsフック関数をトリガーし、コメントに遭遇するとコメントフック関数をトリガーします。

  2. HTMLコンテンツをさまざまな形式で解析します。

4.1コメントの解析では、<!-- 我是注释-->
検出された場合は正規表現を使用<!--し、もう一度調べた後、まだ-->そのコメントが見つかった場合は、そのコメント、予約は移動せず、保持されません。次に、render関数はcommentEnd+3、エンドポイントからレンダリングし、スキップします。

4.2条件付きコメントの解析で<!-- 我是注释 -->
は、検出された場合は正規表現を使用<!--し、検索後に再度条件付きコメントが見つかった場合は、renderを使用してレンダリングをスキップします。

4.3DOCTYPE<!DOCTPE>
正規表現を解析=>スキップし、advance(length)メソッドを使用してレンダリングの位置を変更します。

4.4開始タグの
正規表現を分析する=>

  1. 最初<divにそれを見つけ、次にそれを後で調べますclass = 'a', style = ''。そのような単語は、これらすべての属性を抽出した後、ラベルを見つけます。
  2. 自動終了タグの場合は、監視中/>、終了し></div>ているかどうかです。

4.5終了タグの解析
正規表現=>条件が満たされた場合は、削除を直接戻します。
次に、end()フック関数を呼び出して直接終了します。

4.6テキストの解析

  1. 最初<に見てください。それが始まりである場合は、他のタイプの判断を使用することをお勧めします。それが始まりでない場合は、テキストを解析することです。
  1. ASTのノード階層を確認します。
  1. ASTはどのように階層関係を保証しますか:スタックスタックを使用して、解析されたノード要素を配置すると、対応する関係を接続できます。
  2. スタックの使用、jsの配列には、スタックの多くのメソッド、つまりポップとプッシュが含まれています。その後、配列を直接使用してスタックの機能を実現できます。

3.最適化段階

1)静的ノードをマークする

1.1 先查看是否是根节点, 如果是根节点就进行标记, 
1.2 如果不是查看是否是元素节点, 如果是就递归,递归过程中,如果是就进行标记.
1.3 type的分类和意思是, 1: 就是静态节点, 2: 含有变量的文本节点. 3: 不包含变量的文本节点. 
1.4 如果是元素节点,还需要继续遍历.  

2)静的ルートノードをマークします

2.1 就是从AST的根向下找, 找根节点, 如果是, 就进行标记, 标记完后判断, 是元素节点递归, 否则, 跳过. 

概要:AST生成フェーズで、すべての静的ノードにマークを付けると、パッチフェーズで直接スキップできるため、パフォーマンスの消費が削減されます。

おすすめ

転載: blog.csdn.net/weixin_40944062/article/details/107962508