Skip to content
Advertisement

reuse same value of a function on a vue template

I have a situation that repeats a lot when im trying to get a value on the template from a function, this function recieves parameters from the template (for example the index of a v-for) and returns a result that is printed on the template, the problem is that I need to do this operations twice, and since the value has been already calculated I don’t see the point of calling twice the same function to get the value on the template, but it is not very obveous how and where to store this value for reuse, I know that a computed would cache the value, but computeds don’t take params as far as I know, that’s why I need a function.

Example:

<template v-for="attr in el.attrs">
    <div v-for="(step, i) in steps" :title="getVal(i, attr.key))">
       {{ getVal(i, attr.key) ? '◇' : '-' }}
    </div>
 </template>

I tried by storing the value of getVal in a ref, but then it gives a warning “recursive updates exceeded in component” and it runs pretty slow.

Any workarounds/solutions/ideas? Thanks!

Advertisement

Answer

There are 2 ways to solve this problem:

Make a computed, which extends items of the original array with some additional calculated properties. Computed properties are cached, and recompute only when its dependencies are updated. This approach will also make your template a lot cleaner

const extendedSteps = computed(() => {
  return steps.map((step, stepIndex) => {
    const title = getTitle(stepIndex)
    return {
      ...step,
      title,
      symbol: title ? '◇' : '-'
    }
  })
})

<div v-for="step in extendedSteps" :title="step.title">
   {{ step.symbol }}
</div>

Another option is to make a component representing a single item in your list. There you can create a regular computed property, which will calculate and cache whatever you need for each item separately

// parent template
<Step v-for="step in steps" :step="step" />

// Step.vue script
const props = defineProps(['step'])

const title = computed(() => getTitle(props.step))
const symbol = computed(() => title ? '◇' : '-')

// Step.vue template
<div>
  {{ title }} {{ symbol }}
</div> 
User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement