Можно ли сохранить условный оператор в объекте и динамически добавлять его?
Например, у меня есть такой код, который выводит строку таблицы с кнопкой в ней:
<tr v-for = "item in items">
<td><button v-if = "item.display">{{item.name}}</button>
</tr>
Это мои данные, которые я возвращаю
data() {
return {
items : [
{
name : 'Item1',
display : 'price >= 5',
},
{
name : 'Item2',
display : 'price == 10',
},
],
}
},
При этом логика не работает. Кнопка отображается всегда.
Однако, если бы мне пришлось вручную вводить эту логику для каждой кнопки. Работает корректно. Например, это работает:
<tr v-for = "item in items">
<td><button v-if = "price >= 5">{{item.name}}</button>
</tr>
Итак, в конце концов, мой вопрос. Может ли условный оператор храниться таким образом и динамически добавляться, или Vue не распознает его таким образом?



Технически вы можете использовать функции как свойства ваших объектов и вызывать их:
new Vue({
el: '#app',
data() {
return {
price: 5,
items: [{
name: 'Item1',
display: (price) => price >= 5,
},
{
name: 'Item2',
display: (price) => price == 10,
},
],
}
}
})<script src = "https://unpkg.com/vue"></script>
<div id = "app">
Type "10": <input v-model = "price">
<table>
<tr v-for = "item in items">
<td><button v-if = "item.display(price)">{{item.name}}</button>
</tr>
</table>
</div>Но, возможно, более подходящим подходом Vueу было бы указать ограничения отображения в объекте и иметь расчет в метод.
Преимущество здесь в том, что ваши данные items легко сериализуемы (например, в JSON), тогда как в приведенном выше варианте это не так:
new Vue({
el: '#app',
data() {
return {
price: 5,
items: [{
name: 'Item1',
display: {op: 'ge', val: 5},
},
{
name: 'Item2',
display: {op: 'eq', val: 10},
},
],
}
},
methods: {
display(item) {
switch(item.display.op) {
case 'eq': return this.price == item.display.val;
case 'gt': return this.price > item.display.val;
case 'lt': return this.price < item.display.val;
case 'ge': return this.price >= item.display.val;
case 'le': return this.price <= item.display.val;
default: return false;
}
}
}
})<script src = "https://unpkg.com/vue"></script>
<div id = "app">
Type "10": <input v-model = "price">
<table>
<tr v-for = "item in items">
<td><button v-if = "display(item)">{{item.name}}</button>
</tr>
</table>
</div>Я думаю, что acdcjunior дал хороший прямой ответ на этот вопрос. Я не уверен, стоит ли мне что-то здесь добавлять на тот случай, если вопрос был чисто техническим по этой конкретной функции Vue.
Однако я просто хочу заметить, что данные - не лучшее место для хранения отображаемой информации. Более распространенная ситуация, когда у вас есть данные с собственными ценами:
data() {
return {
price: 5,
items: [{
name: 'Item1',
price: 5,
},
{
name: 'Item2',
price: 10,
},
],
}
}
И очень распространенный случай, когда вам нужно отрендерить только часть ваших элементов. Этот сценарий хорошо описан в vue docs: https://vuejs.org/v2/guide/list.html#Displaying-Filtered-Sorted-Results
Надеюсь, это не было лишним :)
Кроме того, вернемся к самому вашему вопросу:
Can the conditional statement be stored like that and dynamically added in, or will Vue not recognize it that way?
Думаю, короткий ответ - «Нет».
Потому что, когда вы передаете item.condition (который является строкой) в v-if, результат оценки вашего выражения (например, "price === 5") будет проверяться на правильность -> и непустая строка всегда будет true. Для струнных аналогов eval не существует.
Но когда выражение является функцией (как в примере acdcjunior), результат его выполнения будет результирующим выражением, которое следует проверить.