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つのレイヤー(外側のループが新しい、内側のループが古い、多くの古いものを直接削除できる)を介して、要素ノードの子ノードを比較します。子ノードが異なる場合は、変更を行う必要があります。 (作成、削除、移動、更新)
- 古いはい、新しいいいえ=> removeElement
- 古いはい、新しいはい=>同じではなくコンテンツを見て更新します。=>位置を移動する可能性があります。
- 古いものはそうではなく、新しいものは=> createElemnt
- 古いものも新しいものもない=>処理なし。
-
新しく作成されたノードは、処理済みノードの後ではなく、未処理ノードの前の(古い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。したがって、これがすべての前提です。
- v-ifやv-forなどの非htmlコンテンツをネイティブhtmlコードに変更します。レンダリング関数の役割。
用户模版 => 模版编译 => render函数 => VNode => patch(DOM-Diff) => 视图展示
- 抽象構文木AST。
プログラミング言語の構文構造をツリーのような形式で表します。- テンプレート解析段階:テンプレート文字列=>抽象構文木AST。
- 最適化段階:ASTをトラバースし、静的ノードを見つけてマークを付けると、更新する必要がなくなります。
- コード生成段階:ASTをレンダリング関数に変換します。
- html、text、filter、その他のパーサーを含むパーサーが1つだけでなく、メインのパーサーはhtmlパーサーであり、テキストに遭遇したら、パーサーをフィルター処理して、対応するパーサーを呼び出します。
パーサー
||
paeseHtml <== parseText、parseFilters
-
htmlパーサーは、テキストに遭遇するとcharsフック関数をトリガーし、コメントに遭遇するとコメントフック関数をトリガーします。
-
HTMLコンテンツをさまざまな形式で解析します。
4.1コメントの解析では、<!-- 我是注释-->
検出された場合は正規表現を使用<!--
し、もう一度調べた後、まだ-->
そのコメントが見つかった場合は、そのコメント、予約は移動せず、保持されません。次に、render
関数はcommentEnd+3
、エンドポイントからレンダリングし、スキップします。
4.2条件付きコメントの解析で<!-- 我是注释 -->
は、検出された場合は正規表現を使用<!--
し、検索後に再度条件付きコメントが見つかった場合は、renderを使用してレンダリングをスキップします。
4.3DOCTYPE<!DOCTPE>
正規表現を解析=>スキップし、advance(length)メソッドを使用してレンダリングの位置を変更します。
4.4開始タグの
正規表現を分析する=>
- 最初
<div
にそれを見つけ、次にそれを後で調べますclass = 'a', style = ''
。そのような単語は、これらすべての属性を抽出した後、ラベルを見つけます。 - 自動終了タグの場合は、監視中
/>
か、終了し></div>
ているかどうかです。
4.5終了タグの解析
正規表現=>条件が満たされた場合は、削除を直接戻します。
次に、end()フック関数を呼び出して直接終了します。
4.6テキストの解析
- 最初
<
に見てください。それが始まりである場合は、他のタイプの判断を使用することをお勧めします。それが始まりでない場合は、テキストを解析することです。
- ASTのノード階層を確認します。
- ASTはどのように階層関係を保証しますか:スタックスタックを使用して、解析されたノード要素を配置すると、対応する関係を接続できます。
- スタックの使用、jsの配列には、スタックの多くのメソッド、つまりポップとプッシュが含まれています。その後、配列を直接使用してスタックの機能を実現できます。
3.最適化段階
1)静的ノードをマークする
1.1 先查看是否是根节点, 如果是根节点就进行标记,
1.2 如果不是查看是否是元素节点, 如果是就递归,递归过程中,如果是就进行标记.
1.3 type的分类和意思是, 1: 就是静态节点, 2: 含有变量的文本节点. 3: 不包含变量的文本节点.
1.4 如果是元素节点,还需要继续遍历.
2)静的ルートノードをマークします
2.1 就是从AST的根向下找, 找根节点, 如果是, 就进行标记, 标记完后判断, 是元素节点递归, 否则, 跳过.