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

erhoui1w  于 2022-11-25  发布在  Vue.js
关注(0)|答案(7)|浏览(395)

以下是我目前的模板:

<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>

问题是我必须多次编写rowLenMap[orderList[n - 1]],而且我担心vue.js引擎也会多次计算它。
我想要的是这样的东西:

<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>

我觉得在技术上实现起来并不难,因为可以笨拙地用v-for="rowLen in [rowLenMap[orderList[n - 1]]]"之类的东西来解决,那么有没有简洁的官方解决方案呢?

cwtwac6a

cwtwac6a1#

我发现了一个非常简单(几乎是神奇的)的方法来实现这一点,它所做的就是定义一个内联(局部)变量,该变量的值要使用多次:

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

注意:set不是Vuejs中的特殊属性,它只是用作变量定义的占位符。
Sourcehttps://dev.to/pbastowski/comment/7fc9
CodePenhttps://codepen.io/mmghv/pen/dBqGjM

更新:基于@vir us的评论

这对事件不起作用,例如@click="showUser(user)"不会传递正确的用户,而是它将始终是最后评估的用户,这是因为user临时变量将在循环的每个循环中被重用和替换。
因此,此解决方案仅适用于模板呈现,因为如果组件需要重新呈现,它将再次重新计算变量。

但是如果您确实需要将其用于事件(尽管不建议),则需要定义一个外部数组来同时保存多个变量:

<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
制作人员:@vir us
虽然这里基本上复制users数组没有意义,但在需要调用开销很大的函数来获取数据的其他情况下,这可能很方便,但我认为最好使用computed属性来构建数组。

yacmzcpb

yacmzcpb2#

根据您的模板判断,您可能最好使用计算属性,正如公认答案中所建议的那样。
然而,由于问题标题有点宽泛(而且在Google上出现的“Vue模板中的变量”相当高),我将尝试提供一个更通用的答案。
特别是如果你不需要转换数组的每一项,计算属性可能是一种浪费。子组件也可能是多余的,特别是如果它真的很小(这将使它20%的模板,20%的逻辑和60%的属性定义样板)。
我喜欢使用的一个非常简单的方法是一个小的helper组件(我们称之为<Pass>):

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

现在我们可以这样编写您的组件:

<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>的工作原理是创建一个作用域插槽。请阅读Vue.js文档中关于作用域插槽的更多信息,或者阅读我在dev.to article中编写的关于该主题的方法。

附录:第三代

Vue 3对slot的处理方式略有不同,首先,<Pass>组件源代码需要做如下调整:

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

xmq68pz93#

今天我需要这个,并使用了<template>标签和v-for,如下所示
我把这段代码

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

改成了这个

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

它成功了,我很惊喜,因为我不知道这是可能的

ui7jx7zq

ui7jx7zq4#

这似乎是子组件的完美用例。您可以简单地将复杂的计算值作为属性传递给组件。
https://v2.vuejs.org/v2/guide/components.html#Passing-Data-to-Child-Components-with-Props

ie3xauqp

ie3xauqp5#

<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>
laawzig2

laawzig26#

刚刚测试使用vue3和工程,我认为它的工作普遍

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

设置变量时不输出任何内容。
必备:
打开“(“
设置变量
关闭“,null)”

6mw9ycah

6mw9ycah7#

curSize是一个数组。您的临时值包含一个相应的隐含数组sizedOrderList = curSize.map(n => orderList[n-1])。如果您将其定义为一个计算数组,则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>

相关问题