Maison > interface Web > Voir.js > Laissez-moi vous donner une compréhension plus approfondie de cela.$nextTick !

Laissez-moi vous donner une compréhension plus approfondie de cela.$nextTick !

青灯夜游
Libérer: 2022-12-21 20:43:10
avant
2006 Les gens l'ont consulté

Laissez-moi vous donner une compréhension plus approfondie de cela.$nextTick !

Nous sommes presque en 2023, vous ne le savez pas encore.$nextTick ? Vue2 est sorti depuis près de 10 ans, et Vue3 est sorti depuis plus de deux ans, c'est vrai ! C'est embarrassant de le dire. Je ne connais que this.nextTick maintenant (à vrai dire). D'accord, cherchons-le d'abord sur Baidu, cliquez sur cliquez... J'ai rapidement sauté sur le document du site officiel de Vue.js et j'ai soudainement trouvé un. phrase dans le document ? :

nextTick : Exécuter un rappel différé après la fin de la prochaine boucle de mise à jour du DOM. Utilisez cette méthode immédiatement après avoir modifié les données pour obtenir le DOM mis à jour. Il a deux paramètres : le premier paramètre est fonction de rappel, qui fournit un appel de promesse s'il n'est pas transmis ; le deuxième paramètre est contexte d'environnement d'exécution, qui par défaut est une liaison automatique s'il n'est pas transmis ; . est affecté à l'instance qui l'appelle. [Recommandations associées : tutoriel vidéo vuejs, développement web front-end]回调函数,不传时提供promise调用;第二个参数是执行环境上下文,不传默认是自动绑定到调用它的实例上。【相关推荐:vuejs视频教程web前端开发

我们先看看nextTick究竟是个啥?

console.log(this.$nextTick);
// 控制台打印
if(fn){
  return nextTick(fn, this);
}
Copier après la connexion

我们可以看出nextTick就是一个方法,方法有两个参数:fn和this,fn就是需要传的回调函数,this就是所说的执行环境上下文。那么问题来了,在Vue中是如何实现在下一次DOM更新结束之后才会执行延迟回调的? 我们先看看下面的例子:

<div ref="test1">created:{{message}}</div>
// vue实例
data: {
    message: "Hello World!",
},
created(){
    this.message = &#39;你好,世界!&#39;;
    console.log(this.$refs.test1.innerText);// 报错
    // TypeError: Cannot read properties of undefined (reading &#39;innerText&#39;)
    this.$nextTick(()=>{
         console.log(&#39;test1 nextTick:&#39;,this.$refs.test1.innerText);// 你好,世界!
    });
},
Copier après la connexion

从上面例子中,在created生命周期中操作了DOM,但是我们都知道created生命周期只是初始化了数据,这期间是还没有渲染DOM的,如果我们直接操作DOM是找不到DOM元素的,那么问题来了:为什么放在nextTick中就可以获取到了DOM元素呢? 这不是很明显吗,等到DOM渲染完才调用不就获取到了吗,从而知道了nextTick作用就是用来等下次DOM渲染完才去调用nextTick内的DOM操作代码

Jetons d'abord un coup d'oeil à ce que nextTick est ?

console.log(&#39;同步代码1&#39;);
setTimeout(function () {
    console.log("setTimeout");
}, 0);
new Promise((resolve) => {
    console.log(&#39;同步代码2&#39;)
    resolve()
}).then(() => {
    console.log(&#39;promise.then&#39;)
})
console.log(&#39;同步代码3&#39;);
Copier après la connexion
Copier après la connexion
Nous pouvons voir que nextTick est une méthode. La méthode a deux paramètres : fn et this fn

est la fonction de rappel qui doit être transmise

this est ce qu'on appelle le contexte d'environnement d'exécution. La question est donc : Comment implémenter un rappel différé dans Vue jusqu'à ce que la prochaine mise à jour du DOM soit terminée ? Jetons d'abord un coup d'œil à l'exemple suivant :

// 同步代码1
// 同步代码2
// 同步代码3
// promise.then 
// setTimeout
Copier après la connexion
Copier après la connexion
Dans l'exemple ci-dessus, le DOM est manipulé dans le cycle de vie créé, mais nous savons tous que le cycle de vie créé ne fait qu'initialiser les données et que le DOM n'a pas été rendu pendant cette période. Si nous ne trouvons pas directement les éléments DOM lors de l'utilisation de DOM, la question se pose : Pourquoi puis-je obtenir des éléments DOM en les plaçant dans nextTick ?

N'est-ce pas évident ? Vous pouvez l'obtenir en attendant que le DOM soit rendu puis en l'appelant. Vous savez alors que la fonction de nextTick est d'attendre la prochaine fois que le DOM est rendu avant d'appeler l'opération DOM. code dans nextTick. La question revient donc : que fait exactement nextTick ? Analysons le principe nextTick des versions Vue2 et Vue3 depuis le niveau du code source.

Laissez-moi vous donner une compréhension plus approfondie de cela.$nextTick !

Version Vue2 de nextTick
  • Puisque Vue expose la méthode nextTick aux développeurs, trois choses principales sont effectuées dans cette méthode,
ajouter la fonction de rappel

, Laissez-moi vous donner une compréhension plus approfondie de cela.$nextTick !exécution retardée de la fonction de rappel

,
    déterminer si le nextTick est transmis à la fonction de rappel
  • . S'il n'est pas transmis, il s'agit d'une promesse, this.$nextTick.then(()=>{}), et est traitée comme une promesse.
  • La fonction de rappel est ajoutée au tableau des rappels, car il peut y avoir plusieurs fonctions nextTick dans la portée actuelle.

Laissez-moi vous donner une compréhension plus approfondie de cela.$nextTick !

🎜 Déterminez si le nextTick actuel a été marqué comme en attente = vrai, c'est-à-dire qu'il est en cours d'exécution. Sinon, exécutez timerFunc (🎜La fonction d'exécution asynchrone est utilisée pour retarder de manière asynchrone l'appel de la fonction flushCallbacks🎜). L'exécution de timerFunc détermine si l'environnement actuel prend en charge promise, MutationObserver, setImmediate et setTimeout. La priorité est d'avant en arrière, divisée en quatre situations : 🎜🎜🎜🎜Utilisez Promise d'abord🎜 Si l'environnement actuel prend en charge promise, nextTick le fera. utilisez d'abord promise par défaut. Pour exécuter la fonction de rappel différé, timerFunc exécute Promise, et promise est la syntaxe sous es6. Si l'environnement actuel ne prend en charge que la syntaxe inférieure à es6, nous ne pouvons considérer que la prise en charge ultérieure. 🎜🎜🎜🎜🎜
  • 支持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是最新的。

Laissez-moi vous donner une compréhension plus approfondie de cela.$nextTick !

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

Laissez-moi vous donner une compréhension plus approfondie de cela.$nextTick !

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

console.log(&#39;同步代码1&#39;);
setTimeout(function () {
    console.log("setTimeout");
}, 0);
new Promise((resolve) => {
    console.log(&#39;同步代码2&#39;)
    resolve()
}).then(() => {
    console.log(&#39;promise.then&#39;)
})
console.log(&#39;同步代码3&#39;);
Copier après la connexion
Copier après la connexion

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

// 同步代码1
// 同步代码2
// 同步代码3
// promise.then 
// setTimeout
Copier après la connexion
Copier après la connexion

使用Vue2的nextTick

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

    this.$nextTick(()=>{
      // ...操作DOM的代码
    })
    Copier après la connexion
  • 不传入回调函数参数使用:

    // 方式一
    this.$nextTick().then(()=>{
      // ...操作DOM的代码
    })
    
    // 方式二
    await this.$nextTick();
    // 后写操作DOM的代码
    Copier après la connexion

Vue3版本的nextTick

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

// Vue3.2.45
// core-main\core-main\packages\runtime-core\src
export function nextTick<T = void>(
  this: T,
  fn?: (this: T) => void
): Promise<void> {
  const p = currentFlushPromise || resolvedPromise
  return fn ? p.then(this ? fn.bind(this) : fn) : p
}
Copier après la connexion

使用Vue3的nextTick

  • 传入回调函数使用

    import { nextTick } from &#39;vue&#39; // 引入
    setup () {    
    nextTick(()=>{
       // ...操作DOM的代码
    })
    Copier après la connexion
  • 不传入回调函数的使用

    import { nextTick } from &#39;vue&#39; // 引入
    setup () {    
        // 方式一
        nextTick().then(()=>{
          // ...操作DOM的代码
        })
    
        // 方式二
        await nextTick();
        // 后写操作DOM的代码
    }
    Copier après la connexion

    总结

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

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

    Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:juejin.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal