Vue全局挂载实战:从原理到选型,彻底搞懂全局函数与变量
1. 全局挂载这件事到底在解决什么问题刚接触 Vue 那会儿我最常干的一件事就是把一个工具函数从utils.js里import到每一个用到的组件里。三五个组件还好等到项目里几十个组件都要用同一个格式化时间的方法时每个文件顶部都挂着一行几乎一样的 import改个路径还得全局搜索替换那种感觉就像每次出门都要把家里所有钥匙挨个揣兜里。全局挂载要解决的就是这个痛点让一个函数、一个变量、一个对象在任意组件里都能直接拿到不用反复引入。它本质上是把某些高频、通用、与业务弱相关的能力提升到应用级别让组件只关心自己的逻辑而不是把精力浪费在“这个函数从哪来”上。但这里有个前提得先说清楚全局挂载不是越多越好。我见过有项目把几十个方法全塞到全局结果新人接手时完全不知道某个$format是从哪冒出来的调试时断点都找不到源头。所以我的原则一直是——只有真正跨模块复用、且调用频率足够高的东西才值得挂到全局。像那种只有两三个页面用到的函数老老实实 import 反而更清晰。这篇文章我会把 Vue 里全局挂载的几种主流方式掰开揉碎讲一遍包括它们各自的适用场景、底层原理、踩过的坑以及在不同 Vue 版本下的差异。不管你是刚上手 Vue 的新手还是想给团队统一规范的老人应该都能从中找到能直接抄作业的部分。2. 先搞清楚 Vue 的实例和原型链机制在动手挂载之前有必要花点时间理解 Vue 到底是怎么让全局方法“无处不在”的。很多人照着教程写app.config.globalProperties.$xxx fn能用但问他为什么能用就说不清了。理解这层机制后面遇到问题才能自己排查。2.1 原型链是全局访问的底层支撑JavaScript 里每个对象都有一个原型访问一个属性时如果自身没有就会顺着原型链往上找。Vue 的组件实例本质上也是对象它同样遵循这套规则。当我们把方法挂到 Vue 的原型或者应用的全局属性上时组件实例在查找属性时就能顺着链条找到它。用生活化的类比组件实例就像一个员工他手头没有某份资料时会去问自己的直属上级原型上级没有就继续往上问直到问到公司层面全局配置。全局挂载做的事情就是把资料放到公司层面让所有员工都能查到。在 Vue 2 里这个“公司层面”就是Vue.prototype在 Vue 3 里则变成了app.config.globalProperties。名字变了但思路一脉相承。2.2 Vue 2 与 Vue 3 的机制差异Vue 2 直接操作构造函数原型Vue.prototype.$http axios所有由这个构造函数创建的实例都能通过原型链访问到$http。这种方式简单粗暴但有个隐患——它污染了全局的 Vue 构造函数如果页面里同时存在多个 Vue 应用它们会共享同一份原型容易互相干扰。Vue 3 引入了应用实例的概念用createApp创建出来的每个应用都是独立的const app createApp(App) app.config.globalProperties.$http axios这样每个应用有自己的全局属性空间互不影响。这也是为什么 Vue 3 里不再推荐直接改Vue.prototype而是走app.config.globalProperties。理解这个差异能帮你在迁移老项目时少踩坑。2.3 全局属性与全局变量的边界这里要区分两个概念全局属性是挂在应用实例上、通过组件实例访问的全局变量则更宽泛可以是模块级别的导出也可以是挂到window上的东西。我个人的划分标准是这样的类型访问方式适用场景风险全局属性this.$xxx组件内高频调用的工具方法命名冲突、来源不清晰模块导出import { xxx }纯函数、常量、配置需要显式引入全局变量window.xxx跨框架、跨脚本共享污染全局、难以追踪大部分情况下我优先推荐模块导出其次是全局属性最后才考虑挂 window。原因很简单前两者有明确的来源和类型提示IDE 能帮你跳转而 window 上的东西基本靠记忆。3. 全局函数的几种挂载方式逐一拆解这一节是重头戏。我把实际项目里用过的几种方式都列出来每种都配上代码、适用场景和我踩过的坑。3.1 方式一app.config.globalPropertiesVue 3 首选这是 Vue 3 官方推荐的全局挂载方式。写法很直接// main.js import { createApp } from vue import App from ./App.vue const app createApp(App) app.config.globalProperties.$formatDate (timestamp) { const date new Date(timestamp) return ${date.getFullYear()}-${date.getMonth() 1}-${date.getDate()} } app.mount(#app)组件里这样用export default { mounted() { console.log(this.$formatDate(Date.now())) } }在组合式 API 的setup里this不可用需要用getCurrentInstanceimport { getCurrentInstance } from vue export default { setup() { const { proxy } getCurrentInstance() console.log(proxy.$formatDate(Date.now())) } }注意getCurrentInstance官方明确说它是给库作者用的高级 API业务代码里滥用会让逻辑变得难以追踪。我的建议是如果项目以组合式 API 为主全局函数尽量走模块导入而不是挂到 globalProperties 上。这种方式的好处是类型清晰、来源明确配合 TypeScript 还能做类型声明。坏处是每个挂载的属性都要加$前缀这是约定避免和组件自身属性冲突写起来略啰嗦。3.2 方式二Vue.prototypeVue 2 经典做法Vue 2 项目里最常见的就是这个// main.js import Vue from vue import axios from axios Vue.prototype.$http axios Vue.prototype.$formatDate (timestamp) { /* ... */ }组件里直接this.$http.get(...)就能用。这套写法在 Vue 2 生态里根深蒂固很多老项目、老教程都是这么教的。但要注意几个坑。第一Vue.prototype上的属性名如果和组件自身的 data、methods 重名组件自身的会覆盖原型上的容易出诡异 bug。第二如果项目里用了 SSR服务端和客户端共享同一个 Vue 构造函数原型上的状态可能被污染。第三多个 Vue 应用共存时会互相影响。所以我的经验是Vue 2 项目里用Vue.prototype没问题但一定要加$前缀并且只挂真正全局的东西。3.3 方式三provide / inject 实现依赖注入provide和inject是 Vue 提供的依赖注入机制它不算严格意义上的“全局”但能实现跨层级传递很多时候比全局挂载更合适。// 根组件 export default { provide() { return { formatDate: this.formatDate } }, methods: { formatDate(timestamp) { /* ... */ } } }后代组件export default { inject: [formatDate], mounted() { console.log(this.formatDate(Date.now())) } }这种方式的好处是依赖关系显式——组件声明了自己需要什么而不是凭空从全局拿。坏处是每个需要的组件都要写 inject而且 provide 的值默认不是响应式的Vue 3 里可以用ref或reactive包裹解决。我一般在做组件库或者需要严格控制依赖的场景下用 provide/inject业务项目里如果只是图省事还是 globalProperties 更直接。3.4 方式四挂到 window 或 globalThis最原始的方式直接挂到全局对象上window.$formatDate (timestamp) { /* ... */ }组件里window.$formatDate(...)或者直接$formatDate(...)都能用。这种方式我基本只在两种情况下用一是需要和外部脚本比如某个第三方 SDK共享方法二是做微前端时主子应用之间通信。其他情况一律不推荐因为它完全绕过了 Vue 的机制类型提示没有、来源追踪没有、命名冲突风险极高。3.5 方式五插件形式统一注册如果全局函数比较多一个个挂太散可以封装成 Vue 插件// plugins/global.js export default { install(app) { app.config.globalProperties.$formatDate (timestamp) { /* ... */ } app.config.globalProperties.$debounce (fn, delay) { /* ... */ } app.config.globalProperties.$deepClone (obj) { /* ... */ } } }// main.js import GlobalPlugin from ./plugins/global app.use(GlobalPlugin)这种方式把全局挂载集中管理好处是清晰、可维护坏处是插件内部的东西对使用者来说还是“黑盒”。我一般会配合 TypeScript 的模块增强给 globalProperties 加上类型声明这样 IDE 里能自动补全。4. 全局变量的挂载与状态共享函数讲完了再说变量。全局变量和全局函数在挂载方式上大同小异但变量涉及响应式情况会复杂一些。4.1 普通全局变量模块导出最省心如果只是常量、配置项这类不需要响应式的东西最推荐的方式是模块导出// config/constants.js export const APP_NAME MyApp export const API_TIMEOUT 10000 export const STATUS_MAP { 1: 待处理, 2: 处理中, 3: 已完成 }用的时候import { APP_NAME } from /config/constants。这种方式有类型提示、有来源、可 tree-shaking是纯变量的最佳实践。4.2 响应式全局变量用 reactive 或 ref如果全局变量需要响应式比如用户信息、主题配置可以这样// store/global.js import { reactive } from vue export const globalState reactive({ userInfo: null, theme: light, locale: zh-CN })组件里import { globalState } from /store/global export default { setup() { return { globalState } } }模板里globalState.theme变化会自动更新。这种方式比挂到 globalProperties 上更好因为响应式对象在模块级别是单例的所有组件共享同一份且来源清晰。4.3 挂到 globalProperties 的响应式变量如果非要挂到 globalProperties要注意响应式的问题app.config.globalProperties.$globalState reactive({ theme: light })组件里this.$globalState.theme是响应式的因为 reactive 返回的是 Proxy。但如果挂的是普通对象就不会有响应式效果。这一点很多人会踩坑——以为挂上去就自动响应了其实不是。4.4 全局变量与状态管理库的取舍说到全局状态绕不开状态管理库。我的判断标准是如果只是几个简单的全局变量用模块导出 reactive 就够了没必要上状态管理库。如果状态逻辑复杂、涉及多个模块的读写、需要调试工具追踪那状态管理库更合适。全局挂载适合“只读”或“极少修改”的配置类变量不适合频繁变更的业务状态。我见过有项目把用户登录态、购物车数据全挂到 globalProperties 上结果状态变更完全失控最后不得不重构。这个教训值得记一下。5. 实操从零搭建一套全局挂载方案光说理论不够这一节我带你走一遍完整的搭建流程包括目录结构、代码、类型声明和测试。5.1 目录结构设计我习惯这样组织src/ ├── plugins/ │ ├── global-functions.js // 全局函数插件 │ └── index.js // 插件统一出口 ├── utils/ │ ├── format.js // 格式化相关 │ └── common.js // 通用工具 ├── config/ │ └── constants.js // 常量配置 └── main.js把全局函数的具体实现放在utils里插件只负责挂载这样函数本身还能被单独 import 使用不依赖 Vue 实例。5.2 编写全局函数插件// utils/format.js export function formatDate(timestamp, separator -) { if (!timestamp) return const date new Date(timestamp) const y date.getFullYear() const m String(date.getMonth() 1).padStart(2, 0) const d String(date.getDate()).padStart(2, 0) return [y, m, d].join(separator) } export function formatMoney(amount, symbol ¥) { if (amount null) return return symbol Number(amount).toFixed(2) }// plugins/global-functions.js import { formatDate, formatMoney } from /utils/format export default { install(app) { app.config.globalProperties.$formatDate formatDate app.config.globalProperties.$formatMoney formatMoney } }// main.js import { createApp } from vue import App from ./App.vue import GlobalFunctions from ./plugins/global-functions const app createApp(App) app.use(GlobalFunctions) app.mount(#app)5.3 TypeScript 类型声明补全用 TS 的话globalProperties 上的属性默认没有类型需要做模块增强// types/global.d.ts import { formatDate, formatMoney } from /utils/format declare module vue { interface ComponentCustomProperties { $formatDate: typeof formatDate $formatMoney: typeof formatMoney } } export {}加上这段之后this.$formatDate在组件里就有类型提示和自动补全了。这个细节很多人忽略但用起来体验差别很大。5.4 在组合式 API 中的调用封装组合式 API 里用getCurrentInstance拿 proxy 有点绕我一般封装一个 hook// composables/useGlobal.js import { getCurrentInstance } from vue export function useGlobal() { const instance getCurrentInstance() if (!instance) { throw new Error(useGlobal 必须在 setup 内调用) } return instance.proxy }用的时候import { useGlobal } from /composables/useGlobal export default { setup() { const global useGlobal() console.log(global.$formatDate(Date.now())) } }提示这个 hook 只是让写法好看一点本质上还是依赖 getCurrentInstance。如果项目以组合式 API 为主我更建议直接 import 函数而不是绕这一圈。5.5 验证挂载是否生效写完别急着跑业务先写个最小验证。在 App.vue 里export default { mounted() { console.log(formatDate:, this.$formatDate(Date.now())) console.log(formatMoney:, this.$formatMoney(1234.5)) } }控制台能正常输出就说明挂载成功。如果报this.$formatDate is not a function八成是插件没注册或者注册顺序有问题。6. 常见问题与排查技巧实录这一节是我这些年踩坑攒下来的经验基本都是文档里不会写的。6.1 挂载了但组件里拿不到最常见的原因有三个。第一插件注册在app.mount之后这时候应用已经挂载再注册就晚了。第二在setup里用了this组合式 API 的 setup 里 this 是 undefined。第三属性名拼写错误比如挂的是$formatDate用的却是$formatdate大小写敏感。排查顺序先确认注册时机再确认调用位置最后检查拼写。6.2 命名冲突导致覆盖如果全局属性名和组件自身的 data、computed、methods 重名组件自身的会优先。比如组件里有个formatDate方法那this.formatDate拿到的是组件自己的this.$formatDate才是全局的。这也是为什么全局属性一定要加$前缀——就是为了避开这类冲突。6.3 响应式丢失问题挂到 globalProperties 上的普通对象不会自动响应式。如果需要一个响应式的全局变量要么用reactive包裹要么干脆走模块导出。我见过有人挂了个普通对象然后纳闷为什么改了值视图不更新折腾半天才发现是响应式的问题。6.4 SSR 场景下的注意事项服务端渲染时全局属性是在服务端和客户端分别创建的。如果全局属性里存了用户相关的状态要确保每个请求都有独立的实例否则会出现状态串号。Vue 3 的createApp每次调用都返回新实例天然支持这一点但前提是你别把状态挂到模块级别的变量上。6.5 常见问题速查表现象可能原因解决方向this.$xxx is not a function插件未注册或注册时机晚检查 app.use 和 mount 顺序setup 里拿不到用了 this改用 getCurrentInstance 或直接 import值改了视图不更新挂的是普通对象用 reactive 包裹或改模块导出属性被覆盖与组件自身属性重名全局属性统一加 $ 前缀类型报错缺少类型声明做 ComponentCustomProperties 模块增强多应用互相干扰用了 Vue.prototype改用 app.config.globalProperties6.6 我个人的几条硬性建议第一全局属性只挂真正全局的东西判断标准是“超过一半的组件可能用到”。第二命名统一加$前缀形成团队约定。第三能用模块导出解决的优先模块导出全局挂载是备选不是首选。第四一定要配 TypeScript 类型声明否则半年后你自己都不记得挂了什么。第五插件文件里加注释写清楚每个挂载项的用途和参数。7. 不同场景下的选型建议最后聊聊怎么根据项目情况选方案。这块没有标准答案但有一些经验性的判断。7.1 小型项目模块导出为主小项目组件少、依赖简单直接import工具函数最省事。全局挂载反而增加了理解成本新人进来还得先搞清楚$xxx是从哪来的。我做过几个页面级别的项目全程没用全局挂载代码一样清爽。7.2 中大型项目插件化统一管理项目一大工具函数多了就需要统一管理。这时候用插件形式把全局函数集中注册配合类型声明既方便调用又便于维护。关键是团队要有约定什么能挂什么不能挂避免全局空间被滥用。7.3 组件库开发provide/inject 更合适做组件库时全局挂载是大忌因为组件库不应该假设使用者的应用环境。这时候 provide/inject 是更好的选择让使用者自己决定注入什么组件库只声明依赖。7.4 微前端场景谨慎使用全局挂载微前端里多个子应用可能共存全局挂载容易互相污染。这时候要么用沙箱隔离要么干脆每个子应用独立管理自己的工具函数不往全局挂。这块坑很深我一般建议微前端场景下全局挂载能不用就不用。7.5 选型对照表场景推荐方式理由小型项目模块导出简单直接无额外心智负担中大型项目插件 globalProperties统一管理便于维护组件库provide/inject不污染使用者环境组合式 API 为主模块导出避免 getCurrentInstance 的绕路需要响应式全局状态reactive 模块导出响应式且来源清晰微前端各应用独立管理避免全局污染选型的核心就一句话全局挂载是手段不是目的能让代码更清晰、更好维护的方案就是好方案。别为了用某个 API 而用也别因为教程都这么写就照搬。多想想半年后接手的人能不能一眼看懂这个判断标准比什么都管用。

相关新闻

Category底层原理全解析:从结构体到方法合并的完整链路

Category底层原理全解析:从结构体到方法合并的完整链路

去年面一家头部大厂的时候,面试官问了一个让我印象很深的问题:“你平时写分类写得很溜,那你说说,Category 的底层是怎么把方法加到类上去的?为什么它能‘覆盖’类里面原来的方法?”当时我虽然背过不少面经&…

2026/10/15 12:43:10 阅读更多 →
磁性材料与元件学习路线:从理论到实践

磁性材料与元件学习路线:从理论到实践

1. 磁性材料与元件学习路线概述从事磁性材料研发工作十年,我深刻体会到这是一门需要理论积累与实践验证并重的学科。刚入行时面对纷繁复杂的磁学参数和材料体系,也曾感到无从下手。本文将系统梳理磁性材料与元件的学习路径,重点解析核心知识框…

2026/10/15 12:43:10 阅读更多 →
PHP+MySQL搭建线上纪念馆系统:从建馆到祭拜互动完整方案

PHP+MySQL搭建线上纪念馆系统:从建馆到祭拜互动完整方案

简介:面向清明祭扫与网络追思场景的PHP网站源码包,内置祭祀、祈福、留言、个人中心等完整功能模块,同时兼顾电脑端与移动端浏览体验,适合殡葬服务站点、个人开发者或PHP学习者直接部署、参考与二次开发。压缩包共132个文件&#x…

2026/10/15 12:43:09 阅读更多 →

最新新闻

TileLang:GPU异构计算的声明式分块编程范式

TileLang:GPU异构计算的声明式分块编程范式

1. TileLang不是新语言,而是GPU编程范式的底层重构最近在几个高性能计算开源项目里反复看到tilelang这个词,它既不像Rust那样有语法教程,也不像CUDA那样带完整IDE支持,甚至GitHub上连个独立仓库都没有——但它频繁出现在MLIR、LLV…

2026/10/15 13:26:57 阅读更多 →
Android OpenGL ES绘制圆形全攻略:从三角形扇到着色器工程实战

Android OpenGL ES绘制圆形全攻略:从三角形扇到着色器工程实战

简介:一份面向 Android 图形开发学习者的 OpenGL ES 圆形绘制示例工程。项目通过 OpenGL 实现了圆饼填充、圆环描边与点状圆圈的绘制,覆盖从顶点数据生成、着色器编写到渲染状态设置的完整流程。资源包共 567 个文件,以 xml 布局与资源、grad…

2026/10/15 13:26:57 阅读更多 →
MATLAB二维Delaunay网格生成:MESH2D轻量可控实战指南

MATLAB二维Delaunay网格生成:MESH2D轻量可控实战指南

简介:MESH2D是一款面向科研人员、工程仿真从业者及高校师生的MATLAB/Octave二维Delaunay网格生成工具,专为解决有限元分析、流体力学模拟、地形建模等场景中复杂几何区域的高质量三角剖分问题而设计。资源包共69个文件,含55个核心MATLAB函数&…

2026/10/15 13:26:57 阅读更多 →
SAP外部作业调度服务实战解析与优化

SAP外部作业调度服务实战解析与优化

1. 项目背景与核心价值在企业级应用环境中,SAP系统的批处理作业(Application Job)管理一直是运维工作的重点和难点。传统的手工调度方式不仅效率低下,还容易因人为失误导致作业执行失败或资源冲突。External Job Scheduling Servi…

2026/10/15 13:26:57 阅读更多 →
VMware桥接模式实现虚拟机远程登录与文件传输

VMware桥接模式实现虚拟机远程登录与文件传输

1. 项目概述:为什么桥接模式是远程协作的“隐形地基”VMware桥接网络模式,远程登录和远程传输文件——这三件事放在一起,不是偶然组合,而是实际工作中最常被卡住的“铁三角”。我带过不少刚接触虚拟化环境的开发者和运维新人&…

2026/10/15 13:26:57 阅读更多 →
UEFI DXE阶段驱动开发实战:协议、事件与调试

UEFI DXE阶段驱动开发实战:协议、事件与调试

简介:这份PPT资料围绕UEFI启动流程中的DXE(Driver Execution Environment)阶段展开,面向固件开发工程师、BIOS初学者及嵌入式系统学习者,帮助理解DXE阶段在系统初始化中的核心作用与运行机理。资源共1个pptx文件&#…

2026/10/15 13:25:56 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 9:49:14 阅读更多 →