Replies: 25 comments 5 replies
-
It was proposed in the past: vuejs/vue#7325 |
Beta Was this translation helpful? Give feedback.
-
Probably you already know, but if you use JSX you could do this: export default {
render() {
const b = this.item && this.item.a && this.item.a.b;
return (
<div class="container">
<p class="row">{b && b.hello}</p>
<p class="row">{b && b.world}</p>
<p class="row">{b && b.goodbye}</p>
</div>
)
}
} |
Beta Was this translation helpful? Give feedback.
-
You can also create a method that accepts a parameter, so you can use it in |
Beta Was this translation helpful? Give feedback.
-
The issue with methods is that they aren't cached, so a bit less performatic. |
Beta Was this translation helpful? Give feedback.
-
I see, and a local variable could serve as an in-loop cache for method results where computed props can't be used. |
Beta Was this translation helpful? Give feedback.
-
Whenever I hear someone say that, I think "this is a perfect situation for creating a component for that item!". That would give you the ability to use simple computed getters that can be cached. A component should always have exactly one reason to exist and one mission to execute. This parent components mission is not knowing how to render the child items. |
Beta Was this translation helpful? Give feedback.
-
Well, component instantiations come at a price (memory-footprint & render performance), so sometimes it's better to render i list's items in the parent for that reason. There shuold be ways to keep these situations performant, an this RFC aims to address it. |
Beta Was this translation helpful? Give feedback.
-
Forgive my ignorance, I'm new to the vue community. Could the above be done with optional chaining as well? e.g. <template>
<div class="container">
<p class="row">{{ item?.a?.b?.hello }}</p>
<p class="row">{{ item?.a?.b?.world }}</p>
<p class="row">{{ item?.a?.b?.goodbye }}</p>
</div>
</template> it's stage 3 and has a babel plugin |
Beta Was this translation helpful? Give feedback.
-
Not right now, as vue-es2015-template compiler doesn't aupport >es6 features But that can be solved. |
Beta Was this translation helpful? Give feedback.
-
I was dealing with a similar concern recently in my work so wanted to add 2 cents... (My day job is in Ember so I'll pseudo-code the concepts) Generally I want to pass a data model to my components.. like pass a user to a component for showing the user's badge or pass a meeting to a component for showing when and where and who's attending that meeting... it's just simpler to do I've also recently come to appreciate that this allows me to flatten out deeply nested data and to add logic around data that's not directly suited to my use case. So I recently did something like this: // Component receives `model`
name = model.model_name
date = computed(() => (model.date && date_from_format(model.date, 'YYYY-MM-DD')) || undefined)
instructions = computed(() => (model.location && model.location.meeting_instructions) || undefined) The same can be done for lists... if I need to display a list of users = computed(() => {
return model.users.map((user) => {
const spouse = model.spouse || {};
return {
name: user.name,
spouseName: spouse.name
};
});
}); Now the template can iterate |
Beta Was this translation helpful? Give feedback.
-
Will this make the code much less clear? In my opinion, if you have a large component, it will be difficult to understand what the variable is, where it comes from if it is not in the Much simpler code that doesn't have any "magic" variables: <template>
<div class="container" v-if="item && item.a && item.a.b">
<p class="row">{{item.a.b.hello}}</p>
<p class="row">{{item.a.b.world}}</p>
<p class="row">{{item.a.b.goodbye}}</p>
</div>
</template> |
Beta Was this translation helpful? Give feedback.
-
Computed can also solve v-for performance problem, as items could be mapped to have additional keys for display purposes + you can use object destructuring. Btw. most of times proper Item structurizing can solve this issue. |
Beta Was this translation helpful? Give feedback.
-
I think I found some kind of way to accomplish in-template variables in vue 3. Here is an example where I create the "in-template variable" inside of a v-for. Basically declare an inline array and iterate over the single item. <div v-for='item in items'>
<div v-for="record of [cache.find(item.otherId).value]">
<span v-if="record">{{ record.name }}</span>
</div>
</div> In this case I feel like it's its kinda hacky, and I'm not really sure the performance impact. |
Beta Was this translation helpful? Give feedback.
-
Which is why there are computed functions that do cache results. :-) |
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
It's great how this approach can be used to cache cross-referenced (calculated) item when I have two v-for for matching correct item from big list. This way I don't need to re-evaluate fetching of correct item for each action separately, but can simply fetch item only once and refer to it. It looks like this works correctly, even with events. I would hope to see this implement in more readable manner and without using v-for in hackish-way. Please consider implementing this as built-in-feature. |
Beta Was this translation helpful? Give feedback.
-
There is also a way to set multiple variables in
|
Beta Was this translation helpful? Give feedback.
-
Svelte implements this feature and has good Typescript support. |
Beta Was this translation helpful? Give feedback.
-
I can't find any documentation on |
Beta Was this translation helpful? Give feedback.
-
It was just a suggestion for the syntax, I believe. |
Beta Was this translation helpful? Give feedback.
-
I've a solution that is using a component to solve this issue.
https://www.npmjs.com/package/vue-temp-var Example <script setup lang="ts">
import TempVar from 'vue-temp-var'
function getRandomNumber() {
return Math.random()
}
</script>
<template>
<div v-for="i in 10" :key="`random-${i}`">
<!-- cause the return value would be random, we should store it somewhere -->
<!-- bind a prop 'define' to 'TempVar'. Because it is a prop, it would still be reactive -->
<!-- destruct from slot: defined, the type would be kept -->
<TempVar
:define="{ randomNum: getRandomNumber() }"
#defined="{ randomNum }"
>
<span>"{{ randomNum }}"</span>
<span v-if="randomNum > 0.5"> is larger than 0.5</span>
<span v-else> is smaller than 0.5</span>
</TempVar>
</div>
</template> |
Beta Was this translation helpful? Give feedback.
-
LocalScope.vue <template>
<slot v-bind="$attrs" />
</template> <template>
<LocalScope v-slot="{ classes }" classes="py-3 font-semibold">
<p :class="classes">some text</p>
<p :class="classes">some text</p>
</LocalScope>
</template> |
Beta Was this translation helpful? Give feedback.
-
I guess the most simple solution looks like this <!-- local-scope.vue -->
<script setup lang="ts" generic="T extends Record<string, unknown>">
defineProps<{ set: T }>();
</script>
<template>
<slot v-bind="set" />
</template> And you can use it like this <!-- my-component.vue -->
<script setup lang="ts">
import LocalScope from './local-scope.vue';
</script>
<template>
<local-scope
:set="{ someVar: someValue }"
v-slot="{ someVar }"
>
{{ someVar }}
</local-scope>
</template> The thing is - it's overhead having a component lifecycle just to define a variable while in JSX you could easilly define a variable inside a function. Maybe we could have something like Or, to make it look more like standard JS, we could have
transpiled to
And, with Typescript,
would just work. |
Beta Was this translation helpful? Give feedback.
-
I use a functional component and force (sort of roughly) a type onto it. That way, consumers can choose a fitting name without having to rename the variable. It even allows multiple assignments. What do you think? See the demo. (Note: In the playground typing for <script setup>
import TempVar from './temp-var';
</script>
<template>
<TempVar :foo="Math.random()" v-slot="{ foo }">
<div>{{ foo }}</div>
</TempVar>
</template> // temp-var.ts
const TempVar = defineComponent(
(props, ctx) => () => ctx.slots.default?.(ctx.attrs),
{ inheritAttrs: false },
) as unknown as new <T>(props: T) => {
$props: T;
$slots: { default?: (context: T) => unknown };
};
export default TempVar; |
Beta Was this translation helpful? Give feedback.
-
I created this library for myself https://www.npmjs.com/package/@allindevelopers/vue-local-scope The code is pretty simple https://github.com/allindevelopers/vue-local-scope/blob/main/lib/local-scope.component.vue LocalScope.vue <script setup lang="ts" generic="T">
defineOptions({ inheritAttrs: false });
defineProps</* @vue-ignore */ T>();
defineSlots<{ default?(props: T): any }>();
</script>
<template>
<slot v-bind="$attrs as T" />
</template> |
Beta Was this translation helpful? Give feedback.
-
Sometimes you will encounter such a situation:
These code with the same logic need to be written many times.
I hope there is a way to define local variables in the template, then the above code can be abbreviated as:
or
Q: Why not computed?
A: The
item
in the above code may come fromv-for
, socomputed
is not a feasible solution.Beta Was this translation helpful? Give feedback.
All reactions