Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
310 views
in Technique[技术] by (71.8m points)

javascript - Vue.js:将代码分布在多个组件或所有组件中吗?(Vuejs: distribute code across multiple components or everything into a single component?)

So I've played a lot with Vue, and now that my app has become large, I am having doubts about how to organize it.(因此,我在Vue上玩了很多游戏,现在我的应用程序变得很大,我对如何组织它感到怀疑。)

I understand components and that they make sense when you need to re-use them many time on the same page, for example, a "custom select box" component, that will likely be needed in many places.(我了解组件,当您需要在同一页面上多次重复使用它们时,它们很有意义,例如,“自定义选择框”组件,在许多地方可能会需要它们。)

But what about components that will only have once instance?(但是,只有一次实例的组件又如何呢?)

Example: a administration dashboard interface that has 3 areas: a sidebar with some navigation, a main area with stuff you can edit, based on what is selected in the navigation, another sidebar with stuff related to the main area.(示例:一个管理仪表板界面,该界面包含3个区域:一个带有一些导航的侧栏,一个基于导航中所选内容可以编辑的主区域,另一个带有与主区域相关的内容的侧栏。) Do all these need to be separate components?(所有这些都需要是单独的组件吗?) Because I don't see any benefit of doing that if there is only one instance of each on the page.(因为如果页面上每个实例只有一个实例,我认为这样做没有任何好处。) On the other side, if I stuff all the code in a single "app" component, I could simplify some of the code (less variables)(另一方面,如果我将所有代码填充在单个“ app”组件中,则可以简化一些代码(减少变量))   ask by Alex translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Summary - typical reasons for using components:(摘要-使用组件的典型原因:)

  1. Maintainability.(可维护性。)
  2. Rendering performance via component boundaries.(通过组件边界的渲染性能。)
  3. Loading performance via chunking.(通过分块加载性能。)

If you find that using fewer components improves maintainability then that's fine.(如果您发现使用更少的组件可以提高可维护性,那很好。)

It may well be the correct design for your application.(这很可能是适合您的应用程序的正确设计。)

Verbose version below.(详细版本如下。)


The primary reason for using components is to improve maintainability.(使用组件的主要原因是为了提高可维护性。)

Components that are reused in many places such as a select-box are obviously easier to maintain than repeating the same code over and over.(在很多地方重用的组件(例如选择框)显然比一遍又一遍地重复相同的代码更容易维护。)

However, it is worth considering why that is.(但是,这是值得考虑的。) It's not just that duplication makes it more difficult to make a change to all of the select-boxes.(不仅仅是因为重复使得更改所有选择框变得更加困难。) The other key benefit of using a component is that the extra level of abstraction can reduce mental overhead.(使用组件的另一个主要好处是额外的抽象级别可以减少思想上的开销。)

Let's say someone trying to maintain the code sees something like this (pseudo-code):(假设有人试图维护代码,看到的东西是这样的(伪代码):)

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

Immediately it's clear that this is a select-box .(马上很明显,这是一个select-box 。)

All the gory implementation details of the select-box are hidden away and we don't need to worry about them.(select-box所有gory实现细节都被隐藏了,我们不必担心它们。) By looking at the props, child components and events we can quickly deduce what data goes back-and-forth between the parent component and the select-box .(通过查看道具,子组件和事件,我们可以快速推断出哪些数据在父组件和select-box之间来回select-box 。) This is just separation of concerns .(这只是关注点分离 。)

This benefit also applies to components that aren't reused.(此好处也适用于未重用的组件。)

Let's take the sidebar example.(让我们以边栏示例为例。) We might see this in the template for our main component:(我们可能会在主要组件的模板中看到以下内容:)
<nav-sidebar @navigate="onNavigate" />

The component's name allows us to quickly identify it as the sidebar.(组件的名称使我们可以快速将其标识为侧边栏。)

If our current task doesn't involve the sidebar then we can just skip over that bit of the template.(如果我们当前的任务不涉及边栏,那么我们可以跳过模板的那一部分。) As the code has been moved off to a different file we have no difficulty establishing which bits of the code are part of the sidebar and which bits aren't.(由于代码已移至其他文件,因此我们不难确定代码的哪些位是侧边栏的一部分,哪些位不是。)

In this example the nav-sidebar doesn't have any props and only has a single event.(在这个例子中, nav-sidebar没有任何道具,只有一个事件。)

From that we can start to draw some conclusions about how these components interact.(由此,我们可以开始得出有关这些组件如何相互作用的一些结论。) It would seem that the nav-sidebar doesn't need anything passed from the main component, it could quite happily live stand-alone.(nav-sidebar似乎不需要从主要组件传递的任何内容,它可以很高兴地独立运行。) If we need to debug a problem with data flowing the other way we'd almost certainly start with onNavigate .(如果我们需要用另一种方式调试数据流问题,则几乎可以肯定从onNavigate开始。)

We couldn't start making deductions like these anything like as quickly if everything was mangled together into one, big component.(如果一切都被整合为一个大的组成部分,我们就不可能像这样迅速地做出类似的推论。)

Of course it could be that our deductions are wrong.(当然,这可能是我们的推论是错误的。)

It could be that the nav-sidebar does some horrible things involving $parent to grab data from its parent component.(nav-sidebar做了一些可怕的事情,涉及到$parent来从其父组件中获取数据。) However, that just illustrates why using such techniques is considered bad practice.(但是,这仅说明了为什么使用这种技术被认为是不好的做法。) Maintainable code should allow developers to jump to reasonable conclusions based on the abstractions that appear to be in place.(可维护的代码应允许开发人员根据似乎已到位的抽象,跳到合理的结论。)

But it is possible to go too far the other way.(但是有可能走得太远。)

A good abstraction allows you to free up some mental capacity by hiding details behind a label.(好的抽象可以让您通过将细节隐藏在标签后面来释放一些思维能力。)

A poor abstraction adds mental overhead by hiding the code you want to see behind some indirection.(较差的抽象通过将您想看到的代码隐藏在某种间接后面而增加了精神上的开销。) Add to that the difficulty of naming things and the burden of extra glue code and you may well be better off just ditching the extra layers and keeping everything inline.(再加上命名的难度和额外的粘合代码的负担,最好放弃一些额外的层并使所有内容保持内联。)

The other thing that can go wrong is splitting components up in the wrong way.(可能出错的另一件事是以错误的方式拆分组件。)

Separating concerns requires clean partitions of those concerns.(分离关注点需要对这些关注点进行干净的划分。) Chop things up slightly differently and you end up with a single concern being spread across multiple components and the resulting mess is typically worse than if you hadn't bothered splitting things up at all.(将事情切碎的方式略有不同,最终会导致单个问题分散在多个组件中,并且所产生的混乱情况通常比不进行拆分的情况更糟。)

Vue allows you to split up your JavaScript code in a number of ways, components being just one.(Vue允许您以多种方式拆分JavaScript代码,而组件只是其中一种。)

Separate .js files, plugins, filters, Vuex, mixins, etc.. There are several options available to you.(单独的.js文件,插件,过滤器,Vuex,mixins等。您可以使用几个选项。)

Templates, on the other hand, can only really be split up by using components.(另一方面,只能使用组件来真正拆分模板。)

If you want to break a huge template down into more manageable chunks then components are really the only way to go.(如果您想将一个巨大的模板分解为更多可管理的块,那么组件确实是唯一的选择。)

This brings us to another key reason for using components.(这使我们想到了使用组件的另一个关键原因。)

A template is compiled down into a render function.(模板被编译成render函数。)

When that render function is run it registers reactive dependencies, just like a computed property.(运行该render函数时,它会注册反应性依赖项,就像计算的属性一样。) If any of those dependencies changes it will trigger a re-render.(如果这些依赖项中的任何一项发生更改,它将触发重新渲染。) That runs the whole render function again.(那将再次运行整个render功能。) Even if that doesn't result in any changes to the DOM it will require the generation of all the relevant VNodes and the diffing algorithm will need to check all of them.(即使这不会导致DOM发生任何变化,也将需要生成所有相关的VNode,并且差异算法将需要检查所有这些VNode。)

Component boundaries are also rendering boundaries.(组件边界也是渲染边界。)

Each component makes its own decision about whether or not to render based on whether its dependencies have changed.(每个组件都根据其依赖项是否已更改来决定是否渲染。)

So, taking the nav-sidebar example, let's say something changes in the nav-sidebar so that it needs a rendering update.(因此,服用nav-sidebar例子,比方说在一些变化nav-sidebar ,以便它需要一个描绘更新。)

If the nav-sidebar is a separate component then it just needs to run the template/ render function for that component.(如果nav-sidebar是一个单独的组件,则只需运行该组件的模板/ render功能。) If instead we bundle all the nav-sidebar code into the main template then we'll have to re-render everything.(相反,如果我们将所有nav-sidebar代码捆绑到主模板中,那么我们将不得不重新呈现所有内容。)

Vue also has support for lazily loaded components as a way to reduce the initial load time of the page.(Vue还支持延迟加载的组件,以减少页面的初始加载时间。)

The idea is that many applications have large sections, such as admin interfaces, that aren't relevant to most users.(这个想法是,许多应用程序都具有与大多数用户无关的较大部分,例如管理界面。) Rather than incurring the overhead of downloading all of those components you can split the components into chunks and download the chunks when they're needed.(无需承担下载所有这些组件的开销,您可以将这些组件拆分为多个块,并在需要时下载这些块。) This is usually implemented via the Vue router configuration.(这通常是通过Vue路由器配置实现的。)

Chunking aside, the typical way to use the router is to have separate components for the different pages.(除了块之外,使用路由器的典型方法是为不同的页面使用单独的组件。)

While in theory it is possible to use the same component for all routes that is unlikely to lead to something more maintainable.(从理论上讲,可以对所有路线使用相同的组件,这不太可能导致某些事情更容易维护。) I would add that the definition of 'page' is a little fuzzy here but in most applications it's clear what constitutes a different page, resulting in a different component.(我要补充一点,这里的“页面”的定义有点模糊,但是在大多数应用程序中,很清楚什么构成了不同的页面,从而导致了不同的组件。)

No tome on creating code monoliths would be complete without some mention of testing.(如果不提及测试,就无法完成创建代码整体的工作。)

Unit testing should be thought of as a form of reuse and a particularly extreme form at that.(单元测试应该被认为是一种重用形式,并且在这方面是一种极端的形式。) Tests have an unrelenting knack for exposing the mess of spaghetti that hides behind what you thought was a nice, clean design.(测试对于揭露隐藏在您认为不错,干净的设计背后的意大利面一团糟有着无情的诀窍。) I'm not going to pontificate on testing but suffice it to say that you won't be able to write unit tests unless you split things into suitable units.(我不会夸大测试,但是足以说明您将不能将单元测试拆分为合适的单元,否则就无法编写单元测试。)

Another key feature of a component is that it has its own set of properties.(组件的另一个关键特性是它具有自己的一组属性。)

Its own data and its own computed properties.(它自己的data和自己的计算属性。) This sounds obvious but it gains significance when you consider looping via v-for .(这听起来很明显,但是当您考虑通过v-for循环时,它就变得很重要。)
<div v-for="item in items">...</div>

The example above uses inline elements instead of components.(上面的示例使用内联元素而不是组件。)

Any state can only live on the parent.(任何状态都只能生活在父项上。) That state needs to be held for each loop item, so we may end up with multiple arrays holding different aspects of the state.(该状态需要为每个循环项保留,因此我们可能最终会得到多个保存状态不同方面的数组。) Computed properties are similarly difficult to implement when working with loops.(处理循环时,计算属性同样难以实现。) We typically end up using methods instead:(我们通常最终使用方法代替:)
<div v-for="item in items" :class="getClassesFor(item)">...</div>

Now consider the component version:(现在考虑组件版本:)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...