Subscribe on changes!

Adding constant declaration in `template`

avatar
Sep 18th 2022

What problem does this feature solve?

I'm developing an app that has v-for to repeat items. in v-for I need the return result of a function in two different positions. I can solve this problem by creating a new array, but it's very inconvenient and memory-consuming.

What does the proposed API look like?

The API that I imagined would look like this:

<template>
  <div v-for="name in users" :key="name" v-const:nameObj="name.split(' ')">
    First name: {{ nameObj[0] }} <br>
    Last name: {{ nameObj[1] }}
  </div>
</template>

It's like a directive system v-const:[name]="[value]"

avatar
Sep 19th 2022
const nameObjList = computed(()=>{
    return users.map((name)=>name.split(" "))
})

It seems you could use computed function instead of it,if use v-const... it may also take up more memory.

avatar
Sep 19th 2022
const nameObjList = computed(()=>{
    return users.map((name)=>name.split(" "))
})

It seems you could use function instead of it,if use it may also take up more memory.computed``v-const...

This is memory-intensive and I need v-tools for more complex functions. I don't always need to calculate a value in a iteration of v-for. I can use get value for that, but for the same reason it takes memory and complexity. it's silly that we have to run the if commands twice 1 for calculation 1 for display to solve the problem

avatar
Sep 19th 2022

I can solve this problem with a blank variable like this:

<template>
  <div v-for="name in users" :key="name" v-empty-direactive="tmp = name.split(' ')">
    First name: {{ tmp[0] }} <br>
    Last name: {{ tmp[1] }}
  </div>
</template>

then vue/compiler would understand tmp as a tmp and would translate into _ctx.tmp but it was silly it was an error and it could not declare itself transparent and immutable

avatar
Mar 16th 2023
avatar
Mar 25th 2023

@tachibana-shin

I found that I can define a component to do the following (not as ideal as a proper v-scope).

components/Scope.vue:

<script setup lang="ts">
import { reactive } from 'vue'

defineProps<{ scope: any }>()
</script>

<template>
  <slot :scope="reactive(scope)" />
</template>

Your example:

<div v-for="name in users" :key="name" >
  <Scope :scope="{ parts: name.split(' ') }" v-slot="{ scope }">
    First name: {{ scope.parts[0] }} <br>
    Last name: {{ scope.parts[1] }}
  </Scope>
</div>

Another example:

<Scope :scope="{ count: 1 }" v-slot="{ scope }">
  <div>{{ scope.count }}</div>
  <button @click="scope.count++">add1</button>
</Scope>
avatar
Mar 26th 2023

@tachibana-shin

I found that I can define a component to do the following (not as ideal as a proper v-scope).

components/Scope.vue:

<script setup lang="ts">
import { reactive } from 'vue'

defineProps<{ scope: any }>()
</script>

<template>
  <slot :scope="reactive(scope)" />
</template>

Your example:

<div v-for="name in users" :key="name" >
  <Scope :scope="{ parts: name.split(' ') }" v-slot="{ scope }">
    First name: {{ scope.parts[0] }} <br>
    Last name: {{ scope.parts[1] }}
  </Scope>
</div>

Another example:

<Scope :scope="{ count: 1 }" v-slot="{ scope }">
  <div>{{ scope.count }}</div>
  <button @click="scope.count++">add1</button>
</Scope>

it's a workaround however i don't like the slot as every time the depscha change it has to go through 2 reactions to be shown it's a performance issue

avatar
Mar 27th 2023

@tachibana-shin You are right, let's hope the core team can merge this soon :) https://github.com/vuejs/core/pull/7218

avatar
Sep 20th 2023

Let's track this issue in the RFC discussion instead https://github.com/vuejs/rfcs/discussions/505