Vue の Vue.nextTick を理解するのに役立つ情報を共有する
この記事では、Vueのピュアな辛口情報と、あなたの知らないVue.nextTickについてご紹介します。
1. NextTick クイズNextTick を本当に理解していますか?さあ、直接質問に行きましょう~Vue を使用したことのある友人は多かれ少なかれそれを知っているでしょう
$nextTick
~ nextTick を正式に説明する前に、Vue について明確に理解しておく必要があると思います。 DOM を更新するときは、非同期で実行されます。次の説明プロセスはコンポーネントの更新と一緒に説明します~ 早速、本題に入りましょう (この記事では
v2.0 を使用します)。 6.14 バージョンの Vue ソース コードを説明します) [関連する推奨事項: vuejs ビデオ チュートリアル ]
<template> <div id="app"> <p ref="name">{{ name }}</p> <button @click="handleClick">修改name</button> </div> </template> <script> export default { name: 'App', data () { return { name: '井柏然' } }, mounted() { console.log('mounted', this.$refs.name.innerText) }, methods: { handleClick () { this.$nextTick(() => console.log('nextTick1', this.$refs.name.innerText)) this.name = 'jngboran' console.log('sync log', this.$refs.name.innerText) this.$nextTick(() => console.log('nextTick2', this.$refs.name.innerText)) } } } </script>
が「名前の変更」ボタン をクリックすると、'nextTick1',
'同期ログ' 、
'nextTick2' に対応する
this.$refs.name.innerText がそれぞれ出力されますか?
注、ここに出力されるのはDOMのinnerTextです~(答えは記事の最後に掲載されます)
2. NextTick ソース コードの実装 ソース コードは core/util/next-tick にあります。これは 4 つの部分に分割でき、コード
#1 に直接移動できます。グローバル変数
##callbacksQueue, pending
Status<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>const callbacks = [] // 存放cb的队列
let pending = false // 是否马上遍历队列,执行cb的标志</pre><div class="contentsignin">ログイン後にコピー</div></div>
2.
flushCallbacks
コールバックをトラバースして各 cb
function flushCallbacks () { pending = false // 注意这里,一旦执行,pending马上被重置为false const copies = callbacks.slice(0) callbacks.length = 0 for (let i = 0; i < copies.length; i++) { copies[i]() // 执行每个cb } }
3.
nextTick
の非同期実装 実行環境のサポートの程度に応じて、さまざまな非同期実装戦略を採用する
let timerFunc // nextTick异步实现fn if (typeof Promise !== 'undefined' && isNative(Promise)) { // Promise方案 const p = Promise.resolve() timerFunc = () => { p.then(flushCallbacks) // 将flushCallbacks包装进Promise.then中 } isUsingMicroTask = true } else if (!isIE && typeof MutationObserver !== 'undefined' && ( isNative(MutationObserver) || MutationObserver.toString() === '[object MutationObserverConstructor]' )) { // MutationObserver方案 let counter = 1 const observer = new MutationObserver(flushCallbacks) // 将flushCallbacks作为观测变化的cb const textNode = document.createTextNode(String(counter)) // 创建文本节点 // 观测文本节点变化 observer.observe(textNode, { characterData: true }) // timerFunc改变文本节点的data,以触发观测的回调flushCallbacks timerFunc = () => { counter = (counter + 1) % 2 textNode.data = String(counter) } isUsingMicroTask = true } else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) { // setImmediate方案 timerFunc = () => { setImmediate(flushCallbacks) } } else { // 最终降级方案setTimeout timerFunc = () => { setTimeout(flushCallbacks, 0) } }
- MutationObserver
- についての理解を深めます。結局のところ、他の 3 つの非同期ソリューションと比較すると、これは誰にとっても最も馴染みのないものになるはずです。
- script start
- 、
- script end
はマクロ タスクの最初のラウンドで実行されますが、これは問題ありません
setTimeout はマクロ タスク実行の次のラウンドに置かれます
#MutationObserver はマイクロ タスクであるため、次のようになりますマクロ タスクの現在のラウンドが実行された後に実行されるため、前に実行されます。 - setTimeout
結果は以下のようになります。
- script end
#4.
nextTick
cb
、Promise
メソッドconst observer = new MutationObserver(() => console.log('观测到文本节点变化')) const textNode = document.createTextNode(String(1)) observer.observe(textNode, { characterData: true }) console.log('script start') setTimeout(() => console.log('timeout1')) textNode.data = String(2) // 这里对文本节点进行值的修改 console.log('script end')
詳細については、pending
が何に使用され、どのように機能するかを理解していますか? - ケース 1、Tick の同じラウンドで 2 回実行されます
$nextTick
、 timerFunc
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>export function nextTick (cb?: Function, ctx?: Object) {
let _resolve
// 往全局的callbacks队列中添加cb
callbacks.push(() => {
if (cb) {
try {
cb.call(ctx)
} catch (e) {
handleError(e, ctx, &#39;nextTick&#39;)
}
} else if (_resolve) {
// 这里是支持Promise的写法
_resolve(ctx)
}
})
if (!pending) {
pending = true
// 执行timerFunc,在下一个Tick中执行callbacks中的所有cb
timerFunc()
}
// 对Promise的实现,这也是我们使用时可以写成nextTick.then的原因
if (!cb && typeof Promise !== &#39;undefined&#39;) {
return new Promise(resolve => {
_resolve = resolve
})
}
}</pre><div class="contentsignin">ログイン後にコピー</div></div>
画像を使用した方が直感的ですか?
- #3. Vue コンポーネントの非同期更新
Vue のコンポーネント化がある場合は # # ディストリビューションのアップデート
ここをクリックして Vue の応答性の原理を図解でご覧ください
Vue のコンポーネント化とディストリビューションのアップデートについて学んでから戻ってきてください~
Vue の 非同期更新DOM は、実際には nextTick を使用して実装されます。これは、実際には通常使用する $nextTick と同じです~ここで、何が起こるかを確認します。属性の値を変更するとき?
上図のディストリビューション更新プロセスに従って、watcher.update の先頭から開始し、例として
Rendering Watcher
queueWatcher
里queueWatcher は何をしましたか? <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>this.$nextTick(() => console.log(&#39;nextTick1&#39;))
this.$nextTick(() => console.log(&#39;nextTick2&#39;))</pre><div class="contentsignin">ログイン後にコピー</div></div>
flushSchedulerQueue は何をしましたか?
// 用来存放Wathcer的队列。注意,不要跟nextTick的callbacks搞混了,都是队列,但用处不同~
const queue: Array<Watcher> = []
function queueWatcher (watcher: Watcher) {
const id = watcher.id // 拿到Wathcer的id,这个id每个watcher都有且全局唯一
if (has[id] == null) {
// 避免添加重复wathcer,这也是异步渲染的优化做法
has[id] = true
if (!flushing) {
queue.push(watcher)
}
if (!waiting) {
waiting = true
// 这里把flushSchedulerQueue推进nextTick的callbacks队列中
nextTick(flushSchedulerQueue)
}
}
}
ログイン後にコピー
最後に、コンポーネントの非同期更新プロセスを理解するための図// 用来存放Wathcer的队列。注意,不要跟nextTick的callbacks搞混了,都是队列,但用处不同~ const queue: Array<Watcher> = [] function queueWatcher (watcher: Watcher) { const id = watcher.id // 拿到Wathcer的id,这个id每个watcher都有且全局唯一 if (has[id] == null) { // 避免添加重复wathcer,这也是异步渲染的优化做法 has[id] = true if (!flushing) { queue.push(watcher) } if (!waiting) { waiting = true // 这里把flushSchedulerQueue推进nextTick的callbacks队列中 nextTick(flushSchedulerQueue) } } }
- 4. 回帰の質問I nextTick ソース コードの上記の分析を通じて、その謎のベールが明らかになったと考えています。このとき、答えをしっかりと伝えることができなければなりませんので、早速、自分の考えと合っているか、一緒に確認してみましょう!
1、如图所示,mounted
时候的innerText是“井柏然”的中文
2、接下来是点击按钮后,打印结果如图所示
没错,输出结果如下(意不意外?惊不惊喜?)
sync log 井柏然
nextTick1 井柏然
nextTick2 jngboran
下面简单分析一下每个输出:
this.$nextTick(() => console.log('nextTick1', this.$refs.name.innerText)) this.name = 'jngboran' console.log('sync log', this.$refs.name.innerText) this.$nextTick(() => console.log('nextTick2', this.$refs.name.innerText))
ログイン後にコピーsync log
:这个同步打印没什么好说了,相信大部分童鞋的疑问点都不在这里。如果不清楚的童鞋可以先回顾一下EventLoop,这里不多赘述了~nextTick1
:注意其虽然是放在$nextTick
的回调中,在下一个tick执行,但是他的位置是在this.name = 'jngboran'
的前。也就是说,他的cb会比App组件的派发更新(flushSchedulerQueue
)更先进入队列,当nextTick1
打印时,App组件还未派发更新,所以拿到的还是旧的DOM值。nextTick2
就不展开了,大家可以自行分析一下。相信大家对它应该是最肯定的,我们平时不就是这样拿到更新后的DOM吗?
最后来一张图加深理解
写在最后,nextTick其实在Vue中也算是比较核心的一个东西了。因为贯穿整个Vue应用的组件化、响应式的派发更新与其息息相关~深入理解nextTick的背后实现原理,不仅能让你在面试的时候一展风采,更能让你在日常开发工作中,少走弯路少踩坑!好了,本文到这里就暂告一段落了,如果读完能让你有所收获,就帮忙点个赞吧~画图不易、创作艰辛鸭~
以上がVue の Vue.nextTick を理解するのに役立つ情報を共有するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









vue.jsでBootstrapを使用すると、5つのステップに分かれています。ブートストラップをインストールします。 main.jsにブートストラップをインポートしますブートストラップコンポーネントをテンプレートで直接使用します。オプション:カスタムスタイル。オプション:プラグインを使用します。

HTMLテンプレートのボタンをメソッドにバインドすることにより、VUEボタンに関数を追加できます。 VUEインスタンスでメソッドを定義し、関数ロジックを書き込みます。

vue.jsでJSファイルを参照するには3つの方法があります。タグ;; mounted()ライフサイクルフックを使用した動的インポート。 Vuex State Management Libraryを介してインポートします。

Vue.jsの監視オプションにより、開発者は特定のデータの変更をリッスンできます。データが変更されたら、Watchはコールバック関数をトリガーして更新ビューまたはその他のタスクを実行します。その構成オプションには、すぐにコールバックを実行するかどうかを指定する即時と、オブジェクトまたは配列の変更を再帰的に聴くかどうかを指定するDEEPが含まれます。

VUEマルチページ開発は、VUE.JSフレームワークを使用してアプリケーションを構築する方法です。アプリケーションは別々のページに分割されます。コードメンテナンス:アプリケーションを複数のページに分割すると、コードの管理とメンテナンスが容易になります。モジュール性:各ページは、簡単に再利用および交換するための別のモジュールとして使用できます。簡単なルーティング:ページ間のナビゲーションは、単純なルーティング構成を介して管理できます。 SEOの最適化:各ページには独自のURLがあり、SEOに役立ちます。

vue.jsには、前のページに戻る4つの方法があります。$ router.go(-1)$ router.back()outes&lt; router-link to =&quot;/&quot; Component Window.history.back()、およびメソッド選択はシーンに依存します。

Vue.jsには配列とオブジェクトを通過するには3つの一般的な方法があります。V-Forディレクティブは、各要素をトラバースしてテンプレートをレンダリングするために使用されます。 V-BindディレクティブをV-Forで使用して、各要素の属性値を動的に設定できます。 .mapメソッドは、配列要素を新しい配列に変換できます。

VUEでタグのジャンプを実装する方法には、HTMLテンプレートでAタグを使用してHREF属性を指定する方法が含まれます。 VUEルーティングのルーターリンクコンポーネントを使用します。 JavaScriptでこれを使用します。$ router.push()メソッド。パラメーターはクエリパラメーターに渡すことができ、ルートは動的ジャンプのルーターオプションで構成されています。
