当前位置: 首页 > news >正文

【Vue3 源码讲解】nextTick

nextTick 是 Vue 3 中用于异步执行回调函数的函数,它会将回调函数延迟到下一个微任务队列中执行。其中,Vue 更新 DOM 是异步的。下面是对 nextTick 函数的详细解释:

export function nextTick<T = void, R = void>(this: T,fn?: (this: T) => R
): Promise<Awaited<R>> {const p = currentFlushPromise || resolvedPromisereturn fn ? p.then(this ? fn.bind(this) : fn) : p
}
let currentFlushPromise: Promise<void> | null = null
const resolvedPromise = /*#__PURE__*/ Promise.resolve() as Promise<any>

解释如下:

  1. 函数签名:

    • nextTick<T = void, R = void>(this: T, fn?: (this: T) => R): Promise<Awaited<R>>:这是 nextTick 函数的类型签名。它接受以下参数:
      • this:不是参数,是ts中的一个语法,给 this 定义类型。给用于绑定回调函数中的 this 上下文,可以省略。
      • fn:要异步执行的回调函数,是一个函数,可以省略。
    • 函数返回一个 PromisePromise 的泛型为 Awaited<R>,表示回调函数执行后的返回值。
  2. 实现逻辑:

    • nextTick 函数首先定义了一个 Promise 对象 p,这个 Promise 对象被初始化为 currentFlushPromiseresolvedPromise,取决于当前是否处于刷新队列(flush)的过程中。currentFlushPromise 是一个全局变量,用于表示当前正在刷新队列,如果不在刷新队列中,则使用 resolvedPromise,它是一个已经 resolved(已解决)的 Promise

    • 接着,函数检查是否传入了回调函数 fn。如果传入了 fn,则会返回一个 Promise.then(),去执行一个微任务,这个 Promise 在微任务队列中执行回调函数(如果使用 await nextTick() 也相当于执行一个微任务)。如果没有传入 fn,则直接返回 p,这意味着如果没有回调函数,会返回一个已经 resolved 的 Promise

    • 在返回 Promise 的过程中,函数会根据传入的 this 上下文(如果有的话),使用 fn.bind(this) 来绑定回调函数中的 this,确保回调函数在执行时具有正确的上下文。

  3. 总结:

    • nextTick 函数用于将回调函数异步执行,将回调函数放入下一个微任务队列中。它的核心逻辑是使用 Promise 来管理回调函数的异步执行,也就是把我们的代码放到一个 Promise 中去执行微任务,把我们的代码变成异步的。
    • 如果不传入回调函数,将返回一个已经 resolved Promise。这个函数在 Vue 3 中用于在数据更新后执行回调函数,确保数据更新后的 DOM 操作在下一个微任务中执行,以提高性能和响应速度。

Vue 更新 DOM 是异步的,然后我们看一下队列是怎么更新的。

  // job 是组件实例上的 update 方法,生成 instance.update 函数
export function queueJob(job: SchedulerJob) {// the dedupe search uses the startIndex argument of Array.includes()// by default the search index includes the current job that is being run// so it cannot recursively trigger itself again.// if the job is a watch() callback, the search will start with a +1 index to// allow it recursively trigger itself - it is the user's responsibility to// ensure it doesn't end up in an infinite loop.// 检查任务队列是否为空,或者当前任务是否已经在任务队列中if (!queue.length || // 如果队列为空,直接将任务添加到队列中!queue.includes(job,isFlushing && job.allowRecurse ? flushIndex + 1 : flushIndex)) {// 如果任务的 id 为 null,直接将任务添加到队列末尾if (job.id == null) {queue.push(job)} else {// 如果任务的 id 不为 null,根据任务的 id 寻找插入位置// 将任务插入到合适的位置,以保持任务按照 id 的顺序执行queue.splice(findInsertionIndex(job.id), 0, job)}// 触发任务刷新,开始执行任务队列中的任务queueFlush()}
}
const queue: SchedulerJob[] = []

这段代码是 Vue 3 内部用于调度和执行任务的关键部分,主要涉及到任务队列的管理和触发任务执行的逻辑。

解释如下:

  1. queueJob 函数用于将一个任务 job 添加到任务队列 queue 中,并触发任务刷新(queueFlush)。

  2. 在添加任务之前,首先会进行一些条件判断:

    • 首先检查任务队列是否为空,如果为空,直接将任务添加到队列中,不需要进行后续的检查。
    • 然后,使用 queue.includes 方法检查当前任务 job 是否已经在任务队列中。这里的检查是为了避免任务的重复添加。如果任务队列中已经包含了当前任务,就不再添加。
  3. 如果当前任务 job 通过了上述检查条件,就可以将它添加到任务队列中:

    • 如果任务的 id 属性为 null,表示没有指定任务的唯一标识,直接将任务添加到队列末尾(queue.push(job))。
    • 如果任务的 id 属性不为 null,表示指定了任务的唯一标识,需要根据该标识找到合适的插入位置,以保持任务队列中的任务按照 id 的顺序执行(按照 job id 自增的顺序排列)。这时会调用 findInsertionIndex(job.id) 来找到插入位置,然后使用 splice 方法插入任务到指定位置。
  4. 最后,调用 queueFlush 函数,触发任务刷新。任务刷新会开始执行任务队列中的任务。

总结:queueJob 函数用于添加任务到任务队列中,并确保任务不会重复添加。它也负责触发任务刷新,以开始执行任务队列中的任务。这是 Vue 3 中任务调度的核心逻辑之一,用于管理异步任务的执行顺序。

以上的 idjob 都存在于 getCurrentInstance 中,因此可以打印看一下:

import { reactive, ref, nextTick, getCurrentInstance, watch } from 'vue'
const instance = getCurrentInstance()
console.log(instance);

在这里插入图片描述

返回一个对象,源码里面的 id 就是这里的 uid ,里面的 job 函数就是这里的 update 函数。也就是说:const update = (instance.update = () => effect.run()) , update.id = instance.uid。所以,源码就是获取了这两者,放入 queue 队列。

function queueFlush() {if (!isFlushing && !isFlushPending) {// 如果没有正在刷新任务队列(isFlushing 为 false)// 且没有挂起的刷新请求(isFlushPending 为 false)// 设置 isFlushPending 为 true,表示有一个刷新请求挂起isFlushPending = true// 使用 resolvedPromise.then(flushJobs) 来延迟执行 flushJobs 函数// 这样可以让当前的 JavaScript 执行栈完成后再执行刷新操作currentFlushPromise = resolvedPromise.then(flushJobs)}
}

这段代码是 Vue 3 内部用于触发任务刷新(flushJobs)的逻辑。它确保在没有正在刷新任务队列(isFlushingfalse)且没有挂起的刷新请求(isFlushPendingfalse)时才会触发任务刷新。

解释如下:

  1. queueFlush 函数用于触发任务刷新,但它不会立即执行刷新操作,而是通过 Promise 的方式进行延迟执行。

  2. 在执行触发刷新前,首先进行两个条件的检查:

    • isFlushingfalse:表示没有正在刷新任务队列,确保不会同时执行多次刷新。
    • isFlushPendingfalse:表示没有挂起的刷新请求,确保不会重复触发刷新。
  3. 如果上述两个条件都满足,就会执行以下操作:

    • isFlushPending 设置为 true,表示有一个刷新请求挂起。
    • 创建一个 Promise 对象 currentFlushPromise,使用 resolvedPromise 来生成一个已经 resolved(已完成)状态的 Promise,并通过 .then 方法将 flushJobs 函数作为回调传递进去。这样,flushJobs 函数会在下一个微任务中执行。
  4. currentFlushPromise 这个 Promise 被 resolved 时,会触发 flushJobs 函数的执行,从而实际执行任务刷新的操作。

总结:queueFlush 函数用于触发任务刷新,但会确保在没有正在刷新任务队列的情况下,且没有挂起的刷新请求时才触发。核心就是通过将刷新操作包装成 Promise,把 flushJobs 放入下一个微任务中执行,以确保任务刷新是异步的,不会阻塞当前 JavaScript 执行栈。这种设计有助于保持 Vue 3 的响应性和性能。

function flushJobs(seen?: CountMap) {// 标志当前没有挂起的刷新请求isFlushPending = false// 标志当前正在执行刷新操作isFlushing = trueif (__DEV__) {// 如果是开发环境,创建一个用于追踪任务数量的 Map 对象seen = seen || new Map()}// Sort queue before flush.// This ensures that:// 1. Components are updated from parent to child.// 2. If a component is unmounted during a parent component's update,//    its update can be skipped.// 在执行刷新前,对任务队列进行排序,以确保以下两点:// 1. 组件更新的顺序是从父组件到子组件的(因为父组件总是在子组件之前创建,所以其渲染效果具有较小的优先级编号)。// 2. 如果在父组件的更新期间卸载了子组件,可以跳过子组件的更新。queue.sort(comparator)// 条件使用 checkRecursiveUpdate 必须在 try...catch 块外部决定// 因为 Rollup 默认会在 try...catch 块内部取消树摇,这可能导致所有警告代码都无法被摇掉。// 尽管它们最终会被像 terser 这样的压缩器摇掉,但某些压缩器可能无法做到这一点(例如 https://github.com/evanw/esbuild/issues/1610)。const check = __DEV__? (job: SchedulerJob) => checkRecursiveUpdates(seen!, job): NOOPtry {for (flushIndex = 0; flushIndex < queue.length; flushIndex++) {const job = queue[flushIndex]if (job && job.active !== false) {if (__DEV__ && check(job)) {continue}// 执行任务,并使用 callWithErrorHandling 包装,以捕获可能的错误callWithErrorHandling(job, null, ErrorCodes.SCHEDULER)}}} finally {// 清空 flushIndex,重置任务队列flushIndex = 0queue.length = 0// 执行在刷新后的回调函数flushPostFlushCbs(seen)// 标志当前刷新结束isFlushing = false// 将当前刷新的 Promise 置为 nullcurrentFlushPromise = null// 如果任务队列中仍有任务或者有挂起的 postFlush 回调// 继续执行刷新操作,直到任务队列为空if (queue.length || pendingPostFlushCbs.length) {flushJobs(seen)}}
}

这段代码是 Vue 3 中用于执行任务刷新的关键逻辑,它会在 queueFlush 函数触发时执行。

解释如下:

  1. flushJobs 函数用于执行任务刷新,它在 queueFlush 函数触发后被调用。

  2. 首先,它会将 isFlushPending 置为 false,表示当前没有挂起的刷新请求,然后将 isFlushing 置为 true,表示当前正在执行刷新操作。

  3. 在开发环境中,创建一个用于追踪任务数量的 seen Map 对象。

  4. 对任务队列 queue 进行排序,确保组件的更新按从父到子的顺序执行,同时也考虑了组件在父组件更新期间被卸载的情况。

  5. 使用 check 函数来检查是否存在递归更新的情况。这个检查在开发环境下才会执行。

  6. 进入循环,依次处理任务队列 queue中的任务。如果任务是激活状态且没有递归更新的情况,就执行该任务。callWithErrorHandling 函数用于包装任务的执行,以捕获可能的错误,其实就是包装了 job 函数,并且会把错误抛出。

  7. finally 块中,清空 flushIndex,重置任务队列 queue,确保任务只会执行一次。

  8. 执行在刷新后的回调函数 flushPostFlushCbs,这些回调函数通常用于清理或执行一些不同的调度政策。

  9. 最后,将 isFlushing 置为 false,表示刷新操作结束,将当前刷新的 Promise currentFlushPromise 置为 null

  10. 如果任务队列 queue 中仍有任务,或者有挂起的 postFlush 回调函数,就继续执行刷新操作,直到任务队列为空。

总结:flushJobs 函数是 Vue 3 中执行任务刷新的核心逻辑,它会在 queueFlush 触发后执行,负责遍历并执行任务队列中的任务,确保组件更新按正确的顺序执行,并处理递归更新的情况。这个函数的设计是为了保持 Vue 3 的响应性和性能。

比如我们可以在父组件中嵌套一个子组件,让父组件和子组件都输出 getCurrentInstance(上面提到过~)。可以看到 uid 的顺序就是先创建父组件,再创建子组件。

在这里插入图片描述

至于上面说的 flushPostFlushCbs 函数,其实我们在学watch的时候已经接触过了。

watch((xxx)=> {},{flush: 'post'
})

这里的 flush: 'post' 其实就是调用了flushPostFlushCbs 函数。

相关文章:

【Vue3 源码讲解】nextTick

nextTick 是 Vue 3 中用于异步执行回调函数的函数&#xff0c;它会将回调函数延迟到下一个微任务队列中执行。其中&#xff0c;Vue 更新 DOM 是异步的。下面是对 nextTick 函数的详细解释&#xff1a; export function nextTick<T void, R void>(this: T,fn?: (this:…...

什么是ATR,在聚宽量化平台如何计算ATR

海龟们使用两种资金管理方法。首先&#xff0c;我们把头寸分成一个个小块。这样&#xff0c;即使一笔交易赔了钱&#xff0c;我们损失的也只是一个头寸的一部分。里奇和比尔把这些小块称作头寸单位。其次&#xff0c;我们使用里奇和比尔发明的一种创新性的头寸规模决定方法。这…...

Python 爬虫实战之爬淘宝商品并做数据分析

前言 是这样的&#xff0c;之前接了一个金主的单子&#xff0c;他想在淘宝开个小鱼零食的网店&#xff0c;想对目前这个市场上的商品做一些分析&#xff0c;本来手动去做统计和分析也是可以的&#xff0c;这些信息都是对外展示的&#xff0c;只是手动比较麻烦&#xff0c;所以…...

Python爬虫-requests.exceptions.SSLError: HTTPSConnectionPool疑难杂症解决(1)

前言 本文是该专栏的第7篇,后面会持续分享python爬虫案例干货,记得关注。 在爬虫项目开发中,偶尔可能会遇到SSL验证问题“requests.exceptions.SSLError: HTTPSConnectionPool(host=www.xxxxxx.com, port=443): Max retries exceeded with url ...”。亦或是验证之后的提示…...

12:STM32---RTC实时时钟

目录 一:时间相关 1:Unix时间戳 2: UTC/GMT 3:时间戳转化 二:BKP 1:简历 2:基本结构 三: RTC 1:简历 2: 框图 3:RTC基本结构 4:RTC操作注意 四:案例 A:读写备份寄存器 1:连接图 2: 步骤 3: 代码 B:实时时钟 1:连接图 2:函数介绍 3:代码 一:时间相关 1:Un…...

【动态规划刷题 16】最长等差数列 (有难度) 等差数列划分 II - 子序列

1027. 最长等差数列 https://leetcode.cn/problems/longest-arithmetic-subsequence/ 给你一个整数数组 nums&#xff0c;返回 nums 中最长等差子序列的长度。 回想一下&#xff0c;nums 的子序列是一个列表 nums[i1], nums[i2], …, nums[ik] &#xff0c;且 0 < i1 <…...

【postgresql】替换 mysql 中的ifnull()

数据库由mysql 迁移到postgresql&#xff0c;程序在执行查询时候报错。 HINT: No function matches the given name and argument types. You might need to add explicit type casts. CONTEXT: referenced column: ifnull 具体SQL: SELECT ifnull(phone,) FROM c_user p…...

单例模式(懒汉式,饿汉式,变体)

单例模式&#xff0c;用于确保一个类只有一个实例&#xff0c;并提供一个全局访问点以访问该实例。 饿汉式&#xff08;Eager Initialization&#xff09; 程序启动时就创建实例 #include <iostream> class SingletonEager { private:static SingletonEager* instanc…...

Java Lambda表达式:简洁且强大的函数式编程工具

Lambda表达式是Java 8及以后版本中引入的一种函数式编程特性。它是一种匿名函数&#xff0c;允许开发人员以简洁和易读的方式编写代码&#xff0c;并且可以作为参数传递给方法或存储在变量中。Lambda表达式的基本语法如下&#xff1a;(parameters) -> expression&#xff0c…...

开源框架中的责任链模式实践

作者&#xff1a;vivo 互联网服务器团队-Wang Zhi 责任链模式作为常用的设计模式而被大家熟知和使用。本文介绍责任链的常见实现方式&#xff0c;并结合开源框架如Dubbo、Sentinel等进行延伸探讨。 一、责任链介绍 在GoF 的《设计模式》一书中对责任链模定义的&#xff1a;将…...

智能配电系统:保障电力运行安全、可控与高效

智能配电系统是一种先进的电力分配技术&#xff0c;它通过智能化、数字化和网络化等方式&#xff0c;有效地保障了电力运行的安全、可控和高效。 力安科技智能配电系统是在配电室&#xff08;含高压柜、变压器、低压柜&#xff09;、箱式变电站、配电箱及动力柜&#xff08…...

MySQL学习系列(11)-每天学习10个知识

目录 1. 数据库设计的关键因素2. 使用存储过程和函数来提高性能和可重用性3. MySQL性能优化4. 使用视图简化查询和提供数据安全性5. 数据库备份和恢复策略的重要性和实践经验6. 在分布式系统中保证数据一致性和可用性7. 理解MySQL的复制和其在实际应用中的作用8. 使用游标进行分…...

如何通过Gunicorn和Niginx部署Django

本文主要介绍如何配置Niginx加载Django的静态资源文件&#xff0c;也就是Static 1、首先需要将Django项目中的Settings.py 文件中的两个参数做以下设置&#xff1a; STATIC_URL /static/ STATIC_ROOT os.path.join(BASE_DIR, static) 然后在宝塔面板中执行python manage.…...

C语言 cortex-A7核UART总线实验

一、C 1&#xff09;uart4.h #ifndef __UART4_H__ #define __UART4_H__ #include "stm32mp1xx_rcc.h" #include "stm32mp1xx_gpio.h" #include "stm32mp1xx_uart.h&quo…...

asp.net C#免费反编译工具ILSpy

在维护一个没有源码的C#项目&#xff0c;只能反编译了。 项目主页 https://github.com/icsharpcode/ILSpy 使用方法 中文界面使用简单&#xff0c;把你要反编译的dll拖过去就可以了。好使&#xff01;&#xff01;&#xff01;...

演讲实录:DataFun 垂直开发者社区基于指标平台自主洞察北极星指标

在7月14日举办的 Kyligence 用户大会的数智新应用论坛上&#xff0c;DataFun COO 杜颖女士为大家带来了《垂直开发者社区基于指标平台自主洞察北极星指标》的主题演讲。接下来&#xff0c;我们一起看看 DataFun 如何在没有专门的 IT 团队的情况下&#xff0c;实现对北极星指标的…...

ffmpeg编译 Error: operand type mismatch for `shr‘

错误如下&#xff1a; D:\msys2\tmp\ccUxvBjQ.s: Assembler messages: D:\msys2\tmp\ccUxvBjQ.s:345: Error: operand type mismatch for shr D:\msys2\tmp\ccUxvBjQ.s:410: Error: operand type mismatch for shr D:\msys2\tmp\ccUxvBjQ.s:470: Error: operand type mismatch…...

【Windows Server 2012 R2搭建FTP站点】

打开服务器管理器——添加角色和功能 下一步 下一步 下一步 选择FTP服务器&#xff0c;勾上FTP服务和FTP扩展&#xff0c;点击下一步 安装 安装完成关闭 打开我们的IIS服务器 在WIN-XXX主页可以看到我们的FTP相关菜单 右键WIN-XXXX主页&#xff0c;添加FTP站点 输入站点名称-FT…...

python教程:使用gevent实现高并发并限制最大并发数

嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取 import time import gevent from gevent.pool import Pool from gevent import monkey # 一&#xff0c;定义最大并发数 p Pool(20) # 二&#xff0c;导入gevent…...

借助reCAPTCHA实现JavaScript验证码功能

前言 验证码&#xff08;CAPTCHA&#xff09;是一种常见的安全验证机制&#xff0c;常用于区分真实用户和机器人。使用验证码可以有效防止恶意登录、自动注册或者密码爆破等攻击。本文将借助reCAPTCHA第三方库来实现JavaScript验证码功能。 验证码的原理 验证码的核心思想是要…...

监控数据的采集方式及原理

采集方法使用频率从高到低依次是读取 /proc目录、执行命令行工具、远程黑盒探测、拉取特定协议的数据、连接到目标对象执行命令、代码埋点、日志解析。 读取 /proc目录 /proc是一个位于内存中的伪文件系统&#xff0c;而在该目录下保存的不是真正的文件和目录&#xff0c;而是…...

Vue路由与node.js环境搭建

目录 前言 一.Vue路由 1.什么是spa 1.1简介 1.2 spa的特点 1.3 spa的优势以及未来的挑战 2.路由的使用 2.1 导入JS依赖 2.2 定义两个组件 2.3 定义组件与路径对应关系 2.4 通过路由关系获取路由对象 2.5 将对象挂载到vue实例中 2.6 定义触发路由事件的按钮 2.7 定…...

腾讯云16核服务器性能测评_轻量和CVM配置大全

腾讯云16核服务器配置大全&#xff0c;CVM云服务器可选择标准型S6、标准型SA3、计算型C6或标准型S5等&#xff0c;目前标准型S5云服务器有优惠活动&#xff0c;性价比高&#xff0c;计算型C6云服务器16核性能更高&#xff0c;轻量16核32G28M带宽优惠价3468元15个月&#xff0c;…...

Postman应用——下载注册和登录

文章目录 下载安装注册登录注册账号登录账号 下载安装 Postman下载&#xff1a;https://www.postman.com/ 访问链接后&#xff0c;进入首页&#xff0c;根据自己的操作系统下载对应的版本。 找到下载到的目录直接双击.exe文件&#xff0c;会默认安装在C盘&#xff0c;安装完会…...

uni-app混合开发 navigateTo、reLaunch、redirectTo、switchTab区别

1.navigateTo 保留当前页面&#xff0c;跳转到应用内的某个页面&#xff0c;使用uni.navigateBack可以返回到原页面。 要注意的是navigateTo只能跳转的应用内非 tabBar 的页面的路径 , 路径后可以带参数&#xff1b;如果跳转url参数为tabBar的路径则无法进行跳转 2.redir…...

专业软件测评中心:关于软件性能测试的实用建议

软件性能测试是通过自动化的测试工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指标进行测试。性能测试在软件的质量保证中起着重要的作用&#xff0c;它包括的测试内容丰富多样。 一、软件性能测试的实用建议   1、制定清晰的测试目标&#xff1a;明确测试目标…...

vue项目通过json-bigint在前端处理java雪花id过长导致失去精度问题

这里 我简单模仿了一个接口 这里 我单纯 返回一个long类型的雪花id 然后 前端 用 axios 去请求 大家知道 axios 会对请求数据做一次处理 而我们 data才是拿到我们java这边实际返回的东西 简单说 就是输出一下我们后端返回 的内容 这里 我们网络中显示的是 35866101868095488…...

【全志V3s】SPI NAND Flash 驱动开发

文章目录 一、硬件介绍V3s的启动顺序 二、驱动支持U-Boot驱动主线 Linux 驱动已经支持 三、烧录工具 xfel四、构建U-Boot&#xff08;官方的Uboot&#xff09;先编译一下开始spi nand flash 代码层面的适配修改menuconfig配置ARM architecture配置Support for SPI Nand Flash o…...

【二叉树】二叉树展开为链表-力扣 114 题

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…...

NLP文本生成全解析:从传统方法到预训练完整介绍

目录 1. 引言1.1 文本生成的定义和作用1.2 自然语言处理技术在文本生成领域的使用 2 传统方法 - 基于统计的方法2.1.1 N-gram模型2.1.2 平滑技术 3. 传统方法 - 基于模板的生成3.1 定义与特点3.2 动态模板 4. 神经网络方法 - 长短时记忆网络(LSTM)LSTM的核心概念PyTorch中的LST…...

wordpress jitpecj插件/怎么根据视频链接找到网址

2021 年 9 月 29 日 Stephan Ewen ( StephanEwen ) 和 Johannes Moser ( joemoeAT ) Apache 软件基金会最近发布了年度报告&#xff0c;Apache Flink 再次跻身最活跃项目前 5 名&#xff01;这一非凡的活动也体现在新的 1.14.0 版本中。200 多名贡献者再次致力于解决 1,000 多…...

建设银行官方网站买五粮液酒/品牌推广的目的和意义

效果预览 按下右侧的“点击预览”按钮可以在当前页面预览&#xff0c;点击链接可以全屏预览。 https://codepen.io/comehope/pen/PdaNXw 可交互视频 此视频是可以交互的&#xff0c;你可以随时暂停视频&#xff0c;编辑视频中的代码。 请用 chrome, safari, edge 打开观看。 ht…...

做网站应规避的风险/媒体推广

本文同步发表在我的个人博客中&#xff1a;沧沧凉凉​www.cclliang.com随着前端的飞速发展&#xff0c;现在制作界面时出现了非常多的好看的样式&#xff0c;比如说全屏滚动效果&#xff0c;能够带来很舒服的视觉体验。先来看一下什么是全屏滚动&#xff1a;这是fullpage.js的官…...

河南科技园网站建设/河南网络推广公司

DevC++:下载地址 如果你的系统没有安装Mingw编译器,那就下载带有TDM-GCC的安装版,自带gcc编译器,而不是No Compiler的版本 gtkbundle-2.12.11-20080720.zip:下载地址 将下载后的gtkbundle-2.12.11-20080720.zip解压,将其中的bin目录加入windows环境变量path目录中 打开…...

网站转微信小程序/emlog友情链接代码

单元测试&#xff08;模块测试&#xff09;是开发者编写的一小段代码&#xff0c;用于检验被测代码的一个很小的、很明确的功能是否正确。通常而言&#xff0c;一个单元测试是用于判断某个特定条件&#xff08;或者场景&#xff09;下某个特定函数的行为。例如&#xff0c;你可…...

吗网站建设/合肥网络推广网络运营

[TOC]下面向大家介绍几个python算法题。 一&#xff1a;二分法求平方根1.题目要求为2.输入输出格式为3.博主解题的思路这道题在c语言中是一道经典的题目&#xff0c;可以用循环&#xff0c;或者递归&#xff0c;在这里我们用python来写。无论是循环还是递归&#xff0c;都是下面…...