javascript - Vuejs:将代码分布在多个组件或所有组件中吗?

标签 javascript vue.js vue-component code-organization

因此,我在Vue上玩了很多游戏,而现在我的应用变得越来越大,我对如何组织它感到怀疑。

我了解码件,当您需要在同一页面上多次重复使用它们时,它们很有意义,例如,“自定义选择框”组件,在许多地方可能会需要它们。

但是,只有一次实例的组件又如何呢?示例:一个管理仪表板界面,该界面包含3个区域:一个带有一些导航的侧栏,一个可以根据导航中选择的内容进行编辑的主区域,另一个带有与主区域相关的内容的侧栏。所有这些都需要是单独的组件吗?因为如果页面上每个实例只有一个实例,我看不到这样做的任何好处。另一方面,如果我将所有代码填充在单个“app”组件中,则可以简化一些代码(减少变量)

最佳答案

摘要-使用组件的典型原因:

  • 可维护性。
  • 通过组件边界的渲染性能。
  • 通过分块加载性能。

  • 如果您发现使用更少的组件可以提高可维护性,那很好。这很可能是适合您的应用程序的正确设计。

    详细版本如下。

    使用组件的主要原因是为了提高可维护性。

    在很多地方重用的组件(如选择框)显然比一遍又一遍地重复相同的代码更容易维护。但是,这是值得考虑的。不仅仅是重复使更改所有选择框变得更加困难。使用组件的另一个主要好处是额外的抽象级别可以减少思想上的开销。

    假设有人试图维护代码,看到的是这样的东西(伪代码):

    <select-box :some-prop="blah">
      <select-box-option v-for="something" />
    </select-box>
    

    显然,这是一个select-boxselect-box的所有繁琐的实现细节都被隐藏了,我们不必担心它们。通过查看 Prop ,子组件和事件,我们可以快速推断出哪些数据在父组件和select-box之间往返。这只是关注点分离。

    此好处也适用于未重用的组件。让我们以边栏示例为例。我们可能会在模板的主要组件中看到这一点:

    <nav-sidebar @navigate="onNavigate" />
    

    组件的名称使我们可以快速将其标识为侧边栏。如果我们当前的任务不涉及边栏,那么我们可以跳过模板的那一部分。由于代码已移至其他文件,因此我们可以轻松确定代码的哪些位是侧边栏的一部分,哪些位不是。

    在此示例中,nav-sidebar没有任何 Prop ,只有一个事件。由此我们可以开始得出关于这些组件如何相互作用的一些结论。看来nav-sidebar不需要从主要组件传递的任何内容,它可以很幸福地独立运行。如果需要用另一种方式调试数据流问题,则几乎可以肯定地从onNavigate开始。

    如果一切都被整合成一个大的组成部分,我们就不可能像这样迅速地做出类似的推论。

    当然,这可能是我们的推论是错误的。 nav-sidebar可能做了一些涉及$parent的可怕事情,以从其父组件中获取数据。但是,这仅说明了为什么使用这种技术被认为是不好的做法。可维护的代码应允许开发人员根据似乎已到位的抽象,跳到合理的结论。

    但是有可能走得太远。

    好的抽象可以让您通过将细节隐藏在标签后面来释放一些思维能力。较差的抽象通过将您想看到的代码隐藏在某种间接后面而增加了精神上的开销。再加上命名的困难和额外的粘合代码的负担,您最好抛弃多余的层并使所有内容保持内联。

    可能出错的另一件事是以错误的方式拆分组件。分离关注点需要对这些关注点进行干净的划分。将事情切碎略有不同,最终会导致单个问题分散在多个组件中,并且所产生的困惑通常比您根本不愿意将事情分解的情况更糟。

    Vue允许您以多种方式拆分JavaScript代码,而组件只是其中一种。单独的.js文件,插件,过滤器,Vuex,mixins等。您可以使用几个选项。

    另一方面,只能使用组件来真正拆分模板。如果您想将一个巨大的模板分解为更多可管理的块,那么组件确实是唯一的选择。

    这使我们想到了使用组件的另一个关键原因。

    模板被编译成render函数。运行该render函数时,它会注册反应性依赖项,就像计算的属性一样。如果这些依赖项中的任何一项发生更改,它将触发重新渲染。那将再次运行整个render函数。即使这不会导致DOM发生任何更改,也将需要生成所有相关的VNode,并且差异算法将需要检查所有这些VNode。

    组件边界也是渲染边界。每个组件都根据其依赖项是否已更改决定是否渲染。

    因此,以nav-sidebar为例,假设nav-sidebar有所更改,因此需要进行渲染更新。如果nav-sidebar是一个单独的组件,则只需为该组件运行template / render函数。相反,如果我们将所有nav-sidebar代码 bundle 到主模板中,那么我们将不得不重新呈现所有内容。

    Vue还支持延迟加载的组件,以减少页面的初始加载时间。这个想法是,许多应用程序都具有与大多数用户无关的较大部分,例如管理界面。无需承担下载所有这些组件的开销,您可以将这些组件拆分为多个块,并在需要时下载这些块。这通常是通过Vue路由器配置实现的。

    除了块之外,使用路由器的典型方法是为不同的页面使用单独的组件。从理论上讲,可以对所有路线使用相同的组件,而这不太可能导致更易于维护。我要补充一点,这里的“页面”的定义有点模糊,但是在大多数应用程序中,很清楚什么构成了不同的页面,从而导致了不同的组件。

    如果不提及测试,创建代码整体的书就不会完整。单元测试应该被认为是一种重用形式,并且在这种情况下特别极端。测试对于揭露隐藏在您认为不错,干净的设计背后的意大利面一团糟有着无情的诀窍。我不会对测试进行夸大,但足以说明您将无法将单元测试拆分为合适的单元,否则就无法编写单元测试。

    组件的另一个关键特性是它具有自己的一组属性。它自己的data和它自己的计算属性。这听起来很明显,但是当您考虑通过v-for循环时,它就变得很重要。

    <div v-for="item in items">...</div>
    

    上面的示例使用内联元素而不是组件。任何状态都只能生活在父项上。该状态需要为每个循环项保留,因此我们可能最终得到多个保存状态不同方面的数组。处理循环时,计算属性同样难以实现。我们通常最终使用方法代替:

    <div v-for="item in items" :class="getClassesFor(item)">...</div>
    

    现在考虑组件版本:

    <my-component v-for="item in items" :item="item" />
    

    每个my-component可以保留自己的状态。例如,假设my-component具有扩展/折叠功能。现在可以将其存储在每个实例中的本地data属性中。同样,每个实例将具有自己的计算属性。

    可以说这只是重复使用,因为v-for创建了多个实例。但是,鉴于我们正在专门引入一个新组件以提供一种属性范围,因此我认为值得特别提及。

    关于javascript - Vuejs:将代码分布在多个组件或所有组件中吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58487873/

    相关文章:

    javascript - 生成具有延续性的Javascript代码的诀窍是什么?

    javascript - 将 UI-Bootstrap Modal 与 Angular-Fullstack 和 ES6 结合使用

    javascript - VueJs (Quasar), vuex store access in router

    javascript - Vue js 跟踪范围槽中选定的复选框

    javascript - 在 Javascript 中递归创建多个 Google Charts

    javascript - 无法使用 View 路由器解析异步组件渲染

    javascript - Laravel - 让 vue 与其他插件一起工作

    vue.js - VueJS 路由器守卫实现访问控制机制

    vue.js - 为什么两个具有不同 prop 名称的 Vue.js 相同组件会产生不同的结果?

    javascript - 如何将小数简化为最小的分数?