VueJS 如何在 v-for 中使用计算属性

IT技术 javascript vue.js computed-properties
2021-02-22 19:00:00

如何在列表中使用计算属性。我正在使用 VueJS v2.0.2。

这是 HTML:

<div id="el">
    <p v-for="item in items">
        <span>{{fullName}}</span>
    </p>
</div>

这是Vue代码:

var items = [
    { id:1, firstname:'John', lastname: 'Doe' },
    { id:2, firstname:'Martin', lastname: 'Bust' }
];

var vm = new Vue({
    el: '#el',
    data: { items: items },
    computed: {
        fullName: function(item) {
            return item.firstname + ' ' + item.lastname;
        },
    },
});
5个回答

您不能为每次迭代创建计算属性。理想情况下,每个组件items都是自己组件,因此每个组件都可以拥有自己的fullName计算属性。

如果您不想创建user组件,您可以做的是改用方法。您可以fullNamecomputed属性向右移动methods,然后您可以像这样使用它:

{{ fullName(user) }}

另外,请注意,如果您发现自己需要将参数传递给 acomputed您可能需要一个方法。

老实说,我会在州更高的地方做这件事。如果您正在处理项目的排序版本,则下面的计算方法会中断。我绝对是为了安全而去的。对我来说,让数据尽可能地重用更有意义。
2021-04-22 19:00:00
我的问题是,该数组可以根据其他被选中和取消选中的项目进行更改,这会触发数组本身的反应性,因此我无法在更高级别上真正做到这一点,我不认为,除了可能创建过滤器并在那时向数组中的对象添加额外的属性(这不是一个糟糕的主意,但只会导致通过数组循环执行所有这些操作 - 我猜两次比 10 次要好)。
2021-05-17 19:00:00
如果您需要多次使用 fullName 并且 fullName 方法是一个复杂的函数,每次迭代执行 10 次真的很费钱怎么办?我认为@PanJunie 的解决方案在那种情况下会好得多。
2021-05-18 19:00:00

您在这里缺少的是,您items是一个数组,其中包含所有项目,但computed是单个fullName,它无法表达 .s 中的所有fullNames items试试这个:

var vm = new Vue({
    el: '#el',
    data: { items: items },
    computed: {
        // corrections start
        fullNames: function() {
            return this.items.map(function(item) {
                return item.firstname + ' ' + item.lastname;
            });
        }
        // corrections end
    }
});

然后在视图中:

<div id="el">
    <p v-for="(item, index) in items">
        <span>{{fullNames[index]}}</span>
    </p>
</div>

Bill 引入的方式肯定有效,但我们可以使用计算props做到这一点,我认为这是比method迭代更好的设计,尤其是当应用程序变大时。此外,computedmethod某些情况相比,性能有所提升http : //vuejs.org/guide/computed.html#Computed-Caching-vs-Methods

为什么在items排序时会失败@比尔克里斯威尔
2021-04-21 19:00:00
这不太便携。如果您想通过排序的副本items并获得 fullName,这将失败。真正应该做的是一个“用户”组件,它接受一个具有 fullName 计算属性的用户对象。
2021-05-01 19:00:00
如果你做v-for="item in sortedVersionOfItems"index是关闭。
2021-05-08 19:00:00
我使用它来突出显示:class指令中的一行比方法更好。
2021-05-16 19:00:00

喜欢潘俊杰潘俊杰的解决方案。通过只迭代this.items一次(在组件创建阶段),然后缓存结果,它成为了问题的核心这当然是使用计算props而不是方法的主要好处。

computed: {
    // corrections start
    fullNames: function() {
        return this.items.map(function(item) {
            return item.firstname + ' ' + item.lastname;
        });
    }
    // corrections end
}

.

<p v-for="(item, index) in items">
    <span>{{fullNames[index]}}</span>
</p>

我唯一不喜欢的是,在 DOM 标记中,fullNames是通过列表索引访问的。我们可以通过在计算 prop 中使用.reduce()而不是.map()创建一个对象来改进它,每个item.idin都有一个键this.items

考虑这个例子:

computed: {
    fullNames() {
        return this.items.reduce((acc, item) => {
            acc[item.id] = `${item.firstname} ${item.lastname}`;
            return acc;
        }, {});
    },
},

.

<p v-for="item in items" :key="`person-${item.id}`">
    <span>{{ fullNames[item.id] }}</span>
</p>

注意:上面的示例假设它item.id是唯一的,例如来自典型的数据库输出。

也许添加另一个 v-for 迭代一个单项长的列表:

<div id="el">
    <p v-for="item in items">
        <template v-for="fullName in [item.firstName + ' ' + item.lastName]">
            <span>{{fullName}}</span>
        </template>
    </p>
</div>

不好,但这就是您要查找的内容:该跨度周围的对象具有名为 fullName 的属性,该属性包含该特定值。

而且它不仅仅是一个虚荣功能,因为我们可能需要在多个地方使用该值,例如:

<span v-if="...">I am {{fullName}}</span>
<span v-else-if="...">You are {{fullName}}</span>
<span v-else>Who is {{fullName}}?</span>

我的用例是我在 v-for 循环中构建日期(是的,另一个日历),例如:

<v-row v-for="r in 5">
    <v-col v-for="c in 7">
        <template v-for="day in [new Date(start.getTime() + 24*60*60*1000*((c-1) + 7*(r-1)))]">
            <span>
                Some rendering of a day like {{day.getYear()}} and
                {{day.getMonth()}} etc.
            </span>
        </template>
    </v-col>
</v-row>

(为简洁起见,我省略了:key="whatever"设置)

我承认最好的方法是将它移动到一个单独的组件,但是如果我们像这样为每个双行创建一个新组件,并且只在这个地方使用该组件,那么我们只会污染另一个命名空间。

也许v-let="day as new Date(...)"指令会很方便用于这种目的。

你必须在函数调用中传递参数

 <div id="el">
       <p v-for="item in items">
           <span>{{fullName(item)}}</span>
       </p>
 </div>
纯代码答案质量不高虽然此代码可能有用,但您可以通过说明其工作原理、工作方式、何时使用以及其局限性来改进它。编辑您的答案以包含相关文档的解释和链接。
2021-05-03 19:00:00