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

手写 vue 源码 ===:自定义调度器、递归调用规避与深度代理

目录

引言

自定义调度器(Scheduler)

什么是调度器?

调度器的实现原理

自定义调度器的实际应用

切面编程(AOP)思想在调度器中的应用

递归调用规避

递归调用的问题

Vue 如何规避递归调用

深度代理(Deep Proxy)

什么是深度代理?

Vue 中的深度代理实现

bind 方法的应用

bind 方法的作用

为什么需要 bind?

总结


 

引言

在上一篇文章中,我们深入探讨了 Vue 响应式系统中的依赖清理机制。本文将继续深入 Vue 响应式系统的其他高级特性,包括自定义调度器、递归调用规避、深度代理等,并探讨其中涉及的bind方法、切面编程思想以及递归实现流程。

自定义调度器(Scheduler)

什么是调度器?

调度器是 Vue 响应式系统中的一个重要概念,它允许我们控制 effect 的执行时机和方式。当响应式数据发生变化时,默认情况下会立即触发相关的 effect 执行。而通过自定义调度器,我们可以改变这一默认行为。

调度器的实现原理

在 Vue 的响应式系统中,调度器是通过 effect函数的第二个参数传入的:

export function effect(fn, options: any = {}) {// 创建一个 effect 只要依赖的属性变化,就会重新执行const _effect = new ReactiveEffect(fn, () => {_effect.run();});// 执行_effect.run();if (options) {Object.assign(_effect, options); //用用户传入的配置,来覆盖默认的配置}const runner = _effect.run.bind(_effect); //bind 改变this指向 并且返回一个函数runner.effect = _effect; //将effect挂载到runner上return runner;
}

当我们创建一个ReactiveEffect 实例时,可以传入一个调度器函数作为第二个参数。当响应式数据变化触发 effect 执行时,会先检查是否有调度器,如果有则执行调度器而不是直接执行 effect:

export function triggerEffects(dep) {for (let effect of dep.keys()) {// 如果不是正在执行,那么就执行调度器if (!effect._runing) {if (effect.scheduler) {effect.scheduler();}}}
}

自定义调度器的实际应用

让我们看一个实际的例子,展示如何使用自定义调度器:

//调度器
let runner = effect(() => {document.body.innerHTML = `<h1>${state.flag ? state.name : state.age}</h1>`
}, {scheduler: () => {console.log('scheduler执行了,不自动更新');//AOP 面向切面编程runner() //重新渲染}
})

在这个例子中,我们创建了一个 effect 并传入了一个自定义调度器。当响应式数据变化时,不会直接执行 effect 的回调函数,而是先执行调度器函数。在调度器函数中,我们可以决定是否执行 effect,或者何时执行 effect。

切面编程(AOP)思想在调度器中的应用

上面的例子中提到了 AOP(面向切面编程)。AOP 是一种编程范式,它允许我们在不修改原有代码的情况下,通过"切面"的方式添加新的行为。

在 Vue 的响应式系统中,调度器就是一个典型的 AOP 应用:

  1. 原始行为:响应式数据变化时执行 effect
  2. 切面:调度器函数
  3. 新行为:响应式数据变化时先执行调度器,由调度器决定何时执行 effect

这种设计使得我们可以在不修改 Vue 核心代码的情况下,灵活地控制 effect 的执行方式,例如:

  • 延迟执行 effect(使用 setTimeout
  • 批量执行 effect(收集多个变化后一次性执行)
  • 条件执行 effect(根据某些条件决定是否执行)

递归调用规避

递归调用的问题

在响应式系统中,如果在 effect 中修改了触发该 effect 的响应式数据,就会导致递归调用,例如:

effect(() => {state.count = state.count + 1
})

这段代码会导致无限循环:读取 state.count 会收集依赖,修改 state.count 会触发依赖执行,而依赖执行又会修改 state.count,如此循环往复。

Vue 如何规避递归调用

Vue 通过在ReactiveEffect类中添加一个_runing 标志来规避递归调用:

class ReactiveEffect {_trackId = 0; // 当前的 effect 执行了几次deps = []; // 当前的 effect 依赖了哪些属性_depsLength = 0; // 当前的 effect 依赖的属性有多少个_runing = 0; // 当前的 effect 是否在执行public active = true; //默认是响应式的constructor(public fn, public scheduler) {}run() {// 如果当前状态是停止的,执行后,啥都不做if (!this.active) {return this.fn();}let lastEffect = activeEffect;try {activeEffect = this; // 当前的 effect 「依赖收集」// 每次执行前需要将上一次的依赖清空 effect.depspreCleanEffect(this);this._runing++; //执行前,将当前的effect设置为正在执行return this.fn(); //依赖收集 「state.name ,state.age」} finally {this._runing--; //执行后,将当前的effect设置为未执行postCleanEffect(this);activeEffect = lastEffect; // 执行完毕后 恢复上一次的 activeEffect}}
}

在 run 方法中,执行前将 _runing 设为 1,执行后将 _runing 设为 0。在 triggerEffects 函数中,会检查 effect 是否正在执行,如果是则不触发:

export function triggerEffects(dep) {for (let effect of dep.keys()) {// 如果不是正在执行,那么就执行调度器if (!effect._runing) {if (effect.scheduler) {effect.scheduler();}}}
}

深度代理(Deep Proxy)

什么是深度代理?

深度代理是指不仅对对象本身进行代理,还对对象的嵌套属性(如果是对象)也进行代理。这样,无论访问对象的哪一层属性,都能触发依赖收集和更新。

Vue 中的深度代理实现

Vue 的深度代理是在 getter 中实现的:

export const mutableHandlers: ProxyHandler<any> = {get(target: any, key: any, receiver: any) {// 如果访问的是代理对象的属性,直接返回if (key === ReactiveFlags.IS_REACTIVE) {return true;}// 依赖收集「收集这个对象上的这个属性,和 effect 关联」// 「当取值的时候,应该让 响应式属性,和 effect 建立联系」track(target, key);let res = Reflect.get(target, key, receiver); // 等价于receiver[key]if (isObject(res)) {// 如果取值是对象,则递归代理return reactive(res);}return res;},
}

深度代理的递归流程如下:

  • 调用 reactive(obj) 创建一个代理对象
  • 当访问代理对象的属性时,触发 get 方法
  • 在 get 方法中,先进行依赖收集
  • 然后获取属性值 res
  • 如果 res 是一个对象,则调用 reactive(res) 对其进行代理
  • 返回代理后的对象

这样,当我们访问嵌套属性时,例如 state.address.city,会发生以下过程:

  • 访问 state.address,触发 state 的 get 方法
  • 在 get 方法中,获取 address 属性,发现它是一个对象,调用 reactive(address) 创建代理
  • 返回 address 的代理对象
  • 访问 address 代理对象的 city 属性,触发 address 代理对象的 get 方法
  • 在 get 方法中,获取 city 属性,它不是对象,直接返回

通过这种递归的方式,Vue 实现了对嵌套对象的深度代理。
 

// 深度监听
effect(() => {document.body.innerHTML = state.address.city
})setTimeout(() => {state.address.city = "上海"
}, 1000)

在这个例子中,我们创建了一个 effect,它依赖于 state.address.city。当我们修改 state.address.city 时,effect 会重新执行,更新页面内容。

这是因为 state.address 是一个代理对象,当我们访问 state.address.city 时,会触发 state.address 的 get 方法,从而收集依赖。当我们修改 state.address.city 时,会触发

state.address 的 set 方法,从而触发依赖更新。

bind 方法的应用

在 Vue 的响应式系统中,bind 方法被用于创建 effect 的运行器(runner)

export function effect(fn, options: any = {}) {// 创建一个 effect 只要依赖的属性变化,就会重新执行const _effect = new ReactiveEffect(fn, () => {_effect.run();});// 执行_effect.run();if (options) {Object.assign(_effect, options); //用用户传入的配置,来覆盖默认的配置}const runner = _effect.run.bind(_effect); //bind 改变this指向 并且返回一个函数runner.effect = _effect; //将effect挂载到runner上return runner;
}

bind 方法的作用

bind 方法是 JavaScript 中函数对象的一个方法,它创建一个新函数,该函数的 this 被绑定到指定的值。在 Vue 的响应式系统中, bind 方法的作用是:

  • 创建一个新函数 runner,它的 this 被绑定到 _effect
  • 这样,无论在哪里调用 runner,它内部的 this 都指向 _effect
  • 这确保了 runner 可以正确地访问 _effect 的属性和方法

为什么需要 bind?

在 JavaScript 中,函数的 this 值取决于函数的调用方式,而不是函数的定义方式。如果我们直接返回 _effect.run,那么当调用这个函数时,this 可能不指向 _effect,导致错误。

通过使用 bind,我们确保了无论如何调用 runner,它内部的 this 都指向 _effect,从而保证了函数的正确执行。

总结

本文深入探讨了 Vue 响应式系统的几个高级特性:

  1. 自定义调度器:通过调度器,我们可以控制 effect 的执行时机和方式,实现更灵活的响应式行为。这是 AOP(面向切面编程)思想在 Vue 中的一个应用。
  2. 递归调用规避:Vue 通过在 effect 执行前后设置标志位,避免了在 effect 中修改响应式数据导致的递归调用问题。
  3. 深度代理:Vue 通过在 getter 中递归调用  reactive 函数,实现了对嵌套对象的深度代理,使得无论访问对象的哪一层属性,都能触发依赖收集和更新。
  4. bind 方法的应用:Vue 使用  bind 方法创建 effect 的运行器,确保了无论在哪里调用运行器,它内部的 this 都指向正确的 effect 实例。

通过理解这些高级特性,我们可以更深入地理解 Vue 响应式系统的工作原理,以及如何利用这些特性构建更高效、更灵活的 Vue 应用。

在实际开发中,虽然我们可能不需要直接操作这些底层 API,但了解它们的工作原理,可以帮助我们更好地理解 Vue 的响应式系统,以及在遇到复杂问题时进行调试和优化。

    相关文章:

    手写 vue 源码 ===:自定义调度器、递归调用规避与深度代理

    目录 引言 自定义调度器&#xff08;Scheduler&#xff09; 什么是调度器&#xff1f; 调度器的实现原理 自定义调度器的实际应用 切面编程&#xff08;AOP&#xff09;思想在调度器中的应用 递归调用规避 递归调用的问题 Vue 如何规避递归调用 深度代理&#xff08;D…...

    WPF实时调试的一种实现方法

    在WPF程序中&#xff0c;如果我们需要对程序进行调试&#xff0c;一般是使用断点/单步或输出日志之类的调试方法。 如果我们需要实时查看程序输出&#xff0c;可以将程序的输出类型修改为控制台应用程序 这样我们在程序运行后&#xff0c;就可以得到一个控制台窗口。 然后再配…...

    数据库操作

    本篇会加入个人的所谓鱼式疯言 ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人能接…...

    学习笔记:数据库——事务

    1.内容&#xff1a; 基于现有数据库设计检查点实验&#xff0c;观察比较提交前后执行结果并分析。 2.实现 源码 -- 开启事务 START TRANSACTION;-- 插入一条订单记录&#xff08;客户ID为10002&#xff09; INSERT INTO orders (o_date, c_id) VALUES (NOW(), 10002);-- 获…...

    企业级可观测性实现:OpenObserve云原生平台的本地化部署与远程访问解析

    文章目录 前言1. 安装Docker2. 创建并启动OpenObserve容器3. 本地访问测试4. 公网访问本地部署的OpenObserve4.1 内网穿透工具安装4.2 创建公网地址 5. 配置固定公网地址 前言 嘿&#xff0c;各位小伙伴们&#xff0c;今天要给大家揭秘一个在云原生领域里横扫千军的秘密法宝—…...

    【Linux系统】第三节—权限

    Hello&#xff0c;好久不见—— 云边有个稻草人-CSDN个人博客主页 Linux-本节文章所属专栏-欢迎订阅-持续更新中~~~ 目录 hi&#xff01;在这里—本节课重要知识点详解 一、Shell命令以及运行原理 二、Linux权限 2.1 Linux权限的概念 2.2 Linux权限管理 2.3 ⽂件权限值的…...

    @Data和 @NoArgsConstructor注解详解

    Data 和 NoArgsConstructor 注解详解 1. Data 注解 作用&#xff1a;Data 是 Lombok 提供的一个复合注解&#xff0c;用于自动生成 Java 类的常用方法&#xff0c;减少样板代码。生成的内容&#xff1a; Getter 和 Setter&#xff1a;为所有非静态、非 final 字段生成 getter…...

    《云计算》第三版总结

    《云计算》第三版总结 云计算体系结构 云计算成本优势 开源云计算架构Hadoop2.0 Hadoop体系架构 Hadoop访问接口Hadoop编程接口 Hadoop大家族 分布式组件概述ZooKeeperHbasePigHiveOozieFlumeMahout 虚拟化技术 服务器虚拟化存储虚拟化网络虚拟化桌面虚拟化OpenStack开源虚…...

    滚珠导轨:电子制造领域精密运动的核心支撑

    电子制造正朝着高精度、高效率方向飞速发展&#xff0c;滚珠导轨在这一进程中扮演着重要角色。滚珠导轨在电子制造领域中具有广泛且重要的应用&#xff0c;主要体现在以下几个方面&#xff1a; 1、印刷电路板&#xff08;PCB&#xff09;制造设备&#xff1a;滚珠导轨在PCB制造…...

    Spark缓存--cache方法

    在Spark 中&#xff0c;cache() 是用于优化计算性能的核心方法之一&#xff0c;但它有许多细节需要深入理解。以下是关于 cache() 的详细技术解析&#xff1a; 1. cache() 的本质 简化的 persist()&#xff1a;cache() 是 persist(StorageLevel.MEMORY_ONLY) 的快捷方式&#x…...

    kafka logs storage

    Kafka 会将日志文件按段&#xff08;Segment&#xff09;存储。 Segment是Kafka的最小存储单元&#xff0c;它是一个可追加的文件&#xff0c;用于存储Kafka分区中的一部分消息。 在文件系统中&#xff0c;Partition 是目录名&#xff0c;而Segment 是文件名。 Segment可以通过…...

    数据分析平台选型与最佳实践:如何打造高效、灵活的数据生态?

    数据分析平台选型与最佳实践:如何打造高效、灵活的数据生态? 在大数据时代,数据分析平台已经成为企业决策的核心支撑。从传统 BI(商业智能)到现代 AI 驱动的数据分析,选择合适的平台不仅影响数据处理效率,也决定了企业的数字化竞争力。面对市场上的众多解决方案(如 Ap…...

    MYSQL之索引结构,为何要用B+树

    索引的目的就是为了提高查询效率 索引的结构是B树&#xff0c;那么说到B树&#xff0c;必须提一下其他三种结构&#xff0c;分别是&#xff1a;二叉查找树、平衡二叉树、B树 我们来看看各自的结构特征 二叉查找树 特点:任何节点的左子节点的值都小于当前节点的值&#xff0c;右…...

    OpenCV 中用于背景分割的一个类cv::bgsegm::BackgroundSubtractorLSBP

    操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 cv::bgsegm::BackgroundSubtractorLSBP 是 OpenCV 中用于背景分割的一个类&#xff0c;它基于局部样本二进制模式&#xff08;Local Sample Bina…...

    【PmHub后端篇】PmHub Gateway全局过滤器:接口调用耗时统计及黑白名单配置技术深度解析

    在微服务架构日益成为现代应用开发主流模式的背景下&#xff0c;网关作为微服务架构前端的关键组件&#xff0c;肩负着路由请求、负载均衡、安全认证、流量控制、监控和日志记录等多项重要任务。本文将围绕PmHub项目中Gateway全局过滤器实现接口调用耗时统计的相关技术进行深入…...

    国产激光二极管厂家

    中国在激光二极管&#xff08;Laser Diode&#xff09;领域已有多家厂商布局&#xff0c;涵盖从低功率到高功率、不同波长的产品&#xff0c;应用于工业、医疗、通信、消费电子等领域。以下是部分国产激光二极管厂家及相关信息&#xff0c;供参考&#xff1a; 1. 武汉锐科光纤…...

    安卓基础(XML)

    123 属性​​​​行为​​​​适用场景​​​​注意事项​​match_parent填满父容器可用空间全屏视图、占满剩余空间父容器需有固定尺寸wrap_content根据内容自适应尺寸动态文本、图标、浮动按钮内容过长时可能超出父容器需处理 123 ​​属性​​​​作用​​​​常用值​​…...

    uniapp|获取当前用户定位、与系统设定位置计算相隔米数、实现打卡签到(可自定义设定位置、位置有效范围米数)

    基于UniApp阐述移动应用开发中定位功能的实现全流程,涵盖实时定位获取、动态距离计算与自定义位置、有效范围设定等功能。文章提供完整的代码示例与适配方案,适用于社交签到、课堂教室打卡等场景。 目录 引言定位功能在移动应用中的价值(社交、导航、O2O等场景)UniApp跨平台…...

    matlab稳定求解高精度二维对流扩散方程

    利用MATLAB稳定求解高精度二维对流扩散方程 Diffusion_1D.m , 2310 Diffusion_2D.m , 3813 license.txt , 1334...

    【最新版】likeshop连锁点餐系统-PHP版+uniapp前端全开源

    一.系统介绍 likeshop外卖点餐系统适用于茶饮类的外卖点餐场景&#xff0c;搭建自己的一点点、奈雪、喜茶点餐系统。 系统基于总部多门店的连锁模式&#xff0c;拥有门店独立管理后台&#xff0c;支持总部定价和门店定价LBS定位点餐&#xff0c;可堂食可外卖。无论运营还是二开…...

    Redis 重回开源怀抱:开源精神的回归与未来展望

    在开源软件的广袤天地里&#xff0c;Redis 一直是备受瞩目的明星项目。近期&#xff0c;Redis 宣布重新回归开源&#xff0c;这一消息犹如一颗石子投入平静的湖面&#xff0c;在技术社区激起层层涟漪。今天&#xff0c;就让我们深入了解 Redis 这一重大转变背后的故事、意义以及…...

    mac运行java文件提示 错误: 缺少 JavaFX 运行时组件, 需要使用该组件来运行此应用程序

    1、问题如上 双击java文件打不开&#xff0c;命令行报错。查找了下文章说java8之后&#xff0c;高版本jdk不自带javafx&#xff0c;需要自己下载 2、解决办法 首先查看自己的java版本&#xff0c;我是17.0.10 访问 JavaFX - Gluon 下载对应的版本&#xff0c;如果没有对应的 …...

    pimpl与unique_ptr的问题

    PImpl与std::unique_ptr组合 pimpl(Pointer to Implementation)是C程序开发中非常常用的技巧之一&#xff0c;它的好处有&#xff1a; 节省程序编译时间保持程序/库的二进制兼容性隐藏实现细节 举例一个常见的pimpl的使用示例&#xff1a; // a.h class Impl; //前置声明 c…...

    Opencv进阶操作:图像拼接

    文章目录 前言一、图像拼接的原理1. 特征提取与匹配2. 图像配准3. 图像变换与投影4. 图像融合5. 优化与后处理 二、图像拼接的简单实现&#xff08;案例实现&#xff09;1.引入库2.定义cv_show()函数3.创建特征检测函数detectAndDescribe()4.读取拼接图片5.计算图片特征点及描述…...

    记录Token反序列化OAuth2Authentication(主要是直接存储用户信息的UserDetails )

    项目场景&#xff1a; 本地开发环境部署了多套系统&#xff0c;并且使用了同一套登入鉴权组件&#xff0c;存入的TokenStore也是相同的Redis库&#xff1b; 问题描述&原因分析 由于是做的不同项目&#xff0c;group等组织机构不同&#xff0c;导致多系统若是有存储相同用…...

    【QT】深入理解 Qt 中的对象树:机制、用途与最佳实践

    深入理解 Qt 中的对象树&#xff1a;机制、用途与最佳实践 在使用 Qt 编程时&#xff0c;你是否注意到很多对象可以设置“父对象”&#xff1f;比如&#xff1a; QPushButton* btn new QPushButton(parentWidget);这不是简单的层级结构&#xff0c;而是 Qt 强大而优雅的 对象…...

    基于FPGA的血氧和心率蓝牙监测系统设计-max30102

    文章目录 前言一、芯片手册分析二、串口接口的血氧模块使用讲解三、仿真时序分析四、代码分析1.蓝牙数据发送2.心率数据采集 总结 前言 本产品的核心是基于心率传感器的智能心率监测系统&#xff0c;通过硬件端的心率传感器获取人体的心率和血氧浓度等信息&#xff0c;并进行实…...

    华为首款鸿蒙电脑正式亮相,开启国产操作系统新篇章

    5 月 8 日&#xff0c;华为在深圳举办鸿蒙电脑技术与生态沟通会&#xff0c;正式推出了备受瞩目的首款鸿蒙电脑&#xff0c;这一重大举措标志着国产操作系统在个人电脑&#xff08;PC&#xff09;领域实现了关键突破&#xff0c;为行业发展注入了新的活力。​ 历经五年打磨&…...

    Docker部署常见应用之Superset

    文章目录 使用 Docker 部署使用 Docker Compose 部署参考文章 以下是使用 Docker 部署 Superset 并将存储配置为 MySQL 的详细步骤&#xff1a; 使用 Docker 部署 获取Superset镜像: 使用Docker从官方仓库拉取Superset镜像&#xff1a;docker pull apache/superset:4.0.0创建 …...

    触想CX-3588工控主板应用于移动AI数字人,赋能新型智能交互

    一、行业发展背景 随着AI智能、自主导航和透明屏显示等技术的不断进步&#xff0c;以及用户对“拟人化”、“沉浸式”交互体验的期待&#xff0c;一种新型交互终端——“移动AI数字人”正在加速实现规模化商用。 各大展厅展馆、零售导购、教学政务甚至家庭场景中&#xff0c;移…...

    关系代数操作之复杂扩展操作

    除&#xff08;Division&#xff09; 定义&#xff1a;关系R为n度关系&#xff0c;关系S为m度关系&#xff0c;m<n,记作RS&#xff0c;关系是K&#xff08;n-m&#xff09;度关系 数学描述&#xff1a; 相当于&#xff08;RS&#xff09;*S在R中的元组 外连接&#xff08…...

    STM32G070xx将Flash页分块方式存储,固定数据块存储,实现一次擦除多次写入

    STM32G070xx将Flash页分块方式存储&#xff0c;固定数据块存储&#xff0c;实现一次擦除多次写入 参考例程例程说明一、存储区数据结构二、读取存储区数据三、写入存储区数据四、测试函数五、测试结果 参考例程 STM32G0xx使用LL库将Flash页分块方式存储数据实现一次擦除可多次…...

    V4L2应用程序开发-- 控制流程

    使用摄像头时&#xff0c;我们可以调整很多参数&#xff0c;比如&#xff1a; 对于视频流本身&#xff1a; 设置格式&#xff1a;比如V4L2_PIX_FMT_YUYV、V4L2_PIX_FMT_MJPEG、V4L2_PIX_FMT_RGB565 设置分辨率&#xff1a;1024*768等 对于控制部分&#xff1a; 调节亮度 调…...

    《大数据技术之Scala》

    这是一篇关于大数据技术中Scala语言的基础教程文章&#xff0c;主要介绍了Scala语言的发展历史、与Java的关系、语言特点、环境搭建、插件安装、编程基础、变量和数据类型、运算符、流程控制、函数式编程、面向对象编程、集合操作、模式匹配、异常处理、隐式转换和泛型等核心内…...

    使用thymeleaf模版导出swagger3的word格式接口文档

    1.pom配置 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.8.RELEASE</version></parent><properties><skipTests>true</skipTests&g…...

    Android RecyclerView自带的OnFlingListener,Kotlin

    Android RecyclerView自带的OnFlingListener&#xff0c;Kotlin Android启动应用时屏蔽RecyclerView滑动&#xff0c;延时后再允许滑动&#xff0c;Kotlin-CSDN博客 使用了GestureDetectorRecyclerView的setOnTouchListener检测用户的快滑fling事件。发现RecyclerView也自带了监…...

    STM32+安信可Ai-WB2-12F连接阿里云物联网平台

    第一步&#xff1a;在阿里云物联网平台创建设备 具体操作流程如下 第二步&#xff1a;生成个人client_id,用户名和密码 打开该软件sign.html 将刚才复制的信息粘贴进去 生成自己的client_id,用户名和密码 第三步&#xff1a;打开MQTTfx软件 电机connect旁边的配置&#xff0…...

    Python实现中文数字与阿拉伯数字映射生成器(支持0-9999)

    文章目录 1. 引言2. 需求分析‌3. 核心实现思路‌4. 完整代码实现‌ 1. 引言 在中文文本处理和自然语言处理(NLP)应用中&#xff0c;经常需要将中文数字转换为阿拉伯数字。本文将介绍如何使用Python根据用户从控制台输入的数字范围&#xff0c;生成相应的中文数字到阿拉伯数字…...

    链表的面试题4之合并有序链表

    这篇文章我们继续来讲链表中很经典的面试题&#xff1a;合并有序链表。 目录 迭代 递归 我们首先来看一下这张图片里面的要求&#xff0c;给你两个链表&#xff0c;要求把他们按照从小到大的方式排列。 这里涉及到几个问题&#xff0c;首先&#xff0c;我们的头节点是不是要…...

    CTF - PWN之ORW记录

    CTF - Pwn之ORW记录https://mp.weixin.qq.com/s/uiRtqCSopn6U6NqyKJ8I7Q...

    mission planner烧录ardupilot固件报错死机

    问题 烧录自己编译的固件&#xff0c;upload done成功后&#xff0c;又跳出以下提示 &#xff0c;返回重新烧录仍然报错 解决 先烧录官方稳定的固件然后使用mission planner连接&#xff0c;此时可能会反复识别串口&#xff0c;因为会死机反复重启&#xff0c;导致灯闪烁又…...

    单片机嵌入式滤波算法库

    kw_ucFiltering库说明 本科针对常用的滤波算法进行汇总&#xff0c;主要包括&#xff1a; 一阶滤波算法 平滑滤波 中位值滤波 限幅 卡尔曼滤波 截至目前&#xff08;20250508&#xff09;滤波算法持续更新中。 本库开源连接地址&#xff1a;gitee连接 一阶滤波算法实现 原理…...

    CAS、CAS自旋、CAS自旋锁、CLH锁与Java AQS:深入理解并发编程核心机制

    CAS、CAS自旋、CAS自旋锁、CLH锁与Java AQS&#xff1a;深入理解并发编程核心机制 1. CAS&#xff08;Compare and Swap&#xff09; 什么是CAS&#xff1f; CAS&#xff08;Compare and Swap&#xff09;是一种无锁&#xff08;Lock-Free&#xff09;的原子操作&#xff0c;…...

    《运维那些事儿》专栏总目录(持续更新)

    《运维那些事儿》专栏以Linux系统为基础&#xff0c;分享作者十年运维生涯中运用到的关键技术要点。本专栏涵盖消息中间件、数据中间件、数据库、虚拟化、Web服务器、高可用架构等运维工作中涉及到的相关内容&#xff0c;每周持续交叉更新一篇高质量技术博文。学生可用于了解、…...

    鸿蒙NEXT开发动画案例4

    1.创建空白项目 2.Page文件夹下面新建Spin.ets文件&#xff0c;代码如下&#xff1a; /*** TODO SpinKit动画组件 - 双粒子旋转缩放动画* author: CSDN-鸿蒙布道师* since: 2025/05/08*/ ComponentV2 export struct SpinFour {// 参数定义Require Param spinSize: number 36…...

    【Linux学习笔记】基础IO之理解文件

    【Linux学习笔记】基础IO之理解文件 &#x1f525;个人主页&#xff1a;大白的编程日记 &#x1f525;专栏&#xff1a;Linux学习笔记 前言 哈喽&#xff0c;各位小伙伴大家好!上期我们讲了进程替换 今天我们讲的是基础IO之理解文件。话不多说&#xff0c;我们进入正题&#…...

    动态计算el-table高度

    form、搜索框、底部导航栏设置class <el-table :height"tableHeight" /> // 计算表格高度的计算属性 const tableHeight ref(0); proxy.toTableHeight((res)>{tableHeight.value res; });tableHeight.js import { nextTick } from vue;export fun…...

    【Linux系列】目录大小查看

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

    数据结构*二叉树

    树 树是一种非线性数据结构。 这就是抽象的树的结构。 对于一棵树来说&#xff0c;有N个结点&#xff0c;就有N-1条边 其中有许多概念&#xff1a; 根结点&#xff1a;对于上图来说就是A 子树&#xff1a;就是结点下面分开的部分。例如&#xff1a;A的子树就是以B为根结点的…...

    RESTful

    一&#xff1a;简介 定义 &#xff08;1&#xff09;访问网络资源的格式 &#xff08;2&#xff09;优点 &#xff08;3&#xff09;区分操作 &#xff08;4&#xff09;注意事项...