(Why) should I *always* use components in any vue.js app, however simple?

Viewed 1172

I am just getting started with vue.js, and already created most of the very small functionality I need from just the first getting started chapters of the documentation.

Now I want to add some tests to ensure my functionality always works after changes (normally I do TDD but this time I had to learn vue first and decide if i keep using it).

So looking for documentation I basically see that just about every documentation/howto on vue testing is about testing components. I really found none else.

This leads me to the question as stated in the subject:

Is it a necessary practice to use vue components, even for the most simple application, when I have definitely nothing that i want to reuse as a component? Besides the current case of only finding documentation on how to test a componentized vue app, will I run in other problems?

I searched the web and the vue docs(at least there I'd hope for a sentence of explanation if and why I should always use components in the "essentials/Components basics" chapter, but dont find it...), and here, but I couldn't find a clue if and why it might be a generally bad idea not to use components.

Based on the questions I see in comments, it seems necessary to explain why I even ask such a question:

  • I don't criticize components in general or say they are a bad idea - I see that basically abstraction and separation of concerns is often helpful, even important in many cases.
  • At the same time, for any kind of abstraction, layering, and separation, there is a line below which introducing it brings more overhead in terms of additional files, glue code to put things together, and tools needed to use it (in the case of vue components special editors capable of properly displaying and syntax highlighting .vue files) than advantages.
  • The vue documentation itself starts without components, which in my understanding suggests that not all users should use components in any case.
  • It seemed to me that I am pretty close to this line, and I was looking for advice and reasons if I should consider my app being above the line so I should introduce components, or I can assume I am below. Answers I thought of would be like "even though you might not benefit a lot from components, and will have to add 3 more files to your 3 files app, doubling the number, it's highly recommend to use them, because nearly all documentation, and most tooling for vue assumes components being used." - or "Just go ahead, introduce components when you think it fits". I got a helpful answer in the meantime that I marked as such.
1 Answers

Firstly, I think I need to dwell a little on what a component is before considering whether you need to use them.

The early pages on the documentation use the term 'component' to describe a pre-defined set of options for creating a Vue instance. In that sense they can be thought of as 'classes', though technically they aren't JavaScript classes.

The term 'component', however, is frequently used to describe the instances too. In that sense you already are using components, albeit one big component.

Obviously the term can be used even more generally as it isn't a Vue-specific term.

It is worth noting that components do not need to be registered using Vue.component. It would not be unusual for an application to have many components without ever using Vue.component. The components can be imported locally instead.

Based on the question I assume you have a main JavaScript file, let's say main.js, that includes all your Vue-related JavaScript. The key section may look something like this:

new Vue({
  data () {
    return { /* some data */}
  },

  computed: { /* ... */ },
  methods: { /* ... */ }
}).mount('#app')

Loosely speaking, the Vue instance here could be described as a component. If we're being a little stricter, then only the configuration would be considered a component and even then only if it's 'pre-defined'. It's not entirely clear what that even means. For example, would just moving the configuration out be enough to make it 'pre-defined'?

const App = {
  data () {
    return { /* some data */ }
  },

  computed: { /* ... */ },
  methods: { /* ... */ }
}

new Vue(App).mount('#app')

Or does App need to be moved to a separate file for it to count as 'pre-defined'?

Moving on...

Components are the only way to split up your template into multiple pieces. They're also the main way to split up the JavaScript. The question 'do I have to use components?' is implicitly asking 'is it acceptable to have all my code in one file?'. That question applies to all programming, it isn't really a Vue question.

If you're happy that your application is so small and so simple that it doesn't need splitting up into smaller pieces then fine, don't introduce any more components.

However, the question mentions 'changes'. That implies that the application isn't complete, suggesting that it's premature to decide that it's small and simple. If there's going to be enough on-going work to justify the overhead of writing tests it seems unlikely that it really is as simple as you've suggested.

Reuse is definitely not the only reason to split an application into multiple components but it is worth further considering your belief that you don't want to reuse anything. Writing unit tests is reuse. The problem of unit testing a monolith is not a Vue-specific problem and the usual solution is to split the code up into small, testable pieces. You can't write unit tests without introducing suitable units. Of course other forms of testing are available.

Reuse via components is just the flip side of duplication. It's rare not to have any duplication, even in a simple application. Even something as simple as two buttons with matching classes could be considered enough duplication to justify introducing a component. You might prefer to avoid the mental overhead of the extra abstraction.

There are other benefits to components, but for a truly trivial application they're unlikely to matter.

For example, when the UI updates it will only re-render the Vue instances that need it. If everything is in one instance then it will have to re-render everything.

As another example, it's difficult to use computed properties in conjunction with a v-for as you can't pass arguments to a computed property. Instead you end up having to use a method:

<div v-for="item in items" :class="someMethod(item)">

If you introduce a component...

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

... then the component can use a computed property instead.

Related