简体   繁体   English

如何在Vue.js模板中定义一个临时变量

[英]How to define a temporary variable in Vue.js template

Here is my current template:这是我当前的模板:

<a-droppable v-for="n in curSize" :key="n - 1" :style="{width: `${99.99 / rowLenMap[orderList[n - 1]]}%`, order: orderList[n - 1]}">
  <a-draggable :class="{thin: rowLenMap[orderList[n - 1]] > 10}">
    <some-inner-element>{{rowLenMap[orderList[n - 1]]}}</some-inner-element>
  </a-draggable>
</a-droppable>

The problem is that i have to write rowLenMap[orderList[n - 1]] multiple times, and i'm afraid vue.js engine will also calculate it multiple times.问题是我要多次写rowLenMap[orderList[n - 1]] ,我怕vue.js引擎也会计算多次。

What i want is something like this:我想要的是这样的:

<a-droppable v-for="n in curSize" :key="n - 1" v-define="rowLenMap[orderList[n - 1]] as rowLen" :style="{width: `${99.99 / rowLen}%`, order: orderList[n - 1]}">
  <a-draggable :class="{thin: rowLen > 10}">
    <some-inner-element>{{rowLen}}</some-inner-element>
  </a-draggable>
</a-droppable>

I think it's not difficult to implement technically because it can be clumsily solved by using something like v-for="rowLen in [rowLenMap[orderList[n - 1]]]" .我认为在技术上实现起来并不困难,因为它可以通过使用v-for="rowLen in [rowLenMap[orderList[n - 1]]]"类的东西笨拙地解决。 So is there any concise and official solution?那么有没有简洁官方的解决方案呢?

I found a very simple (almost magical) way to achieve that, All it does is define an inline (local) variable with the value you want to use multiple times:我找到了一种非常简单(几乎是神奇)的方法来实现这一点,它所做的只是定义一个内联(局部)变量,其中包含您要多次使用的值:

<li v-for="id in users" :key="id" :set="user = getUser(id)">
  <img :src="user.avatar" />
  {{ user.name }}
  {{ user.homepage }}
</li>

Note : set is not a special prop in Vuejs , it's just used as a placeholder for our variable definition.注意: set不是Vuejs中的特殊道具,它只是用作我们变量定义的占位符。

Source : https://dev.to/pbastowski/comment/7fc9 Sourcehttps ://dev.to/pbastowski/comment/7fc9

CodePen : https://codepen.io/mmghv/pen/dBqGjM代码笔: https : CodePen


Update : Based on comments from @ vir us更新:基于@vir us的评论

This doesn't work with events, for example @click="showUser(user)" will not pass the correct user, rather it will always be the last evaluated user, that's because the user temp variable will get re-used and replaced on every circle of the loop.这不适用于事件,例如@click="showUser(user)"不会传递正确的用户,而是始终是最后评估的用户,这是因为user临时变量将被重新使用和替换循环的每一圈。

So this solution is only perfect for template rendering because if component needs re-render, it will re-evaluate the variable again.所以这个解决方案只适用于模板渲染,因为如果组件需要重新渲染,它将再次重新评估变量。

But if you really need to use it with events (although not advisable), you need to define an outer array to hold multiple variables at the same time :但是如果你真的需要将它与事件一起使用(虽然不推荐),你需要定义一个外部数组来同时保存多个变量:

<ul :set="tmpUsers = []">
  <li v-for="(id, i) in users" :key="id" :set="tmpUsers[i] = getUser(id)" @click="showUser(tmpUsers[i])">
    <img :src="tmpUsers[i].avatar" />
    {{ tmpUsers[i].name }}
    {{ tmpUsers[i].homepage }}
  </li>
</ul>

https://codepen.io/mmghv/pen/zYvbPKv https://codepen.io/mmghv/pen/zYvbPKv

credits : @vir us学分: @vir 我们

Although it doesn't make sense here to basically duplicate the users array, this could be handy in other situations where you need to call expensive functions to get the data, but I would argue you're better off using computed property to build the array then.虽然在这里基本上复制users数组没有意义,但这在您需要调用昂贵的函数来获取数据的其他情况下可能很方便,但我认为您最好使用computed属性来构建数组然后。

Judging by your template, you're probably best off with a computed property, as suggested in the accepted answer.从您的模板来看,您可能最好使用计算属性,正如接受的答案中所建议的那样。

However, since the question title is a bit broader (and comes up pretty high on Google for "variables in Vue templates"), I'll try to provide a more generic answer.但是,由于问题标题有点宽泛(并且在 Google 上出现的“Vue 模板中的变量”相当高),我将尝试提供更通用的答案。


Especially if you don't need every item of an array transformed, a computed property can be kind of a waste.特别是如果您不需要转换数组的每个项目,那么计算属性可能有点浪费。 A child component may also be overkill, in particular if it's really small (which would make it 20% template, 20% logic and 60% props definition boilerplate).子组件也可能是矫枉过正,特别是如果它真的很小(这将使它成为 20% 的模板、20% 的逻辑和 60% 的道具定义样板)。

A pretty straightforward approach I like to use is a small helper component (let's call it <Pass> ):我喜欢使用的一个非常简单的方法是一个小的帮助组件(我们称之为<Pass> ):

const Pass = {
  render() {
    return this.$scopedSlots.default(this.$attrs)
  }
}

Now we can write your component like this:现在我们可以像这样编写你的组件:

<Pass v-for="n in curSize" :key="n - 1" :rowLen="rowLenMap[orderList[n - 1]]" v-slot="{ rowLen }">
  <a-droppable :style="{width: `${99.99 / rowLen}%`, order: orderList[n - 1]}">
    <a-draggable :class="{thin: rowLen > 10}">
      <some-inner-element>{{rowLen}}</some-inner-element>
    </a-draggable>
  </a-droppable>
</Pass>

<Pass> works by creating a scoped slot. <Pass>通过创建一个作用域插槽来工作。 Read more about scoped slots on the Vue.js documentation or about the approach above in the dev.to article I wrote on the topic.Vue.js 文档中阅读更多关于作用域槽的信息,或者在我写的关于该主题的dev.to 文章中了解上述方法。


Appendix: Vue 3附录:Vue 3

Vue 3 has a slightly different approach to slots. Vue 3 对插槽的处理方式略有不同。 First, the <Pass> component source code needs to be adjusted like this:首先, <Pass>组件源码需要调整如下:

const Pass = {
  render() {
    return this.$slots.default(this.$attrs)
  }
}

Today I needed this and used <template> tag and v-for like this今天我需要这个并像这样使用<template>标签和v-for
I took this code and我拿了这段代码

<ul>
  <li v-for="key in keys" 
      v-if="complexComputation(key) && complexComputation(key).isAuthorized">
    {{complexComputation(key).name}}
  </li>
</ul>

Changed it to this改成这个

<ul>
  <template v-for="key in keys">
    <li v-for="complexObject in [complexComputation(key)]"
        v-if="complexObject && complexObject.isAuthorized">
      {{complexObject.name}}
    </li>
  </template>
</ul>

And it worked and I was pleasantly surprised because I didn't know this was possible它奏效了,我很惊喜,因为我不知道这是可能的

This seems like the perfect use case of a child component.这似乎是子组件的完美用例。 You can simply pass your complex computed value(s) as a property to the component.您可以简单地将复杂的计算值作为属性传递给组件。

https://v2.vuejs.org/v2/guide/components.html#Passing-Data-to-Child-Components-with-Props https://v2.vuejs.org/v2/guide/components.html#Passing-Data-to-Child-Components-with-Props

Just tested using vue3 and works, i think it works universally刚刚使用 vue3 进行了测试并且有效,我认为它普遍适用

{{ (somevariable = 'asdf', null) }}
<span v-if="somevariable=='asdf'">Yey</span>
<span v-else>Ney</span>

It outputs nothing while setting your variable.它在设置变量时不输出任何内容。

mandatory:强制的:

opening "("打开“(”

set your variable设置你的变量

closing ", null)"关闭“,空)”

<template>
  <div>
    <div v-for="item in itemsList" :key="item.id">
      {{ item.name }}

      <input v-model="item.description" type="text" />
      <button type="button" @click="exampleClick(item.id, item.description)">
        Click
      </button>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      items: [
        {
          id: 1,
          name: 'Name1',
        },
        {
          id: 2,
          name: 'Name2',
        },
      ],
    }
  },
  computed: {
    itemsList() {
      return this.items.map((item) => {
        return Object.assign(item, { description: '' })
      })
    },
  },
  methods: {
    exampleClick(id, description) {
      alert(JSON.stringify({ id, description }))
    },
  },
}
</script>

I found this simple method.我找到了这个简单的方法。
I ran this on vue2.我在 vue2 上运行了这个。

<li v-for="id in users" :key="id">
  <span style="display: none;">{{user = getUser(id)}}</span>
  <img :src="user.avatar" />
  {{ user.name }}
  {{ user.homepage }}
</li>

How about this:这个怎么样:

<div id="app">
  <div
    v-for="( id, index, user=getUser(id) ) in users"
    :key="id"
  >
    {{ user.name }}, {{ user.age }} years old
    <span @click="show(user)">| Click to Show {{user.name}} |</span>
  </div>
</div>

CodePen: https://codepen.io/Vladimir-Miloevi/pen/xxJZKKx代码笔: https://codepen.io/Vladimir-Miloevi/pen/xxJZKKx

curSize is an array. curSize是一个数组。 Your temporary values comprise a corresponding implied array sizedOrderList = curSize.map(n => orderList[n-1]) .您的临时值包含相应的隐含数组sizedOrderList = curSize.map(n => orderList[n-1]) If you define that as a computed, your HTML becomes如果您将其定义为计算,您的 HTML 将变为

<a-droppable v-for="n, index in sizedOrderList" :key="curSize[index]" :style="{width: `${99.99 / rowLenMap[n]}%`, order: n}">
  <a-draggable :class="{thin: rowLenMap[n] > 10}">
    <some-inner-element>{{rowLenMap[n]}}</some-inner-element>
  </a-draggable>
</a-droppable>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM