Adding constant declaration in `template`
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]"
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.
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
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
Maybe https://github.com/vuejs/core/pull/7218 can help.
@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>
@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
@tachibana-shin You are right, let's hope the core team can merge this soon :) https://github.com/vuejs/core/pull/7218
Let's track this issue in the RFC discussion instead https://github.com/vuejs/rfcs/discussions/505