普通视图

发现新文章,点击刷新页面。
昨天 — 2025年7月1日首页

组件通讯要注意内存泄露

2025年7月1日 14:27

作者:程序员成长指北 原文;mp.weixin.qq.com/s/ymcR2ISHb…

在 Vue 中,兄弟组件之间的通信可以通过多种方式实现,以下是一些常用的方法:

1、 使用父组件作为中介(或状态提升)

•兄弟组件可以通过父组件进行通信。一个兄弟组件可以通过事件将数据发送到父组件,父组件再将数据传递给另一个兄弟组件。

•实现步骤:

1.在第一个兄弟组件中,使用 $emit 触发一个事件,将数据传递给父组件。2.在父组件中,监听该事件并接收数据。3.在父组件中,将接收到的数据通过 props 传递给另一个兄弟组件。

2、 使用事件总线

•事件总线是一种轻量级的发布-订阅模式,通过创建一个空的 Vue 实例作为事件中心,兄弟组件可以在事件中心上监听和触发事件。•实现步骤:

1.创建一个新的 Vue 实例,并将其导出作为事件总线。2.在一个兄弟组件中,使用 $emit 在事件总线上触发事件。3.在另一个兄弟组件中,使用 $on 在事件总线上监听该事件。

// eventBus.jsimport Vue from 'vue';export const EventBus = new Vue();
// BrotherComponentA.vueimport { EventBus } from './eventBus.js';EventBus.$emit('event-name', data);
// BrotherComponentB.vueimport { EventBus } from './eventBus.js';EventBus.$on('event-name', (data) => { // Handle data});

在使用 EventBus 时,如果不正确地管理事件监听器,可能导致内存泄露。特别是在组件销毁时,如果没有移除监听器,组件可能无法被垃圾回收,从而导致内存泄露。

为了避免这种问题,在组件销毁时应该移除事件监听器。可以在组件的 beforeDestroy 钩子(Vue 2)或 onBeforeUnmount 钩子(Vue 3)中调用 $off 方法来移除监听器。

// BrotherComponentB.vueimport { EventBus } from './eventBus.js';
export default {  created() {    EventBus.$on('event-name'this.handleEvent);  },  beforeDestroy() {    EventBus.$off('event-name'this.handleEvent);  },  methods: {    handleEvent(data) {      // Handle the event    }  }}

通过在组件销毁时移除事件监听器,可以有效地避免内存泄露问题。这是使用事件总线时的一个重要实践,确保应用程序的性能和稳定性。

你也想成为高手么,那就像高手一样调试程序

2025年7月1日 14:25

一个关于如何高效调试软件的指南,强调采取 detective mindset、熟练掌握工具、善用 print 函数、团队协作共享调试经验以及利用 rubber duck debugging 等方法来提高调试效率。今日前端早读课文章由 @Juhis 分享,@飘飘编译。

译文从这开始~~

像侦探一样思考

一个优秀的调试者,应该像侦探一样去面对问题。优秀的侦探不会凭空猜测或做出假设,而是一步步追踪线索,仔细检查证据,并通过逻辑推理得出结论。

我经常看到无论是初级开发者还是资深工程师,面对问题时要么死盯着代码希望奇迹出现,要么凭经验跳到结论,觉得自己知道问题在哪。结果就是浪费好几个小时,最后发现自己完全在错误的方向上兜圈子。

图片

💡 提示 1:像一个对这段代码一无所知的人那样,按部就班、逐步排查。

  • 确认你正在查看的代码确实被执行了。一个简单的方法是在你检查的每个函数开头加一条 print (或 console.log)语句,确认代码是否运行。
  • 重现 bug。你必须知道怎么触发问题,否则你也无法确认问题是否已解决。
  • 检查变量状态:打印变量的值,或者使用调试工具一步步查看发生了什么。

我发现,每当我在代码库中 “移动” 思考时,反复执行这三个步骤,几乎总能找到 bug 的根源。

对于前端开发者来说,很多 bug 来自异步操作,比如:

  • Promise 未正确返回;
  • await 被遗漏;
  • UI 更新顺序混乱。

此时可以用 Chrome DevTools 的异步堆栈跟踪来帮助我们厘清问题:

  • 在 DevTools 的 Source 面板中打开 Call Stack;
  • 勾选 “Enable async stack traces”;
  • 设置断点,观察异步逻辑是如何一步步触发的。

这比单纯依靠 “猜测 Promise 哪里没返回” 更有效。

投资时间学习你的工具

软件开发行业的工具五花八门,而且大多数工具都是免费的或开源的,几乎没有什么金钱成本。但你需要花时间去学习和掌握它们。

我认为调试是一种双重技能:一方面是前面讲到的思维方式和流程,另一方面就是强大的工具,只有两者结合,才能高效地发现并解决问题。

在日常工作中,我们很容易停留在自己熟悉的那一套工具里,不去了解别的选择,不去查看更新日志,也不知道其他人都在用什么工具解决类似的问题。

💡提示 2:熟练掌握你的语言中的打印、日志、调试器和代码编辑器。这样你就能专注于解决问题,而不是浪费精力在 “怎么用工具” 上。

对于前端开发者来说,除了 console.log,还有许多更高效的调试手段:

📍 断点调试(Breakpoints)

  • 行断点 - 定位特定语句;
  • 条件断点 - 只在变量满足条件时中断;
  • DOM 断点 - 监听元素变化;
  • XHR 断点 - 请求发出时暂停。

在 Chrome DevTools 的 Source 面板中,这些断点设置都非常直观。

⏱ 性能调试(Performance)

  • 用 Performance 面板录制页面行为;
  • 分析 JS 执行时间、Layout 重排;
  • 找出动画卡顿、长任务等瓶颈。

适用于页面流畅度优化和交互延迟排查。

🌐 网络调试(Network)

  • 查看请求是否发出、返回是否正常;
  • 检查 status code、header 和响应数据;
  • 发现跨域问题、缓存设置错误等问题。

例如你遇到 “登录请求发了但页面没跳转”,可以通过 Network 面板确认请求返回是否正常,再去检查 JS 逻辑是否响应了返回结果。

在 Python 中,调试工具有 built-in debugger、PuDB、web-pdb、birdseye 等。在前端,除了 DevTools,也可以结合 VS Code 的 Debug 面板进行跨项目调试。

不断探索这些工具,并根据自己的项目特点选择最顺手的一种,是非常值得投入时间的事情。

打印是最好的调试起点

图片

我在各个地方写文章或演讲时,关于调试我最常遇到的一个反馈就是:很多人对使用打印语句(print)调试存在偏见。

有不少人告诉我,他们的同事说 “打印是不好的做法”,但在我讲完之后,也有人跑来和我说 “太高兴有人告诉我,打印其实不是错的”。

打印是最好的调试工具,因为它几乎没有门槛。你不需要安装或配置任何东西,写一句打印语句只要几秒钟,也很容易在输出中找到结果。而且如果问题本身不复杂,这绝对是最快的方式。

💡提示 3:不要吝啬使用 print!

你越愿意用打印,调试时就越容易上手,而不是陷入死盯代码或胡乱猜测的误区。当然,打印不是最强大的调试手段,也不是最复杂的工具,有时候它不够用 —— 这时候你可以升级到更强的调试器。但打印是你调试之旅最好的起点。

与同事分享经验,共同成长

Jenn Creighton 在她的演讲《Now And Then: Debugging Async JS》中说得很好:

“最好的调试工具,是你对某个东西的理解。”

她提到,长期使用某种技术、某种方法或某个代码库后,会积累很多经验。当你再遇到问题时,大脑会下意识地想起以前的经历,帮你更快判断该先验证哪些假设。

这种经验,很多时候是个人积累的。但其实,它完全可以共享出来。就像我鼓励大家分享工具使用心得一样,我也鼓励你把调试 bug 的经验分享给项目组或团队成员。

💡提示 4:记录下你的调试经历,偶尔组织一次午餐分享会或周五学习时间,讲讲你遇到的 bug 和解决过程。

这些故事不需要是什么重大事故,也不用是 “英雄行为”,而是日常遇到的普通问题。如果我从五位同事那里听到与 “时区问题” 相关的调试经历,当我真的遇到时区 bug 的时候,自然就能更有准备。

你可以尝试以下方式进行知识共享:

  • 在团队的 Wiki、Notion、Confluence 上建立调试经验库;
  • 每周组织一次 “Bug Friday” 或 “午餐分享”,讲讲你遇到的 bug;
  • 总结典型坑,比如跨域失败、异步更新顺序、时区相关错误等。

📄 调试经验记录模板参考:

 【问题描述】登录接口返回 200 但页面无跳转

 【触发方式】登录后点击按钮,开发环境正常,线上异常

 【定位过程】

   - 检查 Network,请求返回正常
   - 发现 login 函数中 Promise 没有 await
   - 修复后跳转恢复正常

 【复盘总结】

 需加强对异步流程的规范管理,避免状态未更新时提前进行跳转逻辑

跟橡皮鸭说话

如果你真的尝试了所有办法还是卡住了,那就请出橡皮鸭吧。橡皮鸭调试(Rubber duck debugging)虽然在行业里有点像是个玩笑,但它其实真的是一种非常有效的方法。

图片

简单来说,方法如下:

  • 拿一只橡皮鸭(没有鸭也可以用别的玩具动物,实在不行就拉同事来)
  • 把你的问题完整地说出来;
  • 告诉它你已经尝试过哪些方法、为什么没成功
  • 向它寻求建议

我的经验是:往往在鸭子还没 “回答” 之前,你自己就已经想出解决办法了。

💡提示 5:多跟鸭子说话,或者写下来你的想法,帮助理清思路、发现隐藏的假设漏洞。

这是因为我们大脑在自己思考时很容易 “骗自己”。当你自己和自己对话时,大脑会跳过一些细节。你可能觉得 “我已经试过了”,但其实你跳过了某些步骤,因为它 “看起来太明显”。当你必须用语言讲出来,就会强迫自己梳理所有细节。这时候,缺失的步骤就很容易暴露出来了。

找到这些 “漏掉的步骤”,通常就能帮助你发现问题所在,至少也能帮你推进一步。

鸭子议会:向自然取经

图片

我以前住在柏林时,附近一棵树下住着一群野鸭。我称它们为 “Rummelsburg 鸭子议会”。当我自己手边的三只橡皮鸭不够用了,我会去散步顺便 “向议会请教”。

这当然是一种幽默表达,但它背后的原则是真实有效的:调试的本质就是不断验证假设,不断缩小问题范围。

🦆!

最后总结

调试不仅仅是修复 bug,更是一项核心的开发技能。通过本文你应该能意识到:

  • 思维方式 > 工具;
  • 简单方法(如打印)也很有价值;
  • 工具熟练度和团队交流能极大提升调试效率;
  • 问题不可怕,找到它的方法才重要。

关于本文
译者:@飘飘
作者:@Juhis
原文:flaky.build/debug-like-…

❌
❌