ホームページ > 記事 > ウェブフロントエンド > vue における nextTick の包括的な分析
次のVue.jsチュートリアル列では、vueのnextTickについて紹介します。一定の参考値があるので、困っている友達が参考になれば幸いです。
#vue は非常に人気のあるフレームワークで、angular と React の利点を組み合わせて、双方向のデータ バインディング機能を備えた軽量で使いやすい mvvm を形成します。フレーム。私はそれを使用することを好みます。 vueを使うときによく使うのが this.$nextTick というメソッドで、皆さんも使ったことがあると思います。私が使用する一般的なシナリオは、データを取得した後、新しいビューで次の手順または他の操作を実行する必要があるときに、DOM を取得できないことが判明するというものです。割り当て操作ではデータ モデルの変更が完了するだけで、ビューの更新は完了しないためです。このとき、この章で紹介する機能を使用する必要があります。
nextTick を使用する理由
次のコード部分を参照してください
new Vue({ el: '#app', data: { list: [] }, mounted: function () { this.get() }, methods: { get: function () { this.$http.get('/api/article').then(function (res) { this.list = res.data.data.list // ref list 引用了ul元素,我想把第一个li颜色变为红色 this.$refs.list.getElementsByTagName('li')[0].style.color = 'red' }) }, } })
データを取得した後、それをデータ モデルを参照してから、ul 要素を参照して最初の li を見つけ、その色を赤に変更したいのですが、実際にはエラーが報告されます。この文を実行すると、ul の下に li がありません。これは、次のことを意味します。実行された割り当て操作は現在行われていません。ビュー レイヤへの更新は行われません。
したがって、この場合、vue は $nextTick メソッドを提供します。将来、更新されたビューを操作したい場合は、実行する関数を this.$nextTick メソッドに渡すだけで済みます。 . 、vue がこの作業を行ってくれます。
ソースコードの解釈
この関数は、vue2.2.6 バージョンの 450 行目から始まる非常に単純です。
まず第一に、この関数は単純関心モードを使用しますか、それとも何かによって作成されたクロージャ関数ですか?
var callbacks = []; // 缓存函数的数组 var pending = false; // 是否正在执行 var timerFunc; // 保存着要执行的函数
まず、後で使用するためにいくつかの変数が定義されています。以下は関数です。
function nextTickHandler () { pending = false; // 拷贝出函数数组副本 var copies = callbacks.slice(0); // 把函数数组清空 callbacks.length = 0; // 依次执行函数 for (var i = 0; i < copies.length; i++) { copies[i](); } }
この関数は、$nextTick で実際に呼び出される関数です。
次に、Vue は上記の関数の呼び出しを遅らせるために 3 つの状況に分けます。$nextTick の目的は、dom が更新されるまで受信関数を遅らせてから使用することであるため、ここではエレガントな降順で js を使用します。 . これを行うためのメソッド。
1. Promise.then の遅延呼び出し
if (typeof Promise !== 'undefined' && isNative(Promise)) { var p = Promise.resolve(); var logError = function (err) { console.error(err); }; timerFunc = function () { p.then(nextTickHandler).catch(logError); if (isIOS) { setTimeout(noop); } }; }
ブラウザが Promise をサポートしている場合は、Promise.then を使用して関数呼び出しを遅延させます。関数を現在の関数呼び出しスタックの最後まで遅延させます。つまり、関数は関数呼び出しスタックの最後に呼び出されます。それにより遅延が発生します。
2. MutationObserver は変更を監視します
else if (typeof MutationObserver !== 'undefined' && ( isNative(MutationObserver) || MutationObserver.toString() === '[object MutationObserverConstructor]' )) { var counter = 1; var observer = new MutationObserver(nextTickHandler); var textNode = document.createTextNode(String(counter)); observer.observe(textNode, { characterData: true }); timerFunc = function () { counter = (counter + 1) % 2; textNode.data = String(counter); }; }
MutationObserver は h5 によって追加された新しい関数で、その機能は dom ノードの変更を監視し、すべての dom 変更が完了した後に実行することです。 。 折り返し電話。
監視すべき具体的な変更がいくつかあります
childList: 子要素の変更
attributes: 属性の変更
characterData: ノード コンテンツまたはノード テキストの変更
subtree: すべての下位ノード (子ノードおよび子ノードの子ノードを含む)
上記のコードは、テキスト ノードを作成してテキスト ノードの内容を変更し、変更をトリガーすることがわかります。これは、データ モデルを更新した後、dom ノードが再レンダリングです。
そこで、このような変更リスナーを追加し、テキスト ノードの変更でリスナーをトリガーし、すべての dom がレンダリングされた後に関数を実行して遅延効果を実現しました。
3. setTimeout 遅延器
else { timerFunc = function () { setTimeout(nextTickHandler, 0); }; }
setTimeout の遅延原理を使用して、setTimeout(func, 0) は func 関数を次の関数呼び出しスタックの先頭まで遅延させます。つまり、現在の関数が実行された後に関数が実行され、遅延関数が完了します。
クロージャー関数
return function queueNextTick (cb, ctx) { var _resolve; callbacks.push(function () { if (cb) { cb.call(ctx); } if (_resolve) { _resolve(ctx); } }); // 如果没有函数队列在执行才执行 if (!pending) { pending = true; timerFunc(); } // promise化 if (!cb && typeof Promise !== 'undefined') { console.log('进来了') return new Promise(function (resolve) { _resolve = resolve; }) } }
return関数は実際に使用するクロージャー関数です。関数を追加するたびにコールバックを考えることになります。 . 関数配列がスタックにプッシュされます。次に、関数が現在実行されているかどうかを監視し、実行されていない場合は関数を実行します。これはわかりやすいですね。次のifは約束です。
this.$nextTick(function () { }) // promise化 this.$nextTick().then(function () { }.bind(this))
上記のコードを記述する 2 番目の方法は、私たちにとっては一般的ではありません。これは、$nextTick 関数を直接呼び出して、Promise 形式でコードを記述します。ただし、これは then と で手動でバインドする必要があります。 Vue は内部的には処理しません。
関連する推奨事項:
プログラミング関連の知識について詳しくは、プログラミング コースをご覧ください。 !
以上がvue における nextTick の包括的な分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。