作为 Vue 开发人员,您是否犯了这些错误?

2025-06-10

作为 Vue 开发人员,您是否犯了这些错误?

我最近订阅了 Adam Wathan 主持的精彩 Web 开发播客《 Full Stack Radio》。其中有一集探讨了Vue.js 中的反模式, Vue 核心团队的 Chris Fritz 就 Vue 架构分享了许多实用技巧,并分享了一些 Vue 开发者常犯的错误。我并没有涵盖所有讨论内容,所以请务必收听完整的播客节目,了解一些精彩的对话和 Vue 的精髓。我会在本文末尾附上链接。

这集讨论了各种各样的话题。以下是我的笔记:

状态管理和事件:

对于复杂的状态,Vuex 是最佳选择。人们通常使用事件总线来管理状态,让组件订阅事件。但最终会导致创建大量重复的状态,这在尝试保持所有内容同步时会引发一系列问题。在调试时,无法知道某个更改来自哪里。

Vuex提供丰富的选项,并且易于追踪。Vue DevTools 中有一个单独的 Vuex 选项卡,这对于调试和原型设计都非常有用。我们可以跟踪不同的状态变化,更改样式,并通过 HMR(热模块重载)即时查看更改的生效。对于小型项目,组件之间可能只需要一两个事件进行通信,那么事件总线就足够了。

如果您发现自己正在做以下一项或多项事情,那么这是一个很好的指标,表明您应该开始使用 Vuex 来管理项目中的复杂状态:

  1. 当你不断向组件传递大量 props 时
  2. 让父组件跟踪子组件的状态,以便兄弟组件可以通过父组件相互交互
  3. 当传递给组件的 props 不被该组件本身使用,而是被嵌套在其中的另一个组件使用时

另一个禁忌是使用this.$parent事件而不是触发事件来访问和操作父组件的状态。这看起来可能很简单,因为我们清楚地知道子组件在父组件中改变了什么。但如果项目规模庞大,尤其是已经进行了相当长一段时间,就很难追踪整个过程,并记住为什么父组件内部会发生某个变化。这看起来可能是一个不错的解决方案,甚至可以复用。即使你不再使用它,其他开发人员(你的同事,或者如果你在开源软件上工作,则是你的贡献者)也可能会用到。每当这种情况发生时,都会使代码难以理解,调试也变得非常困难。

自定义事件和回调 props,哪个更好?

自定义事件是我们发出某个事件并通过它传递值的事件:

this.$emit('modal-closed', this.isClosed);
Enter fullscreen mode Exit fullscreen mode

另一方面,回调 props 是父组件作为 prop 传递给子组件执行的普通方法。这样做是为了替代像自定义事件那样将值传回父组件:

<button @click="onClose">Close Modal</button>
Enter fullscreen mode Exit fullscreen mode

所以它们都用于执行相同的任务。在第一种情况下,我们通过事件将一个值传递给父级,然后父级执行一个方法或使用该值执行所需的操作。在第二种情况下,我们将要执行的方法传递给子级本身,期望它代表父级执行该方法。

那么哪个更好?

几乎没有区别。就像Chris说的:

这是风格化的

这意味着它完全取决于用户。如果您一直在使用一种方法,则没有理由更改它。不过,如果您还没有认真考虑使用哪种方法,不妨考虑使用自定义事件。自定义事件系统在保密性方面要好得多。它阻止家长了解不必要的信息。由于我们传递的是单个值,因此家长只会被告知必要的细节。

在组件驱动的项目中,目标是专注于组件本身,而无需担心其他组件。通过让子组件代表父组件执行某个方法,我们不仅需要依赖一个组件为另一个组件执行某个方法,而且我们可能还不知道该子组件正在执行该方法。

如果组件太多,或者某个父组件有很多子组件,就可能会发生这种情况。几个月后,情况可能会变得混乱,我们可能很难只通过查看父组件来记住该方法是如何执行的。

这并不意味着使用回调 props 有任何缺点。使用自定义事件感觉更像 Vue,官方 Vue 文档中也有演示。

什么时候使用观察者比较合适?计算属性更好吗?

计算属性和观察者的功能非常相似,以至于大多数 Vue 新手开发者都会感到困惑,不知道该选择哪一个。通常,观察者最适合用于异步任务。

如果希望在一个状态更新时也更新另一个状态,则需要计算属性。一个简单的例子是从和派生一个fullName属性firstNamelastName

使用观察器会很繁琐,因为我们必须为每个需要跟踪的属性创建一个观察器。试图通过密切监视某个属性所依赖的所有属性来更改该属性的状态,这需要大量的工作。

在这种情况下,计算属性就派上用场了。我们只需赋予它依赖的属性即可。一旦任何属性发生变化,它就会重新求值并进行相应的更改。该属性会被缓存,这样除非它确实发生了变化,否则就无需每次都进行不必要的重新求值。

这是计算属性相对于常规方法和观察者的性能优势。

这并不意味着观察者毫无用处。有些情况下,计算属性对我们毫无帮助,而我们需要的是方法无法提供的响应式功能。因此,在这种情况下,观察者是最佳选择。

我在做个人项目时也遇到过类似的情况。我有一个用户数组,每个用户都是一个对象。数组中有 3 个单选按钮,根据选中的按钮,需要显示特定的用户。有一些方法可以选取需要显示的用户。使用一个简单的点击监听器来运行这些方法相当简单(我就是这么做的)。但如果我们必须在计算属性和观察者属性之间做出选择,那么在这种情况下,计算属性就无法使用了。

计算属性通过从一个或多个属性的状态变化中得出结果并返回一个值来工作。

因此,就这一点而言,观察者是两者中最适合的。

如果您想了解有关使用方法、计算属性和观察者的更多信息,请务必查看 Sarah Drasner 的这篇深入文章

以正确的方式重用代码

在 Vue 中,有很多方法可以复用代码。其中三种是广为人知且在开发人员中颇受欢迎的:

  • 使用组件
  • 使用指令
  • 使用 mixin

利用组件实现代码复用是 Vue 的核心基础。然而,Chris 告诉我们,许多开源插件本可以作为组件使用,却用上了指令和混合宏。许多开发者错误地使用了混合宏和指令。

mixins 的一个很好的用例是当我们希望组件执行与其通常的特定行为不同的事情时


指令用于在多个不同元素之间共享行为。它们在元素上更有意义,而不是将该行为作为单独组件的一部分。我们经常会看到一些行为非常通用,不够具体或独特,因此不需要为它们单独创建一个组件。

Chris 提到了一个关于自动对焦功能的很好的例子。我们需要手动操作 DOM,但用得不多,所以需要一个组件来实现它。在这种情况下,指令是最好的选择。


人们似乎经常使用 mixin,有时甚至在没有必要的情况下也会用。作用域插槽提供与 mixin 相同的功能,并且在大多数情况下是更好的选择。我们绝对需要使用 mixin 的情况非常特殊。作用域插槽更具组合性,我们需要的一切都由包装器组件提供,我们可以选择要包含的内容。

mixin 的一个好用例是,当我们有一些组件执行非常具体的操作,但根据具体情况,我们希望它们执行不同的操作时。我们可以创建一个 mixin,它是一个返回组件选项的函数。这样我们就动态地生成了组件行为。对于这种动态行为,我们还需要一些变量。与其将它们与必需的变量一起放在组件中,不如将它们放在这个函数中。


这集里有更多有趣的对话,还有很多值得学习的内容。我建议至少听一遍,更好地理解内容,然后再订阅这个精彩的播客。

您可以在这里找到播客节目。您可以在 Twitter 上找到上面提到的所有人——Sarah DrasnerChris FritzAdam Wathan。请务必关注他们,以便及时了解他们的工作进展。如果您对 Vue 有任何疑问,我相信这些人会非常乐意为您提供帮助。如果我遗漏了任何应该添加到本文中的好建议,请在下方评论区留言。

鏂囩珷鏉ユ簮锛�https://dev.to/napoleon039/are-you-committing-这些-mistakes-as-a-vue-developer--566k
PREV
The common misconception about TypeScript
NEXT
测试驱动开发示例