これについてさらに詳しく説明しましょう。$nextTick!

青灯夜游
リリース: 2022-12-21 20:43:10
転載
1914 人が閲覧しました

これについてさらに詳しく説明しましょう。$nextTick!

もうすぐ 2023 年になりますが、これを行う方法がまだわかりません。$nextTick? Vue2 がリリースされてから約 10 年、Vue3 がリリースされてから 2 年以上が経ちます。それは正しい!恥ずかしいです。これしか知りません。nextTick now (正直に言うと) さて、まずは百度で検索してみましょう、クリック、クリック、クリック... すぐに Vue.js 公式 Web サイトのドキュメントにジャンプしました、突然ドキュメント内に文を見つけました? :

nextTick: 次の DOM 更新サイクルの終了後に遅延コールバックを実行します。データを変更した直後にこのメソッドを使用して、更新された DOM を取得します。これには 2 つのパラメータがあります: 最初のパラメータはCallback functionで、渡されなかった場合に Promise 呼び出しを提供します; 2 番目のパラメータは実行環境コンテキストで、渡されなかった場合は自動的にバインドされます。呼び出されるインスタンス上で。 [関連する推奨事項:vuejs ビデオ チュートリアルWeb フロントエンド開発]

まず、nextTick とは何なのか見てみましょう。

console.log(this.$nextTick); // 控制台打印 if(fn){ return nextTick(fn, this); }
ログイン後にコピー

nextTick がメソッドであることがわかります。このメソッドには、fn と this という 2 つのパラメータがあります。fnは、渡す必要があるコールバック関数です。thisいわゆる実行環境コンテキストです。そこで質問は、次の DOM 更新が完了するまで、Vue で遅延コールバックを実装するにはどうすればよいでしょうか?まず次の例を見てみましょう:

created:{{message}}
// vue实例 data: { message: "Hello World!", }, created(){ this.message = '你好,世界!'; console.log(this.$refs.test1.innerText);// 报错 // TypeError: Cannot read properties of undefined (reading 'innerText') this.$nextTick(()=>{ console.log('test1 nextTick:',this.$refs.test1.innerText);// 你好,世界! }); },
ログイン後にコピー

上の例から、DOM は作成されたライフ サイクルで操作されますが、作成されたライフ サイクルはデータを初期化するだけであることは誰もが知っています。この期間中はレンダリングは行われません。DOM を直接操作すると、DOM 要素を見つけることができません。次に疑問が生じます。なぜ nextTick に DOM 要素を配置することで DOM 要素を取得できるのでしょうか?これは明らかではないでしょうか? DOM がレンダリングされるまで待ってから、DOM を呼び出して取得します。次に、DOM オペレーション コードを呼び出す前に、次回 DOM がレンダリングされるまで待機するためにnextTick が使用されていることがわかります。 nextTick。そこで、再び疑問が生じます。nextTick は正確に何をするのでしょうか? Vue2 および Vue3 バージョンの nextTick 原理をソース コード レベルから分析してみましょう。

nextTick の Vue2 バージョン

Vue は開発者に nextTick メソッドを公開しているため、このメソッドではコールバック関数の追加という 3 つの主な処理が行われます。はコールバック関数の実行を遅らせ、は現在の nextTick がコールバック関数に渡されるかどうかを決定します。渡されない場合は Promise、this.$nextTick.then(()=>{}) となり、Promise として処理されます。

これについてさらに詳しく説明しましょう。$nextTick!

  • 現在のスコープ内に複数の nextTick 関数が存在する可能性があるため、コールバック関数がコールバック配列に追加されます。

これについてさらに詳しく説明しましょう。$nextTick!

  • 現在の nextTick が pending=true としてマークされているかどうか、つまり実行中であるかどうかを確認します。そうでない場合は、timerFunc (非同期実行関数を使用します(flushCallbacks関数を非同期で呼び出します)。 timerFunc の実行により、現在の環境が Promise、MutationObserver、setImmediate、setTimeout をサポートしているかどうかが決まります。優先順位は前から後ろにあり、4 つの状況に分けられます:
  • 最初に Promiseを使用します。 , 現在の環境が Promise をサポートしている場合、NextTick はデフォルトで Promise を使用し、遅延コールバック関数を実行します。timerFunc は Promise を実行します。Promise は es6 での構文です。現在の環境が es6 での構文のみをサポートしている場合は、後のサポートのみを考慮できます。

これについてさらに詳しく説明しましょう。$nextTick!

  • 支持MutationObserver,HTML5的api,中文意思是:修改的监听,MutationObserver用来监听DOM的变动,比如节点的增减、属性的变动、文本内容的修改等都会触发MutationObserver事件。注意地,与事件不同,事件是同步触发,DOM的变动会立即触发事件,而MutationObserver事件是异步触发,DOM不会立即触发,需要等当前所有DOM操作完毕才会触发。

MutationObserver有7个属性:childList(true,监听子节点的变动)、attributes(true,监听属性的变动)、characterData(true,监听节点内容或节点文本的变动)、subtree(是否应用于该节点的所有后代节点)、attributeOldValue(观察attributes变动时,是否需要记录变动前的属性值)、characterDataOldValue(观察characterData变动时,是否需要记录变动前的值)、attributeFilter(数组,表示需要观察的特定属性(比如[‘class’,‘src’])。

为什么需要创建一个文本节点?因为在这里操作DOM保证浏览器页面是最新DOM渲染的,虽然看来好像是没什么作用,但这是保证拿到的DOM是最新的。

これについてさらに詳しく説明しましょう。$nextTick!

  • 支持setImmediatesetTimeout,setImmediate即时计时器立即执行工作,它是在事件轮询之后执行,为了防止轮询阻塞,每次只会调用一个。setTimeout按照一定时间后执行回调函数。

これについてさらに詳しく説明しましょう。$nextTick!

好了好了,到了现在,我们都知道nextTick做了什么吧,但是我们有没有想过这样的一个问题:既然都是异步回调执行等待DOM更新后才去调用操作DOM的代码,那么这个机制又是什么原理?这就是JS的执行机制有关了,涉及宏任务与微任务的知识,我们先来看看这样的一道题:

console.log('同步代码1'); setTimeout(function () { console.log("setTimeout"); }, 0); new Promise((resolve) => { console.log('同步代码2') resolve() }).then(() => { console.log('promise.then') }) console.log('同步代码3');
ログイン後にコピー

我们可能会问上面的输出是个啥,首先js是单线程,所以在js程序运行中只有一个执行栈,实现不了多线程,所以就需要任务均衡分配,通俗的讲,按任务急优先处理原则,js中分为同步任务和异步任务,异步任务又分为宏任务和微任务,同步任务先入栈,程序会先把执行栈中的所有同步任务执行完,再去判断是否有异步任务,而异步任务中微任务的优先级高于宏任务。如果当前执行栈为空,而微任务队列不为空,就先执行微任务,等把所有微任务执行完,最后才会考虑宏任务。而上面代码中Promise是属于微任务,而setTimeout是宏任务,所以上面的输出为:

// 同步代码1 // 同步代码2 // 同步代码3 // promise.then // setTimeout
ログイン後にコピー

使用Vue2的nextTick

  • 传入回调函数参数使用:

    this.$nextTick(()=>{ // ...操作DOM的代码 })
    ログイン後にコピー
  • 不传入回调函数参数使用:

    // 方式一 this.$nextTick().then(()=>{ // ...操作DOM的代码 }) // 方式二 await this.$nextTick(); // 后写操作DOM的代码
    ログイン後にコピー

Vue3版本的nextTick

Vue3版本就没有Vue2版本的那么多环境支持,nextTick封装成了一个Promise异步回调函数执行。

// Vue3.2.45 // core-main\core-main\packages\runtime-core\src export function nextTick( this: T, fn?: (this: T) => void ): Promise { const p = currentFlushPromise || resolvedPromise return fn ? p.then(this ? fn.bind(this) : fn) : p }
ログイン後にコピー

使用Vue3的nextTick

  • 传入回调函数使用

    import { nextTick } from 'vue' // 引入 setup () { nextTick(()=>{ // ...操作DOM的代码 })
    ログイン後にコピー
  • 不传入回调函数的使用

    import { nextTick } from 'vue' // 引入 setup () { // 方式一 nextTick().then(()=>{ // ...操作DOM的代码 }) // 方式二 await nextTick(); // 后写操作DOM的代码 }
    ログイン後にコピー

    总结

    • nextTick可以通俗的当作一个Promise,所以nextTick属于微任务。
    • nextTick在页面更新数据后,DOM更新,可以通俗理解为,nextTick就是用来支持操作DOM的代码及时更新渲染页面。也就是在数据变化后要执行的某个操作,而这个操作需要使用随数据改变而改变的DOM结构的时候,这个操作都应该放进Vue.nextTick()的回调函数中。
    • 在Vue生命周期的created()钩子函数进行的DOM操作一定要放在Vue.nextTick()的回调函数中。

    (学习视频分享:vuejs入门教程编程基础视频

    以上がこれについてさらに詳しく説明しましょう。$nextTick!の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:juejin.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!