返回顶部
首页 > 资讯 > 前端开发 > JavaScript >Vue中$nextTick实现源码解析
  • 826
分享到

Vue中$nextTick实现源码解析

Vue $nextTickVue $nextTick 2022-11-13 18:11:51 826人浏览 薄情痞子
摘要

目录正文先看一个简单的问题内部实现先看第一块:再看第二块:然后是第三块:最后是第四块:正文 先看一个简单的问题 <template> <div @click=

正文

先看一个简单的问题

<template>
  <div @click="handleClick" ref="div">{{ text }}</div
</template>
<script>
  export default {
    data() {
      return {
        text: 'old'
      }
    },
    methods: {
      handleClick() {
        this.text = 'new'
        console.log(this.$refs.div.innerText)
      }
    }
  }
</script>

此时打印的结果是什么呢?是 'old'。如果想让它打印 'new',使用 nextTick 稍加改造就可以

this.$nextTick(() => {
  console.log(this.$refs.div.innerText)
})

内部实现

但是你想过它内部是怎么实现的么,和我们写 setTimeout 有什么区别呢?

因为平时工作使用的是Vue2,所以我就以Vue2的最新版本2.6.14为例进行分析,vue3的实现应该也是大同小异。

源码地址:GitHub.com/vuejs/vue/b…

为了方便阅读我删掉了注释,只关注最重要的实现

if (typeof Promise !== 'undefined' && isNative(Promise)) {
  const p = Promise.resolve()
  timerFunc = () => {
    p.then(flushCallbacks)
    if (isiOS) setTimeout(noop)
  }
  isUsingMicroTask = true
} else if (!isIE && typeof MutationObserver !== 'undefined' && (
  isNative(MutationObserver) || MutationObserver.toString() === '[object MutationObserverConstructor]'
)) {
  let counter = 1
  const observer = new MutationObserver(flushCallbacks)
  const textnode = document.createTextNode(String(counter))
  observer.observe(textNode, {
    characterData: true
  })
  timerFunc = () => {
    counter = (counter + 1) % 2
    textNode.data = String(counter)
  }
  isUsingMicroTask = true
} else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {
  timerFunc = () => {
    setImmediate(flushCallbacks)
  }
} else {
  timerFunc = () => {
    setTimeout(flushCallbacks, 0)
  }
}

先大概扫一遍可知 $nextTick 主要是通过微任务来实现的,其实在2.5版本中,是采用宏任务与微任务相结合的方式实现的,但因为在渲染和事件处理中一些比较怪异的行为(感兴趣的话可以看下issue),所以最终统一采用了微任务。

先看第一块:

if (typeof Promise !== 'undefined' && isNative(Promise)) {
  const p = Promise.resolve()
  timerFunc = () => {
    p.then(flushCallbacks)
    if (isIOS) setTimeout(noop)
  }
  isUsingMicroTask = true
}

如果可以使用 Promise ,就采用 promise.then 的方式去执行回调,将任务在下一个tick执行。但是其中 if (isIOS) setTimeout(noop) 这句话是在做什么呢?在iOS >= 9.3.3的UIWEBView中,定义的回调函数通过 Promise 的方式推到微任务队列后,队列不刷新,需要靠 setTimeout 来强制更新一下,noop 就是一个空函数。

再看第二块:

else if (!isIE && typeof MutationObserver !== 'undefined' && (
  isNative(MutationObserver) || MutationObserver.toString() === '[object MutationObserverConstructor]'
)) {
  let counter = 1
  const observer = new MutationObserver(flushCallbacks)
  const textNode = document.createTextNode(String(counter))
  observer.observe(textNode, {
    characterData: true
  })
  timerFunc = () => {
    counter = (counter + 1) % 2
    textNode.data = String(counter)
  }
  isUsingMicroTask = true
}

如果不能用 Promise 就降级使用 MutationObserver。创建了一个文本节点,并通过 observer 去观察文本节点的变化。 characterData: true 这个配置就是当文字变化的时候就会执行回调。(counter + 1) % 2 会使文本节点的文字在 0101之间不同变化,这样就会被 observer 观察到。MutationObserver 也是微任务。

然后是第三块:

else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) { 
  timerFunc = () => { 
    setImmediate(flushCallbacks) 
  } 
}

当微任务都不被支持时,就要使用宏任务了。其实大多数情况下都不会走到这里,因为 setImmediate 并没有成为正式的标准,并且兼容性很差。

最后是第四块:

else {
  timerFunc = () => {
    setTimeout(flushCallbacks, 0)
  }
}

最后在所有方案都行不通时,只能采用 setTimeout 的方式。之所以有第三块是因为虽然都是宏任务,但是 setImmediate 会比 setTimeout 快,所以MDN上才会说 setTimeout(fn, 0) 不能成为 setImmediate 的polyfill。就像作者在注释中写的那样:它仍然是比 setTimeout 更好的选择。

一步一步分析了 $nextTick 源码后,你是否对它的用法理解更加透彻了呢?

以上就是Vue中$nextTick实现源码解析的详细内容,更多关于Vue $nextTick解析的资料请关注编程网其它相关文章!

--结束END--

本文标题: Vue中$nextTick实现源码解析

本文链接: https://lsjlt.com/news/170059.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Vue中$nextTick实现源码解析
    目录正文先看一个简单的问题内部实现先看第一块:再看第二块:然后是第三块:最后是第四块:正文 先看一个简单的问题 <template> <div @click=...
    99+
    2022-11-13
    Vue $nextTick Vue $nextTick
  • 解析VUE中nextTick是什么
    1、nextTick是Vue提供的一个全局API,由于Vue的异步更新策略导致我们对数据的修改不会立刻体现,在DOM变化上,此时如果想要立即获取更新后的DOM状态,就需要使用这个方法...
    99+
    2022-11-13
    vue中nexttick vue中nexttick是什么
  • Vue$nextTick为什么能获取到最新Dom源码解析
    目录正文修改数据之后update 方法nextTick 方法里面怎么执行传进去更新方法正文 <template> <p id='text'>{{tex...
    99+
    2022-11-13
    Vue $nextTick获取Dom Vue $nextTick
  • Vue nextTick的原理解析
    目录Event Loop miscroTask(微任务)UI Render(重点)总结下一个循环nextTick 总结 使用过Vue的小伙伴们都知道,Vue里的nextTick可以获...
    99+
    2024-04-02
  • Vue异步更新DOM及$nextTick执行机制源码分析
    本篇内容介绍了“Vue异步更新DOM及$nextTick执行机制源码分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Vue异步更新DOM策...
    99+
    2023-07-05
  • Vue中nextTick的示例分析
    这篇文章主要介绍了Vue中nextTick的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。vue是什么Vue是一套用于构建用户界面的渐进式JavaScript框架,V...
    99+
    2023-06-14
  • Vue中AST源码解析的示例分析
    这篇文章主要介绍Vue中AST源码解析的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!从这个函数开始的:// Line-3924  Vue.prototy...
    99+
    2024-04-02
  • Node.js pipe实现源码解析
    从前面两篇文章,我们了解到。想要把 Readable 的数据写到 Writable,就必须先手动的将数据读入内存,然后写入 Writable。换句话说,每次传递数据时,都需要写如下的模板代码 reada...
    99+
    2022-06-04
    源码 Node js
  • Vue中的nextTick方法详解
    目录vue nextTick与node的nextTick的区别vue nextTick Vue.nextTick() 是一个方法,用于在下次 DOM 更新循环结束之后执行延迟回调。它...
    99+
    2023-05-16
    Vue nextTick Vue nextTick方法
  • vue parseHTML 函数源码解析
    目录正文函数开头定义的一些常量和变量while 循环textEnd ===0parseStartTag 函数解析开始标签总结:正文 接上篇: Vue编译器源码分析AST 抽象语法树 ...
    99+
    2024-04-02
  • Vue编译器解析compile源码解析
    目录引言解析 compilecompile 源码配置选项属性分别解析finalOptions添加warn 方法两个特殊的属性处理引言 在上篇文章 Vue编译器源码分析com...
    99+
    2024-04-02
  • Vue组件事件触发和监听实现源码解析
    目录正文Vue 的事件触发和监听源码分析ononceemitoff动手实现总结正文 通常我们在使用Vue的时候,会使用$emit和$on来触发和监听事件,但是有没有思考是如何实现的呢...
    99+
    2022-12-22
    Vue 组件事件触发监听 Vue 组件触发监听
  • 带你深入了解Vue.$nextTick(原理浅析)
    白话一点就是说,其实这是和JS当中的事件循环是息息相关的,就是Vue不可能对每一个数据变化都做一次渲染,它会把这些变化先放在一个异步的队列当中,同时它还会对这个队列里面的操作进行去重,比如你修改了这个数据三次,它只会保留最后一次。这些变化是...
    99+
    2023-05-14
    $nextTick 前端 Vue.js
  • 源码 | 解析 Redo Log 实现方式
    柯煜昌 顾问软件工程师 目前从事 RadonDB 容器化研发,华中科技大学研究生毕业,有多年的数据库内核开发经验。 | 前言 提及 Redo Log(重做日志)与 LSN(log sequece number)时,经常被问及以下问题:...
    99+
    2017-03-28
    源码 | 解析 Redo Log 实现方式
  • async-validator实现原理源码解析
    目录async-validator 介绍async-validator 基本使用async-validator 源码分析async-validator 源码-构造函数async-va...
    99+
    2023-01-11
    async-validator原理 async validator
  • GoResiliency库中timeout实现原理及源码解析
    目录1.go-resiliency简介2.timeout模式3.源码实现如下4.扩展一下1.go-resiliency简介 ​ 今天看到项目里用到了go-resiliency这个库,...
    99+
    2023-05-19
    Go Resiliency库中的timeout Go Resiliency库 Go timeout
  • vue虚拟Dom-render的源码解析
    这篇文章主要介绍“vue虚拟Dom-render的源码解析”,在日常操作中,相信很多人在vue虚拟Dom-render的源码解析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”...
    99+
    2024-04-02
  • InnoDB MVCC实现原理及源码解析
    1、原理介绍 数据多版本(MVCC)是MySQL实现高性能的一个主要的一个主要方式,通过对普通的SELECT不加锁,直接利用MVCC读取指版本的值,避免了对数据重复加锁的过程。InnoDB支持MVCC多版本...
    99+
    2024-04-02
  • Redis Lua同步锁实现源码解析
    目录Redis+Lua同步锁Jedis配置Jedis工具类→获取jedisredis 锁工具类加锁示例(jedis+lua)Redis+Lua同步锁 Jedis配置 @Configuration @Getter...
    99+
    2023-05-19
    Redis Lua同步锁 Redis Lua 源码解析
  • goslice扩容实现原理源码解析
    目录正文扩容的示例实际扩容倍数growslice 实现growslice 实现步骤growslice 源码剖析总结正文 基于 Go 1.19。 go 的切片我们都知道可以自动地进行扩...
    99+
    2023-01-03
    go slice 扩容原理 go slice
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作