首页 > 其他分享 >Vue任务调度。

Vue任务调度。

时间:2023-07-25 16:12:52浏览次数:41  
标签:Vue console log state num scheduler const 任务调度

1、作用

vue中一个非常重要的功能,批量更新或者叫异步更新
响应式数据发生变化出发副作用函数重新执行时,我们有能力去决定副作用函数的执行时机、次数和方式。

2、例子

const state = reactive({
  num: 1
})

effect(() => {
  console.log('num', state.num)
})

state.num++

console.log('end')

image

3、实现可调度

const state = reactive({
  num: 1
})

effect(() => {
  console.log(state.num)
}, {
  // 注意这里,假如num发生变化的时候执行的是scheduler函数
  // 那么end将会被先执行,因为我们用setTimeout包裹了一层fn
  scheduler (fn) {
    // 异步执行
    setTimeout(() => {
      fn()
    }, 0)
  }
})

state.num++

console.log('end')

通过scheduler来自主控制副作用函数的执行时机。
在这之前,执行state.num++之后,console.log(state.num)将会被马上执行,而添加scheduler后,num发生变化后将执行scheduler中的逻辑。

4、实现批量更新 & 异步更新

来看段诡异的代码,请问num会被执行多少次?100还是101?

const state = reactive({
  num: 1
})

effect(() => {
  console.log('num', state.num)
})

let count = 100

while (count--) {
  state.num++
}

image
对于页面渲染来说1到101中间的2~100仅仅只是过程,并不是最终的结果,处于性能考虑Vue只会渲染最后一次的101。

Vue是如何做到的呢?

利用可调度性,再加点事件循环的知识,我们就可以做到这件事。

  • num的每次变化都会导致scheduler的执行,并将注册好的副作用函数存入jobQueue队列,因为Set本身的去重性质,最终只会存在一个fn
  • 利用Promise微任务的特性,当num被更改100次之后同步代码全部执行结束后,then回调将会被执行,此时num已经是101,而jobQueue中也只有一个fn,所以最终只会打印一次101
 const state = reactive({
  num: 1
})

const jobQueue = new Set()
const p = Promise.resolve()
let isFlushing = false

const flushJob = () => {
  if (isFlushing) {
    return
  }

  isFlushing = true
  // 微任务
  p.then(() => {
    jobQueue.forEach((job) => job())
  }).finally(() => {
    // 结束后充值设置为false
    isFlushing = false
  })
}

effect(() => {
  console.log('num', state.num)
}, {
  scheduler (fn) {
    // 每次数据发生变化都往队列中添加副作用函数
    jobQueue.add(fn)
    // 并尝试刷新job,但是一个微任务只会在事件循环中执行一次,所以哪怕num变化了100次,最后也只会执行一次副作用函数
    flushJob()
  }
})

let count = 100

while (count--) {
  state.num++
}

image

标签:Vue,console,log,state,num,scheduler,const,任务调度
From: https://www.cnblogs.com/never404/p/17580133.html

相关文章

  • Vue3.0 页面跳转的几种方式
     首先引入import{useRouter}from"vue-router";使用router接收useRouterconstrouter=useRouter(); 1. router.push我们最常用的router.push方法会将新的路由添加到历史记录中,同时会导航到该路由页面,当用户点击浏览器后退按钮时,则回到之前的URL。//保留......
  • vue项目目录结构和启动过程
     1.首先是index.htmlindex.html则是项目的首页,入口页,也是整个项目唯一的HTML页面。一般只定义一个空的根节点,在main.js里面定义的实例将挂载在根节点下,内容都通过vue组件来填充。2.src/main.js相当于Java中的main方法,是整个项目的入口js。主要是引入vue框架,根组件及路由设......
  • vue 实现复制功能
    不使用插件不使用插件,可以使用input标签,然后通过execCommand(‘copy’)函数实现复制功能。复制input标签中的内容<template><divid="app">请输入你需要复制的内容:<inputid="copy"v-model="mes"/><buttonv-on:click="copy()">复制</but......
  • vue的router文件里面import路径的时候ts报红色下划线
    Cannotfindmodule'@/views/index/index.vue'oritscorrespondingtypedeclarations.ts(2307)ViewProblem(Alt+F8)Noquickfixesavailable   解决方法在vite-env.d文件中新增declaremodule"*.vue"{  import{DefineComponent}from&......
  • Vue3组件二次封装
    naive-ui的n-input举例<template><n-inputclearableplaceholder=""v-bind="$attrs"><templatev-for="(value,name)in$slots"#[name]="slotData">......
  • Vue使用v-viewer插件实现图片预览和缩放和旋转等功能
    科普:v-viewer简单来说:v-viewer是一款支持vue项目中的图片浏览组件,它支持图片旋转、缩放、翻转等操作,支持配置化.非常强大官网目录:v-viewer安装依赖直接执行命令:npminstallv-viewer--save引入并使用依赖下载完成之后,就可以配置了,具体操作就是引入并使用依赖了。找到vu......
  • vue2-ace-editor基础配置
    简介Ace是一个用JavaScript编写的可嵌入代码编辑器。它与Sublime、Vim和TextMate等原生编辑器的功能和性能相匹配。它可以很容易地嵌入到任何网页和JavaScript应用程序中。Ace被维护为Cloud9IDE的主要编辑器,并且是MozillaSkywriter(Bespin)项目的继承者。快速开始......
  • 2023-07-25 html中引入vue,报错:Vue is not a constructor ==》引用的vue版本不兼容导致
    报错代码:我使用的vue外链https://cdn.jsdelivr.net/npm/vue,该外链引用的是最新的[email protected]版本,而我的vue写法为vue2.0版本的写法,故而不兼容。解决方案:引用指定版本的vue......
  • Vue学习笔记: provide与inject
    在前几篇学习笔记里,接触到了props$eimt$parent$root等方式实现父子组件间的数据传递方式,但是如果遇到层级很多的情况如何处理呢?provide和inject可以帮助我们解决这一问题。 一个父组件相对于其所有的后代组件,会作为依赖提供者。任何后代的组件树,无论层级有多深,都可以注入......
  • Vue2语法知识总结
    下面总结Vue2的语法知识1、插值语法<!DOCTYPEhtml><html> <head> <metacharset="utf-8"> <title>Vue插值语法</title> <scripttype="text/javascript"src="../javascriptdemo/vue.js"></script> &......