Refactoring into Vue Components: Readability vs Complexity - vue.js

Background
I have a large form in Vue that I want to refactor to make it easier to see whats going on from a developer point of view. i.e. I'd rather work on sub-sets of the form in different files instead of trying to work on a single file with 100s of lines of code.
The form is simple (just inputs with v-model binding to data), and the main bulk of code is in the <Template> tag that Vue uses.
To reduce the parent file, my initial go-to solution was to refactor different parts of the form out into their own components. This achieves my goal of creating an easier to read parent file, and be able to work on small areas of the form in isolation.
The problem however is that now I have to deal with the complexities of parent <-> child component communication. This is easy when you have one parent with many children, but once the child components are refactored further and they too have children, passing all the form data back to the parent becomes overly complex with standard Vue coding.
The go-to solution for this problem is to use Vuex. But here lies my question:
Question
I've tried to improve the readability of my large form by refactoring into components, but in the process I've add the overhead of component state communication. Have I missed some more obvious way to refactor out my large form? Or do we just have to live with the complexity of components if we want to improve readability?

Related

VueJs Mulitple Component Instances - Performance Impact

This question is related to understanding how Vue handles component instances.
I have a 'smart text area' this text area component has many methods within for highlighting text, regex matching and updating the text area changes in the backend. So it's a relatively complex component. The user can create and unlimited number of these components.
What i'm struggling to understand is, does Vue create a brand new instance of these components every time or does it re use the same component code in the same way we use regular functions?
My concern is that if a user creates 1000 text areas we now have 1000 instances of all of the heavy methods used in each component. This could lead to serious performance issues.
Is this the correct understanding of how these components work?

Performance cost of increasing the number of components in Vue.js

I'm currently building an app and I have a pretty complex component to rework. I was considering splitting sub functionalities of this component into various other components for ease of maintaining. And then I asked myself if increasing the number of component types had a cost on the overall performance of my app.
To add a bit of context I'm working on a search page that references songs playable on a twitch stream. Each song is an item of a big list (the list is lazy loaded as the user scroll and I use a virtual scroller to minimize performance issues), for each item I have various pieces of information to display (some tags, some meta data, etc) and I wanted to split my component in sub-component to reduce the size of the song component (currently rocking 1200 lines of code).
So, would splitting this big component into sub-component have an impact on performance and if so is it mitigable?
In addition to having more maintainable code, you may actually see a performance improvement by breaking the large component into sub-components based on how Vue handles re-rendering when it detects changes in a component.
In my experience, Vue handles v-for loops over sub-components efficiently - even very complex sub-components.
As you add more components, you might want to consider implementing Vuex store and (maybe) an event bus.

How to use Vuex in large Vue apps

Vuex is great and too much greatness is not always good.
So how much Vuex is too much Vuex? And how much prop drilling is too much prop drilling?
Let's imagine the following module about editing a contact. How would you share data between your components? Would you rather use Vuex or props with multi-level event emitting?
Please, consider this an abstract example, don't suggest changing the structure of the module:
ContactEdit GETs the data from the server.
ContactEditAvatar shows non-editable part of the data (e.g. the
avatar of the contact)
ContactEditForm shows the editable data and allows the user to edit
it.
ContactEditSubmit contains the submit button, that POSTs the newly
edited data.
How would you pass data around?
There are four options to approach this:
Provider/inject is not considered an option, as it is not recommended for two-way data binding.
We can also eliminate option 3 immediately as it doesn't expose the edited data from ContactEditForm to the submit button in ContactEditSubmit.
But what about 1,2 and 4?
Option 4 keeps all components small, logic is placed next to corresponding template and everything is beautifully modularized.
However, this approach can potentially make tracking data changes a struggle, after the app becomes bigger, so option 2 is a great alternative, because all the module logic is in a single component and anything can be traced easily.
Props and events should also be able to do the job (option 1) and on first sight it actually looks easier and more intuitive.
However, I feel this approach is not scalable enough and can cause real headaches when unexpected changes on the components come in the future. Also, too much props make the code harder to read, imo.
Personally, I would go with option 4, but what do you, guys, think?
Please, when posting your response, share your experience with large-scale SPAs.
Thanks and have a great and productive week ahead

Reusing Components and Maintaining State with Vue

I have created a few linked Vue components that I reuse between multiple projects. Eventually I would like to do it with NPM or a tool like Bit, but right now I am doing it manually.
All of my components are just passing data between themselves using props and emits. This has gotten pretty inefficient as a lot of my components do not sit right next to one another all of the time, so I want to move them over to a more robust solution. Right now I am finding myself having to emit the same data multiple times just to get back up the chain.
Through reading I know that a global event bus can be used to maintain state between components, or Vuex could be used to maintain my overall application state, but how do I factor this into reusable components?
In my head it feels like if I base my components on either option, then I am committing to always using that component with a global event bus or Vuex. And obviously in some projects I may want to switch between using one or the other, depending on the application's complexity.
How do I best approach this? Do I need slightly different components depending on the overall application (this feels like I lose the reuse-ability) or is there something I am not taking into account here?
For one of my applications I have the following simplified component structure:
Root Component
Grid
Card
FilterDropdown
Graph
Currently I pass the data into my root component from the API, then pass it down to the Graph component through props at each stage.
On the other side, my FilterDropdown gets a distinct list of one of the data's columns, and provides a dropdown where the user can select a value. This values is then emitted 3 times back up the tree to the root component, where it is used to filter the data via a computed property, that is then passed down again using the same props.
Am I over-complicating things by thinking this needs changing? I can already imaging how I could achieve the same thing, with less overall confusion, by using an event bus or Vuex, but in my head I think I would lose some reuse-ability?
If an app is passing around props to unrelated components or it's becoming tedious to maintain a props/emit chain through multiple descendants, then it's probably a good time to use one of the options you mentioned. From the Vuex docs:
passing props can be tedious for deeply nested components, and simply doesn't work for sibling components.
If the architecture isn't that complicated, there's probably no need to switch. But if there is...
Vuex Modules
Since Vuex allows for modules, you can probably eliminate the question of whether it negatively impacts component reusability. You can think of the component(s) + their dedicated Vuex module(s) as a package. The Vuex module can encapsulate all of the necessary store functionality without affecting any part of the store of an app that utilizes it.
Plugins
You could even create plugins from these components and use dynamic module registration to register their associated Vuex module in the app's existing store.
You could do something similar with a plugin and event bus.
Instead of thinking of this as committing to a limitation, you can view it as the plugin providing an interface for apps to take advantage of its features. You could also go with an "all of the above" approach and create a solution for each option.

When to split a Vue component into multiple components (sub components)

When creating Vue components, how does one decide when to separate out a component into a parent component with multiple child components versus just having a single component with more logic?
I am using Vue in a few places on a non-SPA website. On one of the pages of the site I need to display a list of items, with some icons next to each item to do some simple things like show/hide. I am building the list as a Vue component, lets call it ProductList. But I am not sure whether to make each item within that list a separate component or not. When is it appropriate to split a component into multiple sub components?
My own reasoning tells me that components should only be created for things that need to be able to stand alone. Since the items are not going to be used outside of a list, there is no point in having them a separate ProductListItem component to put inside the ProductList component. I should just have all the code in the ProductList component. Right?
But when I look at other examples on the internet, many of them tell a different story. For instance, I recall seeing an example where there was an Article component, an ArticleTitle component, an ArticleBody component, and an ArticleEnd component (or something like this). The template of the Article Component had <article-title>, <article-body> and <article-end> within it. If an ArticleTitle component or an ArticleBody component is only going to be used inside the Article component, not standalone, why bother having it be a separate component? Am I missing something here? Is there a technical criteria on which to base the decision of whether to have multiple components or is it just personal preference?
Interesting question, I think this really depends on the developers and its all gonna become agree to disagree. However, wanna share my experience if it helps:
In a most optimised system design, it should be split into components, because thats what modern frontend framework beats pure html coding ( component-based coding). When should we split the components, I think Decade Moon's answer makes a good and clear point. However, I want to write more about the type of components:
1/ View components ( or dumb components): only for purpose of display, no logic of data flow
2/ Control components ( or smart components): display many dumb component and contain data flow logic
3/ Containers (or views): contain many control components, usually put the logic of server interaction here ( api call ,.... )
When we divide like this, it would be easier for maintenance because we control how the data flow better.
So back to your example: the Product list is like a control component, and the list item is likely a view component. Therefore, i actually support the idea of separating them.
Splitting components will make the directory structure become longer, however with good naming and filtering, I think it still better than having single file components with too many code lines.
Typically it is best to create a new component in the following situations:
if the component will be used more than once across your app, especially if it isn't coupled to the parent component.
if the component has a lot of logic, or a big template, etc, then it is best to separate it so it doesn't bloat the parent component. Try to keep your components small and easy to reason about.
if the component has logic that can be tested in isolation from the parent component.
if the component has some internal state that would be easier to implement as a separate component with its own internal data that the parent shouldn't have to manage.
As for your list component, it seems like each list item is specific to the product list and won't be used elsewhere and probably isn't very complicated, so it's fine to keep it within the list component. Separating components out unnecessarily just increases complexity and memory usage (especially for lists with lots of items) with no benefit.