Is the :key attribute mandatory in v-for loops? - vue.js

i don't have a real problem, just i read somewhere once that a :key attribute in vue 3 is not mandatory in a v-for loop.
Is this correct and if so, when do I need a key in v-for loops and when not?
Or do I not need it at all ?
What is it needed for if it is necessary?
Thanks a lot.

It's better for you to use it in all v-for loops.
The key special attribute is used as a hint for Vue's virtual DOM
algorithm to keep track of a node's identity. That way, Vue knows when
it can reuse and patch existing nodes and when it needs to reorder or
recreate them.

Related

Is is proper to use "this" when referencing variables in vuejs v-if expressions?

Many of the examples for v-if use unqualified variable names such as:
<h1 v-if="awesome">Vue is awesome!</h1>
but I am wondering of the following code is equivalent?
<h1 v-if="this.awesome">Vue is awesome!</h1>
It seems to work correctly but I'm seeking some guidance on pros/cons of doing this.
The reason I ask is because when specifying v-if, "this" is not recommended, but when developing computed properties, "this" is required to reference model variables.
This makes things inconsistent for developers.
From the vue.js source code, they are using the javascript "with" statement to evaluate v-if tags to eliminate the need for the "this" qualifier. However, use of "with" is generally discouraged here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/with
I personally don't want to use "this" on v-if but it'd be even nicer to not have to use it in computed properties as well.
Variables in Vue template Keys are actually keys that are evaluated against component instance. These two snippets are equivalent, so this can be omitted.
this is needed in Vue templates in case of dynamic keys, e.g. for this[this.awesome]:
<h1 v-if="this[awesome]">Vue is awesome!</h1>
This is rarely needed in practice because a cleaner way is to move awesome access into computed property or a method.

Is it bad to use a watch in a child component?

In my project, I need to know the changes in the child components in real time from the parent component.
So I'm going to use watch in a child component to emit event to the parent component whenever the data in the child component changes.
Is this a bad way? I'm afraid there's an unnecessary overload in this flow.
If you have a better way, please recommend it.
There's nothing wrong with this approach. Vue is very efficient in the way it detects changes, and there shouldn't be an unnecessary overload, unless you watch more than you need to. You shouldn't notice any performance issues unless you have a huge object graph (eg thousands of objects being watched).
Make sure you only watch the properties that require change detection, and only use deep:true if you really need to.

Is it standard to copy collections out of vuex state to prevent mutation?

I’ve scoured the vue forum and there’s a lot of answers that are 2 years old and close, but I’m having a hard time getting one specifically addressing this (I’m simplifying the example):
I have an array of objects in state (row data for a table)
And a tableComponent with subComponents which for-loops through the data and creates one row per item in the collection
The requirement is to add an input to each row in the table which is bound to rowData.foo
The tableComponent has a computed property that gets rowData from state, puts those objects into a new (modified) array, and passes it into the tableComponent template
Which then adds the input with a v-model of rowData.foo
This works, but I recently realized that it is modifying the foo property of a rowData item in the collection without committing a mutation.
I’m ok with dropping v-model and using #input to commit the change, but I have two questions about how this should work
If I want to block these changes until I hit a “confirm changes” button, is it standard / performant to
_.cloneDeep the whole collection in either the tableComponent computed property or in the vuex getter. It seems like a lot of overhead but maybe I’m being too conservative about that?
Allowing v-model to update RowData.foo directly means each row knows which RowData item to modify, now that I’m committing a change to a single object in a vuex collection, is the best practice to make the vuex mutation _.find the object, change it, and then spread the whole collection back into the store?
As with most of my other vue questions, I have multiple ways that make it work, but I’m not sure what the most performant/best pattern is. Thanks for any help!
Update
Simple codeSandbox here: https://codesandbox.io/embed/vuex-store-olrvk
See how the vuex data is updated without an action call?
After reviewing your codeSandbox sample i found that YES your store state data rowCollection is getting mutated without using any mutation and that's because of the v-model (two-way binding) that detects the data spot in memory and mutates it behind the scenes ... of course this was allowed by Vue devs even tough i couldn't find about this at any document (and by the way on the doc they showed an example of a state mutation using v-model but they used a store mutation for that )
and concerning what is the most performant/best pattern i think this way is the easiest and much cleaner (less code)
If you need to buffer user changes to a reactive model (for a commit operation), you will need to make a deep copy. There is no way around it. Totally normal.

Vue - use vuex instead of eventbus for calculations with nested data & components

I have app when bind big JSON object into component, then some parts from this object into next components etc. - it's structure with many deep levels, but object is not copied, I use advantage that objects are passing by reference.
Components on the lowest level have fields like "price", "qty" etc. When user modifies them, I updated object and run recalculation using global eventbus - after recalculation is done, I also use eventbus to forceUpdate some components. For example parents of these with fields price/qt, to refresh "total" amounts in categories.
Now I move some code to vuex and consider also here. Think that recalculation after commit will be ok. The question is - how can I modify this big object using commit from children components? The problem is that commit must "know" what part of object has been modified (for example, one element inside one of many categories)... I can do it in other way, pass child and parent data in commit and update parent but... will it work? I also need reference to do this in proper way...
Maybe still use binding to pass elements, but call store action to only make recalculation (not sure, that provides automatic refreshes on all required modules).
Or maybe other, better solution?
I think you have some problems with architecture. Main idea here is to have some container (smart) component, that is connedcted with store (vuex), and simple (stupid) components, that recieve data from props. Also you must divide your store into modules, so it'll be easy to maintain. This approach will allows you to modify exactly pieces of data you want.

Vue watchers and components

Vue newbie here - we are introducing Vue into an existing application bit by bit and therefore I am slightly constricted by this with regards to the back end. The Vue template gets an array of objects from the Django backend. Some of the objects returned are parents and others are children of the parents - identified by the parent_id.
These are rendered happily using various components to encapsulate some of the functionality.
The update end point for the back end is configured to take one single object and update the database accordingly, therefore the watcher must be able to identify which of the array of objects has been updated. From my understanding this isn’t possible for objects/arrays in Vue/Js as the before/after values aren’t available for anything other than simple types.
The workaround I have put in place is to clone the array of objects in a computed property, and then compare the new array to the computed array to identify which object has been modified in order to send that back to the back end.
Is this best practice, or am I going to fall foul to this decision later on down the line?
many thanks for your help
It would be better if you give the objects of the array their own components, so you have a vue component that takes as a prop the object and you then use a v-for on the array to create one instance of the "object component" for each object in the array.
Then you can have a watcher on the object prop in the object component and you will know exactly which object has changed and get better control.