VueJS How can I use computed property with v-for
You can't create a computed property for each iteration. Ideally, each of those items
would be their own component so each one can have its own fullName
computed property.
What you can do, if you don't want to create a user
component, is use a method instead. You can move fullName
right from the computed
property to methods
, then you can use it like:
{{ fullName(user) }}
Also, side note, if you find yourself needing to pass an arguments to a computed
you likely want a method instead.
What you're missing here is that your items
is an array, which holds all the items, but the computed
is a single fullName
, which just can't express all the fullName
s in items
. Try this:
var vm = new Vue({ el: '#el', data: { items: items }, computed: { // corrections start fullNames: function() { return this.items.map(function(item) { return item.firstname + ' ' + item.lastname; }); } // corrections end }});
Then in the view:
<div id="el"> <p v-for="(item, index) in items"> <span>{{fullNames[index]}}</span> </p></div>
The way Bill introduces surely works, but we can do it with computed props and I think it's a better design than method
in iterations, especially when the app gets larger. Also, computed
has a performance gain compared to method
on some circumstances: http://vuejs.org/guide/computed.html#Computed-Caching-vs-Methods
I like the solution posted by PanJunjie潘俊杰. It gets at the heart of the issue by only iterating over this.items
once (during the component creation phase), and then caching the result. This is of course the key benefit for utilizing a computed prop instead of a method.
computed: { // corrections start fullNames: function() { return this.items.map(function(item) { return item.firstname + ' ' + item.lastname; }); } // corrections end}
.
<p v-for="(item, index) in items"> <span>{{fullNames[index]}}</span></p>
The only thing I don't like is that, in the DOM markup, fullNames
is accessed by the list index. We could improve that by using .reduce()
instead of .map()
in the computed prop to create an Object with a key for each item.id
in this.items
.
Consider this example:
computed: { fullNames() { return this.items.reduce((acc, item) => { acc[item.id] = `${item.firstname} ${item.lastname}`; return acc; }, {}); },},
.
<p v-for="item in items" :key="`person-${item.id}`"> <span>{{ fullNames[item.id] }}</span></p>
Note: the above example assumes that item.id
is unique, such as from typical database output.