VueJS Как я могу использовать вычисляемое свойство с V-для

Как я могу использовать вычисляемое свойство в списках. Я использую 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 компонент, вместо этого используйте метод. Вы можете двигаться fullName прямо из computed собственность на methodsтогда вы можете использовать его как:

{{ fullName(user) }}

Также, обратите внимание, если вам нужно передать аргументы computed скорее всего, вам нужен метод.

Что вам здесь не хватает, так это того, что ваш items массив, который содержит все элементы, но computed это один fullNameкоторый просто не может выразить все fullNameв 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>

Конечно, способ, которым Билл представляет, работает, но мы можем сделать это с помощью компьютерных реквизитов, и я думаю, что это лучший дизайн, чем method в итерациях, особенно когда приложение становится больше. Также, computed имеет прирост производительности по сравнению с method на некоторые обстоятельства: http://vuejs.org/guide/computed.html

Мне нравится решение, опубликованное PanJunjieæ½˜ä¿Šæ °. Суть проблемы заключается только в повторенииthis.itemsодин раз (на этапе создания компонента), а затем кеширование результата. Это, конечно, ключевое преимущество использования вычисляемой опоры вместо метода.

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доступен по индексу списка. Мы могли бы улучшить это, используя.reduce() вместо того .map() в вычисляемой опоре для создания объекта с ключом для каждого item.id в 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>
Другие вопросы по тегам