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

Vue2 vs Vue3:核心原理与性能优化详解

在这里插入图片描述

Vue2 vs Vue3:核心原理与性能优化详解

​Vue.js 是目前主流的前端框架之一,随着 Vue3 的发布,框架内部的实现和使用方式都发生了显著变化。本文将从 Vue2 和 Vue3 的核心实现原理出发,详细解析两者的区别,并分析 Vue3 的改进背后的技术考量。


一、Vue2 与 Vue3 的核心区别概览

1. 设计理念的不同

Vue2 和 Vue3 在设计理念上的不同,主要体现在它们的核心 API 和逻辑组织方式上。这种差异直接影响了开发体验、代码的可维护性以及在复杂项目中的表现。


1.1 Vue2 的设计理念:基于 Options API

Vue2 的核心是基于 Options API 的设计,这种方式通过明确的配置选项将组件的逻辑、数据、方法、生命周期等分开组织。开发者只需要按照固定的规则,将代码填入对应的选项即可完成开发。

代码示例(Vue2 Options API)

export default {data() {return {message: 'Hello, Vue2!',};},methods: {handleClick() {console.log(this.message);},},created() {console.log('Component created');},
};
1.1.1 优点
  1. 简单易用:清晰的 API 设计让入门开发者能够快速上手。
  2. 逻辑分区明确:通过 datamethodscreated 等选项,将不同职责的代码划分到不同区域,方便管理。
  3. 适合小型项目:对于功能简单的组件,这种分离逻辑的方式清晰明了。
1.1.2 缺点
  1. 逻辑分散
    在复杂组件中,如果某个功能涉及多个选项(如数据、计算属性、生命周期等),逻辑会被分散在多个区域,导致代码阅读和维护变得困难。

    示例
    如果一个表单的功能涉及状态管理、验证逻辑和提交操作,这些代码可能分布在 datamethodswatch 中,调试时需要频繁跳转。

  2. 复用性较低
    Options API 中的逻辑通常是绑定到特定组件的,跨组件复用逻辑需要借助混入(Mixins)或高阶函数等手段。这些方法有时会导致逻辑冲突或命名污染。

  3. 扩展性不足
    随着组件复杂度的提升,Options API 的组织方式显得笨拙,代码不够灵活,难以满足复杂场景的需求。


1.2 Vue3 的设计理念:基于 Composition API

Vue3 引入了 Composition API,它采用更加灵活的函数式组织方式,打破了 Options API 的限制,将与功能相关的代码集中在一起,形成独立的逻辑单元。

代码示例(Vue3 Composition API)

import { ref, onMounted } from 'vue';export default {setup() {const message = ref('Hello, Vue3!');const handleClick = () => {console.log(message.value);};onMounted(() => {console.log('Component mounted');});return {message,handleClick,};},
};
1.2.1 优点
  1. 逻辑聚合
    Composition API 允许将相关逻辑集中到一个函数或一组函数中,从而提高了代码的可读性和维护性。

    示例
    在表单场景中,可以将表单状态、验证和提交操作全部集中在一个逻辑单元中,而不是分散在多个选项中。

  2. 高复用性
    通过定义 Composable 函数,可以将独立的逻辑抽取成通用模块,在多个组件中复用,而无需担心命名冲突或逻辑冲突。

    示例

    // useCounter.js
    import { ref } from 'vue';export function useCounter() {const count = ref(0);const increment = () => count.value++;return { count, increment };
    }
    
    // 在组件中使用
    import { useCounter } from './useCounter';export default {setup() {const { count, increment } = useCounter();return { count, increment };},
    };
    
  3. 更强的扩展性
    Composition API 以函数为核心,可以轻松结合 TypeScript 实现更严格的类型检查,适应复杂项目的需求。

  4. 提升代码的模块化
    每个功能单元都可以抽象为独立模块,减少代码耦合度,提高开发效率。

1.2.2 缺点
  1. 学习曲线陡峭
    Composition API 的灵活性要求开发者具备更高的编程能力,特别是对 JavaScript 的函数式编程思想有一定了解。
  2. 较高的心智负担
    在一些简单项目中,Composition API 可能显得过于复杂,不如 Options API 简单直观。

1.3 Vue2 与 Vue3 的设计理念对比
对比维度Vue2(Options API)Vue3(Composition API)
逻辑组织方式逻辑分散在多个选项中逻辑集中在相关函数中
代码复用借助 Mixins 或高阶函数,可能有命名冲突使用 Composable 函数,复用性更高
复杂项目的适应性逻辑分散,扩展性不足模块化设计,适合复杂场景
学习难度易于上手,规则固定灵活强大,但学习曲线较陡峭
与 TypeScript 兼容性支持有限,类型推断不完善更自然的支持 TypeScript

1.4 总结

​ Vue2 的 Options API 提供了明确的规则和组织方式,适合初学者和小型项目,但在复杂项目中扩展性不足。而 Vue3 的 Composition API 是一种更现代化的设计思路,灵活性和可扩展性更强,特别适合需要高复用性和模块化设计的大型项目。尽管学习成本较高,但其强大的功能和适应性使得 Vue3 成为现代前端开发的理想选择。

2. 性能优化:静态树提升(Static Tree Hoisting)和动态节点追踪(Dynamic Node Tracking)

​ Vue3 的性能提升,除了响应式系统的革新外,还得益于更高效的 模板编译优化,其中 静态树提升动态节点追踪 是两项关键技术。这两者对虚拟 DOM 的生成和更新过程进行了深层次优化,减少了不必要的开销,极大提升了运行时性能。以下对这两个技术展开深入解析:


2.1 静态树提升(Static Tree Hoisting)
2.1.1 什么是静态树?

在模板中,许多内容是静态的,即这些内容在组件的整个生命周期内是固定不变的。例如:

<div><h1>Hello, Vue3!</h1><p>This is a static text.</p>
</div>

上面模板中的 <h1><p> 标签及其内容都是静态的,它们不会因数据的变化而发生改变。这种部分被称为“静态树”。

2.1.2 问题:Vue2 如何处理静态内容?

在 Vue2 中,模板被编译为虚拟 DOM 树(VNode Tree)。每次组件更新时,即使静态内容未发生变化,整个虚拟 DOM 树仍然会重新创建,消耗不必要的性能资源。

示意:Vue2 中的更新流程

  1. 数据变化,触发视图更新。
  2. 整个虚拟 DOM 树被重新生成,包括静态部分。
  3. 使用新旧虚拟 DOM 树进行 Diff 运算(比较差异),确定需要更新的节点。

这种处理方式对静态内容造成了冗余更新。

2.1.3 Vue3 的改进:静态树提升

Vue3 中,编译器在模板编译阶段,会分析哪些部分是静态的,并将这些静态内容提升到渲染函数的外部,只生成一次,不再重复创建。

优化示意:静态树提升

  • 编译阶段:将静态内容抽离到外部变量中。
  • 运行时:静态部分不会参与后续的 Diff 运算。

对比代码示例

  • Vue2 生成的渲染函数

    render() {return h('div', [h('h1', 'Hello, Vue3!'),h('p', 'This is a static text.')]);
    }
    

    每次组件更新时,h('h1', ...)h('p', ...) 都会被重新创建。

  • Vue3 生成的渲染函数

    const _hoisted_1 = h('h1', 'Hello, Vue3!');
    const _hoisted_2 = h('p', 'This is a static text.');render() {return h('div', [_hoisted_1, _hoisted_2]);
    }
    

    在 Vue3 中,_hoisted_1_hoisted_2 是预先生成的静态节点变量,在运行时不会重新创建。

2.1.4 优势
  1. 减少虚拟 DOM 树的创建成本
    静态节点仅生成一次,显著减少了重复生成的性能开销。
  2. 减少 Diff 运算的复杂度
    静态内容不会参与 Diff 运算,直接跳过比较。
  3. 提升整体渲染性能
    对于静态内容较多的页面,性能提升尤为显著。

2.2 动态节点追踪(Dynamic Node Tracking)
2.2.1 背景:动态节点的检测

在模板中,部分内容是动态的,会随着数据的变化而改变,例如:

<div><h1>{{ title }}</h1><p>{{ description }}</p>
</div>

这里的 {{ title }}{{ description }} 是动态的,依赖于数据的变化。

在 Vue2 中,模板中的所有动态内容都会被视为可能更新的节点,即使某些动态内容在当前数据变化中没有实际更新,也会被重新计算和渲染。

2.2.2 Vue3 的改进:动态节点追踪

Vue3 引入了动态节点追踪机制,通过在编译阶段标记动态节点,运行时仅更新这些真正需要变化的部分。

优化机制

  1. 编译阶段:
    • 对模板中的每个节点进行分析,判断其是否为动态节点。
    • 为动态节点添加标记(Patch Flag)。
  2. 运行时:
    • 根据 Patch Flag 跳过不需要更新的部分,仅更新动态节点。

Patch Flag 的作用
Patch Flag 是一种标记机制,用于描述节点的更新范围和类型。例如:

  • TEXT:表示节点的文本内容可能发生变化。
  • CLASS:表示节点的 class 可能发生变化。
  • STYLE:表示节点的 style 可能发生变化。

代码对比示例

  • Vue2 的更新逻辑:

    Vue2 中,无论数据变化是否影响到某个动态节点,整个虚拟 DOM 树的动态部分都会重新计算。

    // 假设 title 变化了
    render() {return h('div', [h('h1', this.title),  // 被重新计算h('p', this.description)  // 无变化,但仍被重新计算]);
    }
    
  • Vue3 的更新逻辑:

    Vue3 会通过 Patch Flag 精确追踪哪些节点需要更新,减少不必要的计算。

    render() {return h('div', [patchFlag(TEXT, h('h1', this.title)),  // 标记动态节点h('p', 'description')  // 静态内容,无需重新计算]);
    }
    
2.2.3 优势
  1. 减少不必要的渲染
    只有数据变化的节点会被更新,未受影响的动态节点被跳过。
  2. 提高更新效率
    节点标记机制使得渲染过程更精确、轻量。
  3. 灵活性更强
    编译器可以根据 Patch Flag 对不同类型的节点采用针对性的优化策略。

2.3 静态树提升和动态节点追踪的综合优势
  • 协同优化:静态树提升减少了不变内容的创建开销,动态节点追踪则减少了动态内容的更新成本。
  • 适配复杂场景:无论页面是静态内容为主,还是动态内容为主,这两项技术都能显著提升性能。
  • 更高效的虚拟 DOM 更新机制:Vue3 的模板编译器将静态与动态节点分离,结合响应式系统的高效性,使整个渲染流程更加流畅。

通过静态树提升和动态节点追踪,Vue3 在性能优化方面实现了跨越式进步,无论是初次渲染还是后续更新,都表现得更高效和精准。这种编译时优化和运行时机制相结合的模式,充分体现了 Vue3 的现代化设计理念。

3. 响应式系统的革新(详解)

Vue 的核心之一是其响应式系统,它通过数据与视图的双向绑定,大幅降低了开发复杂度。在 Vue2 和 Vue3 中,响应式系统分别基于 Object.definePropertyProxy 实现。两者的实现原理、优劣势、以及对开发者的影响存在显著差异。以下将从 数据劫持数据代理 的概念开始,逐步解析两种实现的细节,并通过简化的代码示例展示其工作原理。


3.1 Vue2 的响应式系统:基于 Object.defineProperty

在 Vue2 中,响应式系统的实现基于 Object.defineProperty,它通过劫持对象的属性来实现对数据访问和修改的拦截。

3.1.1 数据劫持和数据代理
  1. 数据劫持
    Vue2 的核心在于对对象的每个属性进行劫持(通过 Object.defineProperty),对属性的访问(get)和修改(set)行为进行拦截。这使得 Vue 能够在用户访问或修改属性时自动执行响应式逻辑。
  2. 数据代理
    Vue2 提供了一个统一的数据入口(this),通过代理方式将数据对象中的属性直接绑定到 Vue 实例上,使开发者能够更便捷地操作数据。
3.1.2 实现机制
  1. 递归遍历
    Vue2 会对响应式对象进行递归遍历,对每个属性调用 Object.defineProperty,为其定义 gettersetter 方法。
  2. 依赖收集
    getter 方法中,Vue 会将当前属性与依赖的组件(即视图)绑定起来,记录依赖关系。
  3. 通知更新
    setter 方法中,当属性值发生变化时,Vue 会通知所有与该属性相关的依赖进行更新。
代码实现:微型响应式系统

以下是一个模仿 Vue2 实现的小型响应式系统:

class Observer {constructor(obj) {this.walk(obj); // 遍历对象所有属性并监听}walk(obj) {if (!obj || typeof obj !== 'object') return;Object.keys(obj).forEach(key => this.defineReactive(obj, key, obj[key]));}defineReactive(obj, key, value) {this.walk(value); // 如果是嵌套对象,递归处理const dep = new Dep(); // 创建依赖收集器Object.defineProperty(obj, key, {enumerable: true,configurable: true,get() {// 依赖收集:将当前 watcher 添加到订阅列表中if (Dep.target) dep.addSub(Dep.target);return value;},set(newValue) {if (newValue !== value) {value = newValue;dep.notify(); // 通知依赖更新}}});}
}class Dep {constructor() {this.subs = []; // 存放所有依赖}addSub(sub) {this.subs.push(sub);}notify() {this.subs.forEach(sub => sub.update());}
}// 测试代码
const data = { name: 'Vue2', age: 2 };
new Observer(data);Dep.target = {update: () => console.log('视图更新!')
};console.log(data.name); // 触发 getter
data.name = 'Vue3';     // 触发 setter,并通知更新
3.1.3 优势和局限
  1. 优点

    • 在 ES5 环境下实现了响应式系统,兼容性良好。
    • 通过 gettersetter,在数据访问和修改时自动执行逻辑。
  2. 局限性

    • 无法监听新增或删除属性:

      因为Object.defineProperty必须在对象属性存在时绑定,新增属性或删除属性不会触发更新。

      data.newKey = 'value'; // 不会触发更新
      delete data.name;      // 不会触发更新
      

      Vue2 通过$set$delete作为补充,但代码复杂度增加。

    • 数组监听的性能问题:Vue2 需要重写数组的变更方法(如 pushpop)来实现监听,这增加了性能开销。

    • 深层嵌套对象性能差:递归遍历会对所有嵌套对象进行响应式处理,初始化成本较高。


3.2 Vue3 的响应式系统:基于 Proxy

在 Vue3 中,响应式系统使用 Proxy 替代了 Object.definePropertyProxy 是 ES6 提供的新特性,可以拦截和代理对象的多种操作(如 getsetdeleteProperty 等),相比 Vue2 的实现,具有更高的灵活性和性能。

3.2.1 数据劫持和数据代理
  1. 数据劫持
    Vue3 使用 Proxy 劫持整个对象,而不是单个属性,这使得新增和删除属性、数组操作都能被监控。
  2. 数据代理
    Vue3 的数据代理通过 Proxy 的捕获器(trap)实现,捕获所有对对象的操作。
3.2.2 实现机制
  1. 动态代理
    使用 Proxy 包装对象时,开发者不需要手动递归遍历,只有在访问嵌套对象时才会进行代理操作(懒代理)。
  2. 完整拦截
    Proxy 可以拦截所有操作,包括读取、设置、新增、删除、判断属性是否存在等。
  3. 依赖追踪与更新
    Vue3 的依赖追踪和更新机制在整体逻辑上与 Vue2 类似,但基于 Proxy 的实现更简洁。
代码实现:微型响应式系统

以下是一个模仿 Vue3 的小型响应式实现:

function reactive(obj) {return new Proxy(obj, {get(target, key, receiver) {console.log(`读取属性 ${key}`);const result = Reflect.get(target, key, receiver);// 对嵌套对象进行懒代理if (typeof result === 'object' && result !== null) {return reactive(result);}return result;},set(target, key, value, receiver) {console.log(`设置属性 ${key}${value}`);const result = Reflect.set(target, key, value, receiver);// 模拟视图更新console.log('视图更新!');return result;},deleteProperty(target, key) {console.log(`删除属性 ${key}`);const result = Reflect.deleteProperty(target, key);// 模拟视图更新console.log('视图更新!');return result;}});
}// 测试代码
const data = reactive({ name: 'Vue3', details: { version: 3 } });
console.log(data.name); // 读取属性 name
data.name = 'Vue4';     // 设置属性 name 为 Vue4
data.details.version = 4; // 嵌套对象自动代理
delete data.name;        // 删除属性 name
3.2.3 优势
  1. 支持新增和删除属性
    Proxy 可以拦截 deleteProperty 和新增属性的操作,无需额外方法支持。

    data.newKey = 'value'; // 响应式
    delete data.name;      // 响应式
    
  2. 懒代理提高性能
    只有在访问嵌套对象时才会动态代理,而不是一次性递归遍历整个对象。

  3. 代码更简洁
    Proxy 的机制简化了实现逻辑,代码更易读、易扩展。

3.2.4 局限性
  1. 兼容性问题
    Proxy 是 ES6 的特性,无法在不支持 ES6 的环境中使用(如 IE11)。
  2. 性能取决于场景
    虽然 Proxy 通常性能更优,但对于极频繁的属性访问,其性能可能不及直接操作对象。

3.3 Vue2 和 Vue3 响应式系统对比(深入分析)
特性Vue2(Object.defineProperty)Vue3(Proxy)
拦截粒度属性级别对象级别
新增/删除属性支持不支持,需手动 $set / $delete支持
嵌套对象处理递归遍历,初始化开销大懒代理,按需拦截
数组支持通过重写数组方法实现监听原生支持
实现代码复杂度代码较复杂,维护成本高代码更简单,扩展性强
性能初始化时性能较差性能更优,操作开销更小

Vue3 的响应式系统是一场彻底的技术革新,解决了 Vue2 在性能、灵活性和扩展性上的诸多限制,为前端开发提供了更强大的工具支持和更流畅的开发体验。


二、实现原理详解

1. 响应式系统

响应式系统是 Vue 的核心之一。

Vue2 的响应式原理

Vue2 的响应式是通过 Object.defineProperty 来拦截数据属性的 getset 操作:

  1. 初始化时递归遍历对象的每个属性,通过 defineReactive 将其转换为响应式。
  2. 当访问数据时,通过 getter 收集依赖(订阅者)。
  3. 数据变化时,通过 setter 触发依赖更新。

优点

  • 简单直接,基于 ES5 的实现。

缺点

  • 无法检测新增属性和删除属性(需用 $set$delete)。
  • 数组的变动只能通过重写数组方法实现。
  • 对深层嵌套对象需要递归处理,初始化开销较大。
Vue3 的响应式原理

Vue3 使用 ES6 的 Proxy 重构响应式系统:

  1. Proxy 可以直接代理整个对象,无需遍历所有属性。
  2. 使用 Reflect 对对象的操作行为进行拦截。
  3. 响应式依赖追踪和触发更新更高效,支持新增属性和删除属性的响应式。

优点

  • 支持数组和对象的所有操作。
  • 性能更高,代码更简洁。
  • 消除了 Vue2 中的诸多限制。

实现代码示例

// Vue2
function defineReactive(obj, key, val) {Object.defineProperty(obj, key, {get() {console.log(`获取属性 ${key}`);return val;},set(newVal) {console.log(`设置属性 ${key}${newVal}`);val = newVal;},});
}// Vue3
const reactiveHandler = {get(target, key, receiver) {console.log(`获取属性 ${key}`);return Reflect.get(target, key, receiver);},set(target, key, value, receiver) {console.log(`设置属性 ${key}${value}`);return Reflect.set(target, key, value, receiver);},
};function reactive(obj) {return new Proxy(obj, reactiveHandler);
}

2. 模板编译

Vue 的模板语法通过编译器转化为虚拟 DOM 渲染函数。

Vue2 的模板编译
  1. Vue2 的模板编译生成渲染函数(render)。
  2. 编译器无法优化静态内容,每次更新都需重新比较和渲染。
  3. 虚拟 DOM 的 diff 算法复杂度较高。

劣势

  • 静态内容更新效率低。
  • 模板编译体积较大。
Vue3 的模板编译
  1. Vue3 的编译器通过静态提升将静态内容提取到渲染函数之外。
  2. 静态节点只需渲染一次,动态节点则被追踪。
  3. 使用基于块(Block Tree)的 diff 算法,大幅减少对比开销。

优化示例

// Vue3 编译器的静态提升
// 模板
<div><p>静态内容</p><p>{{动态内容}}</p>
</div>// 转化后
function render() {return {type: 'div',children: [_createStaticVNode('<p>静态内容</p>', 1),_createVNode('p', null, _toDisplayString(动态内容))]}
}

3. 组件系统

Vue2 的组件实现

Vue2 的组件是基于 Vue.extend 创建的,组件本质上是构造函数的实例:

  1. 每个组件都有独立的作用域和生命周期。
  2. 插槽(slot)是单纯的内容分发。
Vue3 的组件实现
  1. Vue3 的组件基于函数式实现,使用 setup 方法初始化逻辑。
  2. 插槽支持具名和作用域插槽,组织更加灵活。
  3. 组件树的更新通过 Fragment 提升性能。

4. Composition API

Composition API 是 Vue3 的核心功能,完全重塑了代码组织方式。

Vue2 的 Options API

  1. 数据、方法、计算属性等分散在不同的配置对象中。
  2. 在大型项目中,难以复用逻辑。

Vue3 的 Composition API

  1. 通过 setup 函数集中逻辑。
  2. 使用 reactiveref 创建响应式数据。
  3. 更加模块化,适合复用复杂逻辑。

示例代码:

// Vue2
export default {data() {return { count: 0 };},methods: {increment() {this.count++;}}
};// Vue3
import { reactive } from 'vue';
export default {setup() {const state = reactive({ count: 0 });function increment() {state.count++;}return { state, increment };}
};

三、总结

Vue3 的核心改进

  1. 性能提升
    Vue3 基于 Proxy 构建了全新的响应式系统,解决了 Vue2 在新增属性、数组更新等方面的限制,性能显著提升。同时,模板编译引入了静态树提升和动态节点追踪技术,大幅优化了运行时效率。
  2. 灵活性增强
    Composition API 的引入改变了代码组织方式,提供了更高的逻辑复用性和模块化能力,特别适合大型、复杂项目的开发需求。开发者可以通过 Composable 函数灵活管理状态和功能。
  3. 更强的可扩展性
    Vue3 优化了核心包体积,支持 Tree-shaking,运行时更加轻量。同时,其插件化设计为开发者提供了更大的扩展空间,也为构建生态工具链提供了便利。

是否迁移到 Vue3?

  • 小型项目
    如果项目规模较小且功能单一,Vue2 的 Options API 更加简单直接,仍然是一个很好的选择,特别是在开发周期较短的场景中。

  • 复杂应用
    对于需要长期维护的大型项目或复杂应用,Vue3 的性能优化、灵活性和可扩展性无疑是更优的选择,能够显著提升项目的可维护性和开发效率。

    ​ 未来属于 Vue3,无论是为了迎接现代化开发的挑战,还是为项目的长期发展铺平道路,迈出迁移的一步,正当其时。

在这里插入图片描述

相关文章:

Vue2 vs Vue3:核心原理与性能优化详解

Vue2 vs Vue3&#xff1a;核心原理与性能优化详解 ​Vue.js 是目前主流的前端框架之一&#xff0c;随着 Vue3 的发布&#xff0c;框架内部的实现和使用方式都发生了显著变化。本文将从 Vue2 和 Vue3 的核心实现原理出发&#xff0c;详细解析两者的区别&#xff0c;并分析 Vue3…...

Qt+GDAL属性计算软件开发记录

一.GDAL添加字段 void MainWindow::addField(QString fieldName){OGRFieldDefn * fieldDefn new OGRFieldDefn(fieldName.toStdString().c_str(), OFTInteger);ly->CreateField(fieldDefn);srand((int)time(NULL));while (true){OGRFeature * feature ly->GetNextFeat…...

在超表面中琼斯矩阵的使用

琼斯矩阵&#xff08;Jones Matrix&#xff09; 是一种线性代数方法&#xff0c;用于描述光的偏振状态和偏振变化&#xff0c;是偏振光学中重要的数学工具。它在 超表面理论设计 中广泛应用&#xff0c;尤其是在设计和调控光与物质相互作用时&#xff0c;例如偏振控制、相位调制…...

在macOS上从源码部署RAGFlow-0.14.1

一、macOS配置 1. macOS配置 我使用MacBook Pro&#xff0c;chip 是 Apple M3 Pro&#xff0c;Memory是18GB&#xff0c;macOS是 Sonoma 14.6.1。 2.安装Docker和Docker compose 官方要求 Docker ≥ 24.0.0 & Docker Compose ≥ v2.26.1&#xff0c;我的版本如下&#x…...

2-2-18-9 QNX系统架构之文件系统(二)

阅读前言 本文以QNX系统官方的文档英文原版资料为参考&#xff0c;翻译和逐句校对后&#xff0c;对QNX操作系统的相关概念进行了深度整理&#xff0c;旨在帮助想要了解QNX的读者及开发者可以快速阅读&#xff0c;而不必查看晦涩难懂的英文原文&#xff0c;这些文章将会作为一个…...

【经管数据】上市公司企业审计报告时滞数据、 年报披露时滞数据(2001-2022年)

测算方式&#xff1a;参考C刊《审计研究》窦笑晨&#xff08;2022&#xff09;老师的研究&#xff0c;从审计报告约定披露日期到审计报告实际披露日期之间的时间间隔。有关审计报告时滞的度量&#xff0c;现有研究大多采用资产负债表日与审计报告实际披露日期之间的间隔天数进行…...

debian ubuntu armbian部署asp.net core 项目 开机自启动

我本地的环境是 rk3399机器&#xff0c;安装armbian系统。 1.安装.net core 组件 sudo apt-get update && \sudo apt-get install -y dotnet-sdk-8.0或者安装运行库&#xff0c;但无法生成编译项目 sudo apt-get update && \sudo apt-get install -y aspnet…...

无人机地面遥控遥测技术与算法概述!

一、地面系统遥控检测核心技术 卫星遥测技术&#xff1a; 定义&#xff1a;卫星遥测技术是实现卫星与地面之间遥测数据传输的关键环节。 功能&#xff1a;传输卫星的状态信息、传感器采集的环境参数等。 关键技术&#xff1a; 调制解调技术&#xff1a;用于将数字遥测数据…...

游戏引擎学习第30天

仓库: https://gitee.com/mrxiao_com/2d_game 回顾 在这段讨论中&#xff0c;重点是对开发过程中出现的游戏代码进行梳理和进一步优化的过程。 工作回顾&#xff1a;在第30天&#xff0c;回顾了前一天的工作&#xff0c;并提到今天的任务是继续从第29天的代码开始&#xff0c…...

Django drf 快速使用

1. 安装: pip install djangorestframework 2. 添加rest_framework到您的INSTALLED_APPS设置。 settings.pyINSTALLED_APPS [...rest_framework, ] 3. 定义模型 models.pyfrom django.db import modelsclass BookModel(models.Model):name models.CharField(max_length64)…...

机器学习介绍与实战:案例解析与未来展望

一、机器学习概述 1. 什么是机器学习&#xff1f; 机器学习&#xff08;Machine Learning, ML&#xff09;是一种通过数据训练模型&#xff0c;使计算机能够自动从经验中学习的技术。它旨在让计算机在没有显式编程的情况下&#xff0c;能够从数据中提取模式、进行预测或决策。…...

【SCT71401】3V-40V Vin, 150mA, 2.5uA IQ,低压稳压器,替代SGM2203

SCT71401 3V-40V Vin, 150mA, 2.5uA IQ&#xff0c;低压稳压器&#xff0c;替代SGM2203 描述 SCT71401系列产品是一款低压差线性稳压器&#xff0c;设计用于3 V至40 V &#xff08;45V瞬态输入电压&#xff09;的宽输入电压范围和150mA输出电流。SCT71401系列产品使用3.3uF…...

2024.12.3总结

继周一把PPT初稿弄出来后&#xff0c;今晚进行了转正预答辩&#xff0c;主管&#xff0c;导师&#xff0c;团队里能来听答辩的人都来了&#xff0c;讲完后&#xff0c;自己都觉得自己讲得不好&#xff0c;基本上是照着PPT念的。 写PPT&#xff0c;改PPT,不停的预演答辩的过程&…...

Redis探秘Sentinel(哨兵模式)

概述 Redis的高可用机制有持久化、复制、哨兵和集群。其主要的作用和解决的问题分别是&#xff1a; 持久化&#xff1a;持久化是最简单的高可用方法(有时甚至不被归为高可用的手段)&#xff0c;主要作用是数据备份&#xff0c;即将数据存储在硬盘&#xff0c;保证数据不会因进…...

Linux C/C++编程之静态库

【图书推荐】《Linux C与C一线开发实践&#xff08;第2版&#xff09;》_linux c与c一线开发实践pdf-CSDN博客《Linux C与C一线开发实践&#xff08;第2版&#xff09;&#xff08;Linux技术丛书&#xff09;》(朱文伟&#xff0c;李建英)【摘要 书评 试读】- 京东图书 (jd.com…...

strlen函数用法,模拟实现

一、strlen 函数用法 用来求字符串长度&#xff0c;从我们给的地址开始&#xff0c;往后数&#xff0c;直到遇到 \0 停止&#xff0c;返回数的个数&#xff0c;不包括 \0 返回值类型是无符号整形 char arr[ ]"bvcxz"; printf("%u ",strlen(arr)); …...

云原生后端:解锁高效可扩展应用的魔法世界

目录 一、云原生后端的崛起&#xff1a;时代的必然选择 二、云原生后端的基石&#xff1a;容器化与 Docker &#xff08;一&#xff09;容器化的概念与优势 &#xff08;二&#xff09;Docker&#xff1a;容器化的明星工具 三、微服务架构&#xff1a;云原生后端的灵魂 &…...

大数据新视界 -- Hive 数据湖架构中的角色与应用(上)(25 / 30)

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…...

React高阶面试题目(六)

React的formik库 定义&#xff1a; Formik是一个用于在React应用程序中构建和处理表单数据的流行开源库。它提供了许多实用的组件和函数&#xff0c;使在React应用程序中处理表单数据变得更加轻松。 优点&#xff1a; 自动处理表单状态管理&#xff0c;无需手动编写大量的状态…...

容器运行应用及Docker命令

文章目录 一、使用容器运行Nginx应用1_使用docker run命令运行Nginx应用1 观察下载容器镜像过程2 观察容器运行情况 2_访问容器中运行的Nginx服务1 确认容器IP地址2 容器网络说明3 使用curl命令访问 二、Docker命令1_Docker命令获取帮助方法2_Docker官网提供的命令说明3_docker…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

ardupilot 开发环境eclipse 中import 缺少C++

目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

今日科技热点速览

&#x1f525; 今日科技热点速览 &#x1f3ae; 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售&#xff0c;主打更强图形性能与沉浸式体验&#xff0c;支持多模态交互&#xff0c;受到全球玩家热捧 。 &#x1f916; 人工智能持续突破 DeepSeek-R1&…...

Linux离线(zip方式)安装docker

目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1&#xff1a;修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本&#xff1a;CentOS 7 64位 内核版本&#xff1a;3.10.0 相关命令&#xff1a; uname -rcat /etc/os-rele…...

基于TurtleBot3在Gazebo地图实现机器人远程控制

1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...

【JVM】Java虚拟机(二)——垃圾回收

目录 一、如何判断对象可以回收 &#xff08;一&#xff09;引用计数法 &#xff08;二&#xff09;可达性分析算法 二、垃圾回收算法 &#xff08;一&#xff09;标记清除 &#xff08;二&#xff09;标记整理 &#xff08;三&#xff09;复制 &#xff08;四&#xff…...

CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!

本文介绍了一种名为AnomalyAny的创新框架&#xff0c;该方法利用Stable Diffusion的强大生成能力&#xff0c;仅需单个正常样本和文本描述&#xff0c;即可生成逼真且多样化的异常样本&#xff0c;有效解决了视觉异常检测中异常样本稀缺的难题&#xff0c;为工业质检、医疗影像…...

Python竞赛环境搭建全攻略

Python环境搭建竞赛技术文章大纲 竞赛背景与意义 竞赛的目的与价值Python在竞赛中的应用场景环境搭建对竞赛效率的影响 竞赛环境需求分析 常见竞赛类型&#xff08;算法、数据分析、机器学习等&#xff09;不同竞赛对Python版本及库的要求硬件与操作系统的兼容性问题 Pyth…...