この記事では主に Vue の nextTick 関数のソースコード解析を紹介していますが、編集者が非常に優れていると思ったので、参考として共有します。編集者をフォローして見てみましょう。皆さんのお役に立てれば幸いです。
1. Vue.nextTick() とは何ですか?
公式ドキュメントでは次のように説明されています:
次の DOM 更新サイクルが終了した後に実行される遅延コールバック。データを変更した直後にこのメソッドを使用して、更新された DOM を取得します。
2. nextTick を使用する理由
<!DOCTYPE html> <html> <head> <title>演示Vue</title> <script src="https://tugenhua0707.github.io/vue/vue1/vue.js"></script> </head> <body> <p id="app"> <template> <p ref="list"> {{name}} </p> </template> </p> <script> new Vue({ el: '#app', data: { name: 'aa' }, mounted() { this.updateData(); }, methods: { updateData() { var self = this; this.name = 'bb'; console.log(this.$el.textContent); // aa this.$nextTick(function(){ console.log(self.$el.textContent); // bb }); } } }); </script> </body> </html>
上記のコードはページビューに bb を表示しますが、コンソールに印刷すると、取得されたテキストコンテンツはまだ aa ですが、nextTick を使用すると、取得されたテキスト コンテンツはまだ aa です。テキスト コンテンツは最新のコンテンツ bb であるため、この場合は nextTick 関数を使用できます。
なぜ上記のコードは this.name = 'bb'; を変更してから console.log(this.$el.textContent); を使用して値を出力するのでしょうか?それは、nameの値を設定した後、DOMが更新されていないため、取得された値は前の値のままですが、nextTick関数に入れると、DOMが更新された後にコードが実行されるためです。 DOM が更新されると、要素が再度取得され、最新の値が取得されます。
DOM の更新について理解します。VUE では、データ内の値を変更しても、それはすぐには el に反映されません。Vue は、現在のウォッチャー キュー タスク内でのみ、変更されたデータをウォッチャーの非同期キューに置きます。タスクがアイドル状態の場合にのみ実行されます。遅延時間があるため、nextTick関数に配置した後、elの最新の値を取得できます。上記の nextTick を setTimeout に変更しても可能です。
3. Vue ソースコード nextTick の詳細説明 (ソースコードは vue/src/core/util/env.js にあります)
nextTick ソースコードを理解する前に、まず html5 の新しい MutationObserver API を理解しましょう。 DOM の変更を監視するために使用されるインターフェースであり、DOM オブジェクトの子ノードの削除、属性の変更、テキスト内容の変更などを監視できます。
nextTick のソース コードは次のとおりです:
export const nextTick = (function () { const callbacks = [] let pending = false let timerFunc function nextTickHandler () { pending = false; /* 之所以要slice复制一份出来是因为有的cb执行过程中又会往callbacks中加入内容,比如$nextTick的回调函数里又有$nextTick, 那么这些应该放入到下一个轮次的nextTick去执行,所以拷贝一份,遍历完成即可,防止一直循环下去。 */ const copies = callbacks.slice(0) callbacks.length = 0 for (let i = 0; i < copies.length; i++) { copies[i]() } } // the nextTick behavior leverages the microtask queue, which can be accessed // via either native Promise.then or MutationObserver. // MutationObserver has wider support, however it is seriously bugged in // UIWebView in iOS >= 9.3.3 when triggered in touch event handlers. It // completely stops working after triggering a few times... so, if native // Promise is available, we will use it: /* istanbul ignore if */ /* nextTick行为利用了microtask队列, 先使用 Promise.resolve().then(nextTickHandler)来将异步回调 放入到microtask中,Promise 和 MutationObserver都可以使用,但是 MutationObserver 在IOS9.3以上的 WebView中有bug,因此如果满足第一项的话就可以执行,如果没有原生Promise就用 MutationObserver。 */ if (typeof Promise !== 'undefined' && isNative(Promise)) { var p = Promise.resolve() var logError = err => { console.error(err) } timerFunc = () => { p.then(nextTickHandler).catch(logError) // in problematic UIWebViews, Promise.then doesn't completely break, but // it can get stuck in a weird state where callbacks are pushed into the // microtask queue but the queue isn't being flushed, until the browser // needs to do some other work, e.g. handle a timer. Therefore we can // "force" the microtask queue to be flushed by adding an empty timer. if (isIOS) setTimeout(noop) } } else if (typeof MutationObserver !== 'undefined' && ( isNative(MutationObserver) || // PhantomJS and iOS 7.x MutationObserver.toString() === '[object MutationObserverConstructor]' )) { // use MutationObserver where native Promise is not available, // e.g. PhantomJS IE11, iOS7, Android 4.4 /* 创建一个MutationObserver,observe监听到DOM改动之后执行的回调 nextTickHandler */ var counter = 1 var observer = new MutationObserver(nextTickHandler) var textNode = document.createTextNode(String(counter)); // 使用MutationObserver的接口,监听文本节点的字符内容 observer.observe(textNode, { characterData: true }); /* 每次执行timerFunc函数都会让文本节点的内容在0/1之间切换,切换之后将新赋值到那个我们MutationObserver监听的文本节点上去。 */ timerFunc = () => { counter = (counter + 1) % 2 textNode.data = String(counter) } } else { // fallback to setTimeout /* 如果上面的两种都不支持的话,我们就使用setTimeout来执行 */ timerFunc = () => { setTimeout(nextTickHandler, 0) } } return function queueNextTick (cb?: Function, ctx?: Object) { let _resolve callbacks.push(() => { if (cb) { try { cb.call(ctx) } catch (e) { handleError(e, ctx, 'nextTick') } } else if (_resolve) { _resolve(ctx) } }); /* 如果pending为true,表明本轮事件循环中已经执行过 timerFunc(nextTickHandler, 0) */ if (!pending) { pending = true timerFunc() } if (!cb && typeof Promise !== 'undefined') { return new Promise((resolve, reject) => { _resolve = resolve }) } } })()
全体的な概念の理解: まず、nextTick はクロージャー関数であり、コードはすぐに実行されます。全体的なコードを理解する前に、同様のコードを見てみましょう。デモは次のとおりです。
<!DOCTYPE html> <html> <head> <title>演示Vue</title> </head> <body> <p id="app"> </p> <script> var nextTick = (function(){ return function queueNextTick(cb, ctx) { if (cb) { try { cb.call(ctx) } catch (e) { console.log('出错了'); } } } })(); // 方法调用 nextTick(function(){ console.log(2); // 打印2 }) </script> </body> </html>
デモ コードは上記のコードとよく似ています。
次のように nextTick を抽出して使用してデモ コードを作成することもできます:
var nextTick2 = (function(){ const callbacks = []; let pending = false; let timerFunc; function nextTickHandler () { pending = false const copies = callbacks.slice(0) callbacks.length = 0 for (let i = 0; i < copies.length; i++) { copies[i]() } } if (typeof Promise !== 'undefined') { var p = Promise.resolve() var logError = err => { console.error(err) } timerFunc = () => { p.then(nextTickHandler).catch(logError) } } else if (typeof MutationObserver !== 'undefined' || // PhantomJS and iOS 7.x MutationObserver.toString() === '[object MutationObserverConstructor]' ) { // use MutationObserver where native Promise is not available, // e.g. PhantomJS IE11, iOS7, Android 4.4 var counter = 1 var observer = new MutationObserver(nextTickHandler) var textNode = document.createTextNode(String(counter)) observer.observe(textNode, { characterData: true }) timerFunc = () => { counter = (counter + 1) % 2 textNode.data = String(counter) } } else { // fallback to setTimeout /* istanbul ignore next */ timerFunc = () => { setTimeout(nextTickHandler, 0) } } return function queueNextTick (cb, ctx) { let _resolve callbacks.push(() => { if (cb) { try { cb.call(ctx) } catch (e) { handleError(e, ctx, 'nextTick') } } else if (_resolve) { _resolve(ctx) } }) if (!pending) { pending = true timerFunc() } if (!cb && typeof Promise !== 'undefined') { return new Promise((resolve, reject) => { _resolve = resolve }) } } })(); nextTick2(function(){ console.log(2222); });
上記のコードは nextTick のソース コードから抽出したものです。 nextTick をよりよく理解するために、上記のデモを作成しました。
コード全体の意味を理解しましょう。
まず、実行する必要があるすべてのコールバック関数を格納する配列 callbacks = []; を定義し、このラウンドのイベントが完了したかどうかを決定します。 completed timerFunc(nextTickHandler, 0) この関数の場合、true の場合、timeFunc 関数が実行され、nextTickHandler 関数が定義されていることを意味します。この関数の機能は、配列コールバックに保存された関数を順番に走査することです。
以下のソースコードを見てください:
function nextTickHandler () { pending = false const copies = callbacks.slice(0) callbacks.length = 0 for (let i = 0; i < copies.length; i++) { copies[i]() } }
そして、コードは次の 3 つの判断があります:
if (typeof Promise !== 'undefined' && isNative(Promise)) { var p = Promise.resolve(); var logError = err => { console.error(err) } timerFunc = () => { p.then(nextTickHandler).catch(logError); } else if (typeof MutationObserver !== 'undefined' && ( isNative(MutationObserver) || // PhantomJS and iOS 7.x MutationObserver.toString() === '[object MutationObserverConstructor]' )){ var counter = 1 var observer = new MutationObserver(nextTickHandler) var textNode = document.createTextNode(String(counter)) observer.observe(textNode, { characterData: true }) timerFunc = () => { counter = (counter + 1) % 2 textNode.data = String(counter) } } else { timerFunc = () => { setTimeout(nextTickHandler, 0) } }
まず、Promise オブジェクトがサポートされているかどうかを判断します。サポートされている場合は、次の呼び出しに備えて timeFunc() 関数が定義され、オブジェクト MutationObserver がサポートされているかどうかを判断し、テキスト ノードを作成し、ノード データが変更されるかどうかを監視します。 、 timerFunc 関数を呼び出します。値が変更された場合は、データ値を data 属性に割り当てます。データ属性が変更された場合は、ページが再レンダリングされます。属性値は Object.defineProperty によって変更されます)。上記の 2 つの状況が満たされない場合は、setTimeout を直接使用して nextTickHandler 関数を実行します。最後の nextTick コードは次のとおりです。
return function queueNextTick (cb?: Function, ctx?: Object) { let _resolve callbacks.push(() => { if (cb) { try { cb.call(ctx) } catch (e) { handleError(e, ctx, 'nextTick') } } else if (_resolve) { _resolve(ctx) } }) if (!pending) { pending = true timerFunc() } if (!cb && typeof Promise !== 'undefined') { return new Promise((resolve, reject) => { _resolve = resolve }) } }
コードの意味は次のとおりです。受信した cb が関数であるかどうか、ctx パラメータがオブジェクトであるかどうか、cb が関数の場合は cb.call (ctx) を使用し、timerFunc が実行されていない場合は、pending は false です, したがって、timerFunc() 関数が実行されます。基本的な考え方はこれです。 関連する推奨事項:
Vue.nextTick実装方法の簡単な分析
Node.jsのprocess.nextTickの例を使用する
node.jsのTimer nextTick()とsetImmediate() 差分分析_node。 js
以上がVueのnextTick関数のソースコードの詳細説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

Vue.nextTick函数用法详解及在异步更新中的应用在Vue开发中,经常会遇到需要进行异步更新数据的情况,比如在修改DOM后需要立即更新数据或者在数据更新后需要立即进行相关操作。而Vue提供的.nextTick函数就是为了解决这类问题而出现的。本文就会详细介绍Vue.nextTick函数的用法,并结合代码示例来说明它在异步更新中的应用。一、Vue.nex

在Web应用程序中,缓存通常是用来优化性能的重要手段。Django作为一款著名的Web框架,自然也提供了完善的缓存机制来帮助开发者进一步提高应用程序的性能。本文将对Django框架中的缓存机制进行详解,包括缓存的使用场景、建议的缓存策略、缓存的实现方式和使用方法等方面。希望对Django开发者或对缓存机制感兴趣的读者有所帮助。一、缓存的使用场景缓存的使用场景

PHP-FPM是一种常用的PHP进程管理器,用于提供更好的PHP性能和稳定性。然而,在高负载环境下,PHP-FPM的默认配置可能无法满足需求,因此我们需要对其进行调优。本文将详细介绍PHP-FPM的调优方法,并给出一些代码示例。一、增加进程数默认情况下,PHP-FPM只启动少量的进程来处理请求。在高负载环境下,我们可以通过增加进程数来提高PHP-FPM的并发

随着前端技术的迅猛发展,现代化的前端框架层出不穷,Vue.js就是其中的佼佼者。Vue.js是一个渐进式JavaScript框架,具有易学、高效和灵活的特点,是构建交互式Web界面的理想选择。Vue.js3是Vue.js的最新版本,它通过一系列持续性能提升、架构重构和改进开发体验等优点,进一步提高了Vue.js的优越性。其中,nextTick函数是Vue.

在PHP开发中,有时我们需要判断某个函数是否可用,这时我们便可以使用function_exists()函数。本文将详细介绍function_exists()函数的用法。一、什么是function_exists()函数?function_exists()函数是PHP自带的一个内置函数,用于判断某个函数是否被定义。该函数返回一个布尔值,如果函数存在返回True,

Gin框架是目前非常流行的Go语言Web框架之一。作为一个轻量级的框架,Gin提供了丰富的功能和灵活的架构,使得它在Web开发领域中备受欢迎。其中一个特别重要的功能是模板渲染。在本文中,我们将介绍Gin框架的模板渲染功能,并深入了解它的实现原理。一、Gin框架的模板渲染功能Gin框架使用了多种模板渲染引擎来构建Web应用程序。目前,它支持以下几种模板引擎:

ORM(Object-RelationalMapping)框架是一种用于将面向对象编程语言中的对象模型与关系型数据库之间映射的技术。它使开发人员能够使用面向对象的方式操作数据库,而不需要直接操作SQL语言。在PHP开发领域中,ORM框架也得到了广泛的应用。本文将详细介绍PHP中的ORM框架使用方法。一、ORM框架的优点使用ORM框架有以下优点:1.提高开发

组件的异步更新我们应该都知道或者听说过组件的更新是异步的,对于nextTick我们也知道它是利用promise将传入的回调函数放入微任务队列中,在函数更新完以后执行,那么既然都是异步更新,nextTick是怎么保证回调会在组件更新后执行,其插入队列的时机又是什么时候?带着这些问题我们去源码中寻找答案。先回顾一下组件更新的effect:consteffect=(instance.effect=newReactiveEffect(componentUpdateFn,()=>queueJob(u


ホットAIツール

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

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

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

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

DVWA
Damn Vulnerable Web App (DVWA) は、非常に脆弱な PHP/MySQL Web アプリケーションです。その主な目的は、セキュリティ専門家が法的環境でスキルとツールをテストするのに役立ち、Web 開発者が Web アプリケーションを保護するプロセスをより深く理解できるようにし、教師/生徒が教室環境で Web アプリケーションを教え/学習できるようにすることです。安全。 DVWA の目標は、シンプルでわかりやすいインターフェイスを通じて、さまざまな難易度で最も一般的な Web 脆弱性のいくつかを実践することです。このソフトウェアは、

VSCode Windows 64 ビットのダウンロード
Microsoft によって発売された無料で強力な IDE エディター

SublimeText3 英語版
推奨: Win バージョン、コードプロンプトをサポート!

SAP NetWeaver Server Adapter for Eclipse
Eclipse を SAP NetWeaver アプリケーション サーバーと統合します。

ホットトピック



