Reputation: 29987
Consider the following fragment in a <template>
:
<div v-for="entry in entries">
<my-component :color="doSomething(entry)">hello</my-component>
</div>
The related method:
doSomething(entry) {
return entry.color
}
Is there a way to replace the setup above with a computed property without the need to pass (entry)
each time? Something like:
<div v-for="entry in entries">
<my-component :color="doSomething">hello</my-component>
</div>
The related method:
doSomething() {
// I need to know here that the call is coming from <my-component>
// in the context of "entry"
return ???.color
}
The reason for the question is that I would like to reduce the boilerplate for components that rely on the state of an iterated property:
<q-editor
v-for="note in notesByDay[when]"
@click="noteClicked(note)"
@blur="noteBlurred(note)"
:toolbar="SetToolbar(note)"
(...)
Upvotes: 2
Views: 444
Reputation: 28414
I don't think computed-properties
are designed to be used as custom functions that you can call with different inputs.
However, to make your code cleaner, I would suggest making a computed-property
for your entries
list and fill in all the properties you want to add to each item.
Here is a simple demo:
const mycomponent = Vue.component('mycomponent', {
template: '#mycomponent',
props: ['color']
});
new Vue({
el: "#app",
components: { mycomponent },
data: () => ({ entries: [ { id:1 }, { id:2 } ] }),
computed: {
customEntries() {
return this.entries.map(e => ({
...e,
color: e.id === 1 ? 'red' : 'blue', // or call a function to compute this
score: 10 // ...
}));
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<template id="mycomponent">
<p :style="{ color: color }">
<slot></slot>
</p>
</template>
<div id="app">
<div v-for="({color}, index) in customEntries" :key="index">
<mycomponent :color="color">hello</my-component>
</div>
</div>
Upvotes: 2
Reputation: 138286
Computed props can't receive arguments unless they were computed methods themselves, but that's no better than using a component method as in the original question.
You could instead compute the array with the color
field added, using Array.prototype.map
on entries[]
, where you'll have access to the entry
field:
export default {
computed: {
computedEntries() {
return this.entries.map(entry => ({
...entry,
color: this.getColor(entry),
}))
}
},
methods: {
getColor(entry) {
return /* determine color based on state, etc. */
}
},
}
Then in the template, loop over the computed prop instead of entries
:
<template>
<div v-for="entry in computedEntries">
<my-component :color="entry.color">hello</my-component>
</div>
</template>
Upvotes: 3