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

Odoo: Owl Hooks 深度解析技术指南

你好!作为一名 Odoo 开发者,深入理解其前端框架 Owl.js,尤其是 Hooks,是提升开发效率和代码质量的关键。这份指南将带你从基础概念到高级应用,全面掌握 Odoo 18 中 Owl Hooks 的所有知识点。


1. Hooks 核心概念介绍

什么是 Owl Hooks? 🦉

Hooks 是 Owl.js v2(Odoo 16+ 引入)中的一个核心特性,它允许你“钩入”Owl 组件的生命周期和状态管理等底层功能。从本质上讲,Hooks 是一些特殊的函数,可以让你在函数式组件 (Functional Components) 中使用状态 (state)、生命周期方法 (lifecycle methods) 以及其他 Owl 的特性,而无需编写 ES6 Class。

想象一下,你的组件是一个机器人。在过去(使用 Class-based 组件),你必须为机器人构建一个完整的、复杂的骨架(class),并把所有能力(如 state_onSomeAction 方法)都预先定义在这个骨架里。

而有了 Hooks,你的机器人变得更加模块化和灵活。你不再需要一个庞大的骨架,而是可以在需要的时候,随时给它“挂上”各种能力的“工具包”(即 Hooks)。比如,需要记忆功能吗?挂上 useState Hook。需要在启动时执行任务吗?挂上 onWillStart Hook。

Hooks vs. Class-based 组件:优势何在?

采用 Hooks 相对于传统的 Class-based 组件,具有以下显著优势:

特性

Class-based 组件 (旧方式)

Functional Components with Hooks (新方式)

优势分析

逻辑复用

难以复用。通常依赖高阶组件 (HOC) 或 Mixins,这会产生“包装地狱”(Wrapper Hell),使组件层级复杂化。

非常容易。通过创建自定义 Hooks,可以将相关的逻辑(如数据获取、订阅等)封装成一个独立的、可重用的函数。

Hooks 使得逻辑本身成为可移植的单元,代码更清晰、扁平。

代码组织

相关逻辑分散。例如,onWillStart 中获取数据,onWillUnmount 中清理资源,这两个相关的逻辑被迫分散在类的不同方法中。

高度内聚。可以将所有相关的逻辑(数据获取、设置、更新、清理)都放在一个自定义 Hook 中,使得代码按功能而非生命周期方法组织。

极大地提升了代码的可读性和可维护性。

心智负担

需要理解 this 的复杂性。在 JavaScript Class 中,this 的指向是一个常见的坑,尤其是在事件处理函数中需要手动绑定。

无需关心 this。函数式组件和 Hooks 捕获的是词法作用域中的变量,逻辑更直观,更符合 JavaScript 的函数式编程思想。

降低了开发者的心智负担,减少了潜在的 Bug。

代码简洁性

代码量更大,模板化代码(boilerplate)更多,例如构造函数 constructorsuper 调用等。

更加简洁。代码量显著减少,专注于业务逻辑本身。

提升了开发效率和代码的可读性。


2. 核心 Hooks 详解

下面,我们将深入探讨 Odoo 18 中最常用和最重要的 Hooks。

State Hooks: useState

useState 是最基础也是最重要的 Hook,它为函数式组件添加了内部状态。

  • 作用: 在组件内部声明一个或多个状态变量。当这些状态变量被更新时,Owl 会自动重新渲染组件以反映最新的状态。
  • 如何使用:
    • useState(initialValue) 接受一个初始值。
    • 它返回一个响应式对象 (reactive object)。你不能直接替换这个对象,但可以直接修改它的属性。Owl 的响应式系统会侦测到属性的变更。
代码示例: 一个简单的计数器

JS (counter_component.js):

/** @odoo-module */import { Component, useState } from "@odoo/owl";export class CounterComponent extends Component {static template = "my_module.CounterComponent";setup() {// 1. 使用 useState 创建一个响应式状态对象this.state = useState({ value: 0 });}// 2. 在方法中直接修改 state 的属性increment() {this.state.value++;}decrement() {this.state.value--;}
}

XML (counter_component.xml):

<templates><t t-name="my_module.CounterComponent" owl="1"><div class="p-4"><p>Current count: <b t-esc="state.value"/></p><button class="btn btn-primary me-2" t-on-click="increment">+1</button><button class="btn btn-secondary" t-on-click="decrement">-1</button></div></t>
</templates>

Lifecycle Hooks: 组件的生命周期

Lifecycle Hooks 允许你在组件生命周期的特定时间点执行代码。它们都应该在组件的 setup() 方法中调用。

onWillStart
  • 执行时机: 在组件的初始渲染之前执行。它是一个异步 Hook,通常用于准备组件所需的数据。
  • 常见用例:
    • 从服务器异步获取初始数据 (RPC 调用)。
    • 加载必要的资源。
  • 注意: 如果 onWillStart 中的 Promisereject,组件将不会被渲染,并会触发错误。

代码示例: 获取初始数据

import { Component, onWillStart, useState } from "@odoo/owl";
import { useService } from "@web/core/utils/hooks";export class PartnerListComponent extends Component {static template = "my_module.PartnerList";setup() {this.state = useState({ partners: [] });this.orm = useService("orm"); // 获取 ORM 服务onWillStart(async () => {// 在组件渲染前,通过 RPC 调用获取伙伴数据const data = await this.orm.searchRead("res.partner", [], ["name", "email"], { limit: 10 });this.state.partners = data;});}
}
onMounted
  • 执行时机: 在组件首次被渲染并插入到真实 DOM 中之后执行。
  • 常见用例:
    • 集成需要访问 DOM 元素的第三方 JavaScript 库(如图表、地图等)。
    • 手动操作 DOM(例如,聚焦到某个输入框)。
    • 设置事件监听器(如 window.addEventListener)。

代码示例: 集成 Chart.js

import { Component, onMounted, useRef } from "@odoo/owl";
import { loadJS } from "@web/core/assets";export class MyChartComponent extends Component {static template = "my_module.MyChart";setup() {this.chartRef = useRef("chart_canvas"); // 获取对 canvas 元素的引用onMounted(() => {// 在组件挂载后,加载第三方库并初始化loadJS("/path/to/chart.js/dist/chart.umd.js").then(() => {new Chart(this.chartRef.el, {type: 'bar',data: { /* ... chart data ... */ }});});});}
}

XML:

<canvas t-ref="chart_canvas" width="400" height="200"></canvas>
onWillUpdateProps
  • 执行时机: 当父组件传递的 props 即将发生变化时,在组件重新渲染之前执行。
  • 常见用例:
    • 根据新的 props 异步更新组件的内部状态。例如,当 partnerId 这个 prop 变化时,重新获取该伙伴的详细信息。

代码示例: 响应 Props 变化

import { Component, onWillStart, onWillUpdateProps, useState } from "@odoo/owl";
// ...export class PartnerDetailComponent extends Component {static template = "my_module.PartnerDetail";static props = { partnerId: { type: Number } };setup(props) {this.state = useState({ details: {} });this.orm = useService("orm");const loadDetails = async (partnerId) => {if (partnerId) {this.state.details = await this.orm.read("res.partner", [partnerId], ["name", "phone", "website"]);}};// 初始加载onWillStart(() => loadDetails(props.partnerId));// 当 props.partnerId 更新时,重新加载数据onWillUpdateProps(async (nextProps) => {if (this.props.partnerId !== nextProps.partnerId) {await loadDetails(nextProps.partnerId);}});}
}
onWillPatch & onPatched

这两个 Hook 用于在组件重新渲染期间进行精细控制。

  • onWillPatch: 在组件即将因状态或 props 变化而重新渲染 (patch) 之前执行。此时虚拟 DOM 已计算出差异,但真实 DOM 尚未更新。
  • onPatched: 在组件重新渲染完成之后执行。真实 DOM 已经更新。
  • 常见用例:
    • onWillPatch: 在 DOM 更新前读取某些 DOM 属性(如滚动位置),以便在 onPatched 中恢复。
    • onPatched: 在 DOM 更新后执行需要最新布局的操作。
onWillUnmount
  • 执行时机: 在组件即将从 DOM 中被移除和销毁之前执行。
  • 常见用例: 进行清理操作,防止内存泄漏。
    • 移除在 onMounted 中添加的全局事件监听器 (window.removeEventListener)。
    • 清除定时器 (clearInterval, clearTimeout)。
    • 销毁第三方库的实例。

代码示例: 清理事件监听器

import { Component, onMounted, onWillUnmount, useState } from "@odoo/owl";export class ResizeWatcher extends Component {static template = "my_module.ResizeWatcher";setup() {this.state = useState({ width: window.innerWidth });const onResize = () => {this.state.width = window.innerWidth;};onMounted(() => {window.addEventListener("resize", onResize);});// 关键:在组件销毁前,移除监听器,否则会造成内存泄漏onWillUnmount(() => {window.removeEventListener("resize", onResize);});}
}

Context Hooks: useContext

  • 作用: 用于在组件树中进行跨层级数据传递,而无需手动通过 props 一层一层地传递。
  • 如何使用:
    1. 使用 createContext 创建一个 Context 对象。
    2. 在祖先组件中使用 useContext 提供一个值。
    3. 在任何后代组件中使用 useContext 来消费这个值。
  • Odoo 中的应用: Odoo Web Client 内部广泛使用 useContext 来传递诸如 notification 服务、action 服务等上下文信息。通常你更多的是消费 Odoo 提供的上下文,而不是创建。

Ref Hooks: useRef

  • 作用: 获取对模板中特定DOM 元素子组件实例的直接引用。
  • 如何使用:
    • useRef("ref_name") 创建一个 ref 对象。
    • 在模板中使用 t-ref="ref_name" 将其附加到元素或组件上。
    • 通过 this.myRef.el (DOM 元素) 或 this.myRef.comp (子组件实例) 来访问。

代码示例: 自动聚焦输入框

JS:

import { Component, onMounted, useRef } from "@odoo/owl";export class AutoFocusInput extends Component {static template = "my_module.AutoFocusInput";setup() {// 1. 创建一个名为 "myInput" 的 refthis.inputRef = useRef("myInput");onMounted(() => {// 2. 在组件挂载后,通过 ref.el 访问 DOM 元素并调用 focus()if (this.inputRef.el) {this.inputRef.el.focus();}});}
}

XML:

<templates><t t-name="my_module.AutoFocusInput" owl="1"><div><span>My Input:</span><input type="text" t-ref="myInput" class="o_input"/></div></t>
</templates>

Other Important Hooks

onError
  • 作用: 捕获其所在组件及其所有子组件在渲染或生命周期方法中抛出的错误。这是一个错误边界 (Error Boundary) 机制。
  • 常见用例: 防止单个组件的错误导致整个应用崩溃。可以优雅地显示一条错误消息。

代码示例:

import { Component, onError, useState } from "@odoo/owl";export class ErrorBoundary extends Component {static template = "my_module.ErrorBoundary";setup() {this.state = useState({ error: null });onError((error) => {// 当子组件发生错误时,这个函数会被调用this.state.error = error;console.error("Caught an error in ErrorBoundary:", error);});}
}
useEnv
  • 作用: 访问 Odoo 的环境 (env) 对象。env 是一个包含各种 Odoo Web Client 全局服务和配置的重要对象。
  • 常见用例:
    • env.services.orm: ORM 服务,用于 RPC 调用。
    • env.services.notification: 通知服务,用于显示弹窗消息。
    • env.services.action: 操作服务,用于执行 Odoo 动作。
    • env.debug: 判断是否处于调试模式。
    • env.user: 获取当前用户信息。
  • 注意: 在 Odoo 16+ 中,推荐使用 useService("service_name") hook 来获取具体服务,它比直接从 env 中取更简洁、意图更明确。

代码示例: 使用通知服务

import { Component } from "@odoo/owl";
import { useService } from "@web/core/utils/hooks";export class NotifierComponent extends Component {static template = "my_module.Notifier";setup() {// 使用 useService 是访问 env.services 的首选方式this.notification = useService("notification");}showSuccess() {this.notification.add("Operation was successful!", {type: "success",});}
}
useComponent
  • 作用: 获取对当前组件实例的引用。
  • 常见用例: 主要在自定义 Hook 中使用,以便能够访问调用该 Hook 的组件的 props 和其他属性。

3. 高级技巧与最佳实践

组合 Hooks

在一个组件中组合使用多个 Hooks 是非常常见的。这正是 Hooks 强大之处,你可以按需引入功能。

代码示例: 组合 useState, onWillStart, useRef, onMounted

import { Component, useState, onWillStart, useRef, onMounted } from "@odoo/owl";
import { useService } from "@web/core/utils/hooks";export class AdvancedComponent extends Component {static template = "my_module.Advanced";setup() {// 状态管理this.state = useState({ data: null, loading: true });// 服务获取this.orm = useService("orm");// DOM 引用this.containerRef = useRef("container");// 异步数据获取onWillStart(async () => {try {const result = await this.orm.searchRead("res.users", [], ["name"], { limit: 1 });this.state.data = result[0];} catch (e) {console.error(e);} finally {this.state.loading = false;}});// DOM 操作onMounted(() => {console.log("Component mounted inside this DOM element:", this.containerRef.el);});}
}

自定义 Hooks (Custom Hooks)

自定义 Hook 是封装和重用有状态逻辑的终极武器。它本质上是一个以 use 开头的函数,内部可以调用其他 Hooks。

场景: 假设你需要在多个组件中监听窗口的宽度变化。

代码示例: 创建并使用 useWindowWidth 自定义 Hook

1. 创建自定义 Hook (use_window_width.js):

/** @odoo-module */import { onMounted, onWillUnmount, useState } from "@odoo/owl";// 自定义 Hook 是一个以 "use" 开头的函数
export function useWindowWidth() {// 它可以拥有自己的 stateconst screen = useState({ width: window.innerWidth, height: window.innerHeight });const onResize = () => {screen.width = window.innerWidth;screen.height = window.innerHeight;};// 它可以拥有自己的生命周期逻辑onMounted(() => window.addEventListener("resize", onResize));onWillUnmount(() => window.removeEventListener("resize", onResize));// 它返回组件需要的值return screen;
}

2. 在组件中使用自定义 Hook:

/** @odoo-module */import { Component } from "@odoo/owl";
import { useWindowWidth } from "./use_window_width"; // 引入自定义 Hookexport class ResponsiveComponent extends Component {static template = "my_module.Responsive";setup() {// 像使用内置 Hook 一样使用它this.screen = useWindowWidth();}get isMobile() {return this.screen.width < 768;}
}

XML:

<templates><t t-name="my_module.Responsive" owl="1"><div><p>Current Width: <t t-esc="screen.width"/>px</p><p t-if="isMobile">Showing mobile view!</p><p t-else="">Showing desktop view!</p></div></t>
</templates>

通过 useWindowWidth,我们成功地将窗口监听的逻辑完全封装,任何组件都可以通过一行代码复用这个功能,极大地提升了代码的模块化和复用性。

性能优化建议

  • 精确的依赖项: 在 onWillUpdateProps 等 Hook 中,务必比较新旧 props,只有在真正需要时才执行昂贵的操作(如 RPC 调用)。
  • 避免在渲染路径中创建函数: 在模板的 t-on-click 中尽量避免使用箭头函数,如 t-on-click="() => doSomething()", 因为每次渲染都会创建一个新函数。最好是在 setup 中定义方法。
  • 合理拆分组件: 将频繁更新的部分和静态部分拆分成不同的组件,可以减少不必要的渲染范围。
  • 小心使用 useState: 不要将所有东西都放进一个巨大的 state 对象。对于非响应式数据(不需要触发渲染的变量),直接在 setup 中用 letconst 定义即可。

常见陷阱

  1. setup 之外调用 Hooks: Hooks 只能在组件的 setup 方法或自定义 Hook 中调用。在事件处理器、普通函数中调用会报错。
  2. 忘记清理: 在 onMounted 中添加的任何订阅、定时器或事件监听器,必须onWillUnmount 中清理,否则会导致严重的内存泄漏。
  3. 直接替换 useState 返回的对象: useState 返回的是一个代理对象。你不能这样做:this.state = { value: 10 }。必须修改其属性:this.state.value = 10
  4. props 进行修改: 组件不应该修改自己的 props。Props 是父组件传递下来的,应该是只读的。如果需要修改,应该在子组件的 state 中创建一个副本。

4. 总结与对比

Hooks 快速参考表

Hook

用途

执行时机

异步?

useState

声明响应式状态

setup 中调用

onWillStart

异步获取初始数据

组件渲染前

onMounted

DOM 操作,集成第三方库

组件首次插入 DOM 后

onWillUpdateProps

响应 props 变化

Props 变更,组件重绘前

onWillPatch

DOM 更新前读取布局

组件重绘前

onPatched

DOM 更新后执行操作

组件重绘后

onWillUnmount

清理资源(事件监听、定时器)

组件销毁前

useRef

获取 DOM 元素或子组件引用

setup 中调用

useContext

跨层级传递数据

setup 中调用

onError

捕获组件树中的错误

发生错误时

useEnv

访问 Odoo 环境对象

setup 中调用

useService

访问 Odoo 服务(推荐)

setup 中调用

useComponent

获取当前组件实例引用

setup 中调用

与 React Hooks 的对比

如果你有 React 背景,你会发现 Owl Hooks 和 React Hooks 非常相似,这使得学习曲线更加平缓。

  • useState: React 的 useState 返回一个值和一个更新函数 [state, setState]。Owl 的 useState 返回一个响应式对象,你直接修改其属性。这是最大的不同点,Owl 的方式更接近 Vue 的 reactive
  • useEffect: React 的 useEffect 统一处理了 onMounted, onWillUpdateProps, onWillUnmount 的逻辑。Owl 将它们拆分成了更具语义化的独立 Hooks,逻辑上更清晰,但也意味着你需要知道在哪个生命周期钩子中放置代码。
  • 自定义 Hooks: 概念和用法几乎完全相同,都是逻辑复用的最佳实践。

掌握 Owl Hooks 是精通现代 Odoo 前端开发的核心。希望这份详尽的指南能为你铺平学习之路,让你在 Odoo 18 的世界里游刃有余!

相关文章:

Odoo: Owl Hooks 深度解析技术指南

你好&#xff01;作为一名 Odoo 开发者&#xff0c;深入理解其前端框架 Owl.js&#xff0c;尤其是 Hooks&#xff0c;是提升开发效率和代码质量的关键。这份指南将带你从基础概念到高级应用&#xff0c;全面掌握 Odoo 18 中 Owl Hooks 的所有知识点。 1. Hooks 核心概念介绍 什…...

SpringBoot返回xml

默认情况下引入web依赖后自带了JackJson 返回JSON数据 你也可以引入fastJSON 那么方便使用可以用JSON.xxx 如果希望Boot默认返回xml数据 <dependency><groupId>com.fasterxml.jackson.dataformat</groupId><artifactId>jackson-dataformat-xml<…...

【案例篇】 实现简单SSM工程-后端

简介 本篇文章将带你从0到1的实现一个SSM项目&#xff0c;通过此案例可以让你在项目中对SpringBoot的使用有一个更加详细的认识&#xff0c;希望这个简单的案例能够帮到你。文章内容若存在错误或需改进的地方&#xff0c;欢迎大家指正&#xff01;若对操作有任何疑问欢迎留言&a…...

零基础学习计算机网络编程----网络基本知识

目录 1. 计算机网络发展 1.1 网络发展 1.2 媒介 2 认识协议 2.1 为什么要有协议 2.2 协议的本质 3 网络协议的初识 3.1 什么是协议分层 3.2 为什么会有 4. OSI七层模型 4.1 定义 5. TCP/IP五层(或四层)模型 5.1 有什么 6. 网络传输基本流程 6.1 网络传输流程图…...

Zynq和Microblaze的区别和优势

Zynq芯片包含了一颗双核ARM Cortex-A9处理器&#xff0c;这是一颗“硬”处理器---它是芯片上专用 而且优化过的硅片原件。 MicroBlaze为“软”处理器&#xff0c;它是由可编程逻辑部分的单元组合而成的&#xff0c; 也就是说&#xff0c;一个 软处理器的实现和部署在FPGA的逻…...

FastAPI 支持文件下载

FastAPI 支持文件下载 FastAPI 支持文件上传 Python 获取文件类型 mimetype 文章目录 1. 服务端处理1.1. 下载小文件1.2. 下载大文件&#xff08;yield 支持预览的&#xff09;1.3. 下载大文件&#xff08;bytes&#xff09;1.4. 提供静态文件服务 2. 客户端处理2.1. 普通下载2…...

CNN卷积神经网络到底卷了啥?

参考视频&#xff1a;卷积神经网络&#xff08;CNN&#xff09;到底卷了啥&#xff1f;8分钟带你快速了解&#xff01; 我们知道&#xff1a; 图片是由像素点构成&#xff0c;即最终的成像效果是由背后像素的颜色数值所决定 在Excel中&#xff1a;有这样一个由数值0和1组成的66…...

vue中v-clock指令

基础 v-cloak 是 Vue 中的一个非常实用的指令&#xff0c;用于防止在 Vue 实例尚未挂载完成前&#xff0c;用户看到模板中的插值语法&#xff08;如 {{ message }}&#xff09;一闪而过。 ✅ 场景举例 你在页面还没加载完前&#xff0c;可能会看到这样一瞬间的内容&#xff…...

MIT 6.S081 2020Lab5 lazy page allocation 个人全流程

文章目录 零、写在前面一、Eliminate allocation from sbrk()1.1 说明1.2 实现 二、Lazy allocation2.1 说明2.2 实现 三、Lazytests and Usertests3.1 说明3.2 实现3.2.1 lazytests3.2.2 usertests 零、写在前面 可以阅读下4.6页面错误异常 像应用程序申请内存&#xff0c;内…...

C++初阶-list的使用2

目录 1.std::list::splice的使用 2.std::list::remove和std::list::remove_if的使用 2.1remove_if函数的简单介绍 基本用法 函数原型 使用函数对象作为谓词 使用普通函数作为谓词 注意事项 复杂对象示例 2.2remove与remove_if的简单使用 3.std::list::unique的使用 …...

PHP序列化数据格式详解

PHP序列化数据格式详解 概述 PHP序列化是将PHP变量&#xff08;包括对象&#xff09;转换为可存储或传输的字符串表示形式的过程。了解这些序列化格式对于数据处理、调试和安全性分析非常重要。本文将详细介绍PHP中各种数据类型的序列化表示方式。 基本数据类型序列化格式 …...

如何优化 MySQL 存储过程的性能?

文章目录 1. 优化 SQL 语句避免全表扫描减少子查询&#xff0c;改用 JOIN避免 SELECT 2. 合理使用索引3. 优化存储过程结构减少循环和临时变量避免重复计算 4. 使用临时表和缓存5. 优化事务处理6. 分析和监控性能7. 优化数据库配置8. 避免用户自定义函数&#xff08;UDF&#…...

深度学习:损失函数与激活函数全解析

目录 深度学习中常见的损失函数和激活函数详解引言一、损失函数详解1.1 损失函数的作用与分类1.2 回归任务损失函数1.2.1 均方误差&#xff08;MSE&#xff09;1.2.2 平均绝对误差&#xff08;MAE&#xff09; 1.3 分类任务损失函数1.3.1 交叉熵损失&#xff08;Cross-Entropy&…...

【大前端】Node Js下载文件

NodeJs 获取远程文件有很多方式&#xff0c;常见的方式有以下两种&#xff1a; - fetch&#xff08;原生&#xff09; - axios&#xff08;插件&#xff09; 通过 Fetch 下载文件&#xff0c;代码如下&#xff1a; import fs from node:fsfunction main(){fetch(http://xxx.x…...

自训练NL-SQL模型

使用T5小模型在笔记本上训练 nature language to SQL/自然语言 转SQL 实测通过。 本文介绍了如何在笔记本上使用T5小模型训练自然语言转SQL的任务。主要内容包括:1) 创建Python 3.9环境并安装必要的依赖包;2) 通过Hugging Face镜像下载wikisql数据集和T5-small模型;3) 实现…...

创新点!贝叶斯优化、CNN与LSTM结合,实现更准预测、更快效率、更高性能!

能源与环境领域的时空数据预测面临特征解析与参数调优双重挑战。CNN-LSTM成为突破口&#xff1a;CNN提取空间特征&#xff0c;LSTM捕捉时序依赖&#xff0c;实现时空数据的深度建模。但混合模型超参数&#xff08;如卷积核数、LSTM层数&#xff09;调优复杂&#xff0c;传统方法…...

【Flutter】创建BMI计算器应用并添加依赖和打包

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍创建BMI计算器应用并添加依赖和打包。 学其所用&#xff0c;用其所学。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#xff0c;下…...

【Linux 学习计划】-- 倒计时、进度条小程序

目录 \r 、\n、fflush 倒计时 进度条 进度条进阶版 结语 \r 、\n、fflush 首先我们先来认识这三个东西&#xff0c;这将会是我们接下来两个小程序的重点之一 首先是我们的老演员\n&#xff0c;也就是回车加换行 这里面其实包含了两个操作&#xff0c;一个叫做回车&…...

微服务的应用案例

从“菜市场”到“智慧超市”&#xff1a;一场微服务的变革之旅 曾经&#xff0c;我们的系统像一个熙熙攘攘的传统菜市场。所有功能模块&#xff08;摊贩&#xff09;都挤在一个巨大的单体应用中。用户请求&#xff08;买菜的顾客&#xff09;一多&#xff0c;整个市场就拥堵不堪…...

后端开发概念

1. 后端开发概念解析 1.1. 什么是服务器&#xff0c;后端服务 1.1.1. 服务器 服务器是一种提供服务的计算机系统&#xff0c;它可以接收、处理和响应来自其他计算机系统&#xff08;客户端&#xff09;的请求。服务器主要用于存储、处理和传输数据&#xff0c;以便客户端可以…...

2025网络安全趋势报告 内容摘要

2025 年网络安全在技术、法规、行业等多个维度呈现新趋势。技术上&#xff0c;人工智能、隐私保护技术、区块链、量子安全技术等取得进展&#xff1b;法规方面&#xff0c;数据安全法规进一步细化&#xff1b;行业应用中&#xff0c;物联网、工业控制系统安全升级&#xff0c;供…...

云原生安全基石:深度解析HTTPS协议(从原理到实战)

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念&#xff1a;HTTPS是什么&#xff1f; HTTPS&#xff08;HyperText Transfer Protocol Secure&#xff09;是HTTP协议的安全版本&#xff0c…...

Autodl训练Faster-RCNN网络--自己的数据集(一)

参考文章&#xff1a; Autodl服务器中Faster-rcnn(jwyang)复现(一)_autodl faster rcnn-CSDN博客 Autodl服务器中Faster-rcnn(jwyang)训练自己数据集(二)_faster rcnn autodl-CSDN博客 食用指南&#xff1a;先跟着参考文章一进行操作&#xff0c;遇到问题再来看我这里有没有解…...

python打卡day36

复习日 仔细回顾一下神经网络到目前的内容&#xff0c;没跟上进度的补一下进度 作业&#xff1a;对之前的信贷项目&#xff0c;利用神经网络训练下&#xff0c;尝试用到目前的知识点让代码更加规范和美观。探索性作业&#xff08;随意完成&#xff09;&#xff1a;尝试进入nn.M…...

8.Java 8 日期时间处理:从 Date 的崩溃到 LocalDate 的优雅自救​

一、被 Date 逼疯的程序员&#xff1a;那些年踩过的坑​ 还记得刚学 Java 时被Date支配的恐惧吗&#xff1f;​ 想获取 "2023 年 10 月 1 日"&#xff1f;new Date(2023, 9, 1)—— 等等&#xff0c;为什么月份是 9&#xff1f;哦对&#xff0c;Java 的月份从 0 开…...

基于Python的全卷积网络(FCN)实现路径损耗预测

以下是一份详细的基于Python的全卷积网络(FCN)实现路径损耗预测的技术文档。本方案包含理论基础、数据生成、模型构建、训练优化及可视化分析,代码实现约6000字。 基于全卷积网络的无线信道路径损耗预测系统 目录 问题背景与需求分析系统架构设计合成数据生成方法全卷积网络…...

【ubuntu】安装NVIDIA Container Toolkit

目录 安装NVIDIA Container Toolkit 安装依赖 添加密钥和仓库 配置中国科技大学&#xff08;USTC&#xff09; 镜像 APT 源 更新 APT 包列表 安装 NVIDIA Container Toolkit 验证安装 重启docker 起容器示例命令 【问题】如何在docker中正确使用GPU&#xff1f; 安装…...

Paimon和Hive相集成

Flink版本1.17 Hive版本3.1.3 1、Paimon集成Hive 将paimon-hive-connector.jar复制到auxlib中&#xff0c;下载链接Index of /groups/snapshots/org/apache/https://repository.apache.org/snapshots/org/apache/paimon/ 通过flink进入查看paimon /opt/softwares/flink-1.…...

精益数据分析(74/126):从愿景到落地的精益开发路径——Rally的全流程管理实践

精益数据分析&#xff08;74/126&#xff09;&#xff1a;从愿景到落地的精益开发路径——Rally的全流程管理实践 在创业的黏性阶段&#xff0c;如何将抽象的愿景转化为可落地的产品功能&#xff1f;如何在快速迭代中保持战略聚焦&#xff1f;今天&#xff0c;我们通过Rally软…...

HarmonyOS 鸿蒙应用开发进阶:深入理解鸿蒙跨设备互通机制

鸿蒙跨设备互通&#xff08;HarmonyOS Cross-Device Collaboration&#xff09;是鸿蒙系统分布式能力的重要体现&#xff0c;通过创新的分布式软总线技术&#xff0c;实现了设备间的高效互联与能力共享。本文将系统性地解析鸿蒙跨设备互通的技术架构、实现原理及开发实践。 跨设…...