nextTickを学習するVueソースコード

序文

最近、ustbhuangyi先生のVueソースコードを調べて、コースを総合的に分析しています。以下の内容はクラスノートと見なすことができます。

 

JS操作メカニズム

nextTickの理解を容易にするために、最初にJSの操作メカニズムを理解する必要があります。

参照リンク:

https://ustbhuangyi.github.io/vue-analysis/v2/reactive/next-tick.html#js-%E8%BF%90%E8%A1%8C%E6%9C%BA%E5%88%B6

JSの実行はシングルスレッドであり、イベントループに基づいています。イベントループは、大きく次の手順に分けられます。

(1)すべての同期タスクはメインスレッドで実行され、実行コンテキストスタックを形成します。

(2)メインスレッドに加えて、「タスクキュー」もあります。非同期タスクの実行結果がある限り、イベントは「タスクキュー」に配置されます。

(3)「実行スタック」内のすべての同期タスクが実行されると、システムは「タスクキュー」を読み取り、その中にあるイベントを確認します。次に、これらの対応する非同期タスクは待機状態を終了し、実行スタックに入り、実行を開始します。

(4)メインスレッドは上記の3番目のステップを繰り返し続けます。

 

私の理解

簡単なテスト

<script>
  console.log(1)
  console.log(2)
  console.log(3)
  console.log(4)
  test()
  console.log(5)
  console.log(6)
  console.log(7)
  console.log(8)

  function test(){
    console.log("a")
    setTimeout(function(){console.log("b")},1000)
  }
</script>

 プリント注文

 

ソースコードの実装

nextTickソースコード実装の本質は、実装する関数を収集し、それらをコールバック配列に収集してから、次のティックで配列をトラバースしてコールバックを実行することです。

src / core / util / next-tick.js

constコールバック= []

……。

エクスポート関数nextTick(cb?:関数、ctx?:オブジェクト){

_resolveしましょう

callbacks.push(()=> {

if(cb){

{を試してください

cb.call(ctx)

} catch(e){

handleError(e、ctx、 'nextTick')

}

} else if(_resolve){

_resolve(ctx)

}

})

if(!pending){

保留中= true

timerFunc()

}

// $ flow-disable-line

if(!cb && typeof Promise!== 'undefined'){

新しいPromise(resolve => {を返す

_resolve =解決

})

}

}

 

テスト

<テンプレート>

<div class = "hello">

<h1 ref = "msg"> { {msg}} </ h1>

<div>

<button @ click = "changeText1"> change1 </ button>

<button @ click = "changeText2"> change2 </ button>

</ div>

</ div>

</ template>

 

<スクリプト>

デフォルトのエクスポート{

名前: 'NextTick'、

データ(){

戻り値{

msg: 'Hello World'

}

}、

メソッド:{

changeText1(){

this.msg = 'こんにちはvue'

// domの結果を同期的に出力します

console.log( 'sync:msg =' + this。$ refs.msg.innerText)//再輸出の世界

// domの結果を非同期に出力します

//次の2つの方法を書くことができます

//this。$nextTick(()=> {

// console.log( "nextTick:msg =" + this。$ refs.msg.innerText)

//})

this。$ nextTick()。then(()=> {

console.log( 'nextTick:msg =' + this。$ refs.msg.innerText)//輸出出こんにちはvue

})

}、

changeText2(){

//実行順序は書き込み順序に関連しています

this。$ nextTick(()=> {

console.log( 'nextTick:msg =' + this。$ refs.msg.innerText)//再輸出の世界

})

this.msg = 'こんにちはvue'

// domの結果を同期的に出力します

console.log( 'sync:msg =' + this。$ refs.msg.innerText)//再輸出の世界

// domの結果を非同期に出力します

//結論:domの再レンダリングへのデータの変更は非同期プロセスです

this。$ nextTick()。then(()=> {

console.log( 'nextTick:msg =' + this。$ refs.msg.innerText)//輸出出こんにちはvue

})

}

}

}

</ script>

 

総括する

DOMの再レンダリングへのデータ変更は非同期プロセスであり、次のティックで発生します。

これは、サーバーインターフェイスからデータを取得するときなど、開発プロセスで通常行うことです。データの変更後にDOMの変更に依存するメソッドがある場合は、nextTickの後に実行する必要があります。

たとえば、次の擬似コード:

getData(res).then(()=> {

  this.xxx = res.data

  this。$ nextTick(()=> {

    //ここで変更されたDOMを取得できます

  })

})

レンダリングウォッチャーの更新はデータが変更された後にトリガーされますが、ウォッチャーのフラッシュはnextTickの後であるため、再レンダリングは非同期です。

 

 

 

おすすめ

転載: blog.csdn.net/Irene1991/article/details/114097688