Vue: Поддержка большего количества типов данных коллекции в v-for

Созданный на 28 февр. 2016  ·  39Комментарии  ·  Источник: vuejs/vue

В некоторых ситуациях простой объект - не лучший выбор. Я попытался визуализировать объект Map помощью v-for , но, похоже, Vue настоящее время не поддерживает его. (Вот сообщение, которое я создал в ветке справки на форуме.)

Надеюсь, Vue может предоставить синтаксис for ... of в v-for для перебора типов данных, таких как Map и Set .

Например:

const map = new Map();
map.set('key1', 'val1');
map.set('key2', 'val2');

и мы можем отобразить map следующим образом:

<ul>
    <li v-for="[key, val] of map">{{key}} - {{val}}</li>
</ul>
feature request

Самый полезный комментарий

Важно иметь возможность перебирать итераторы в циклах. Это кажется очевидным. Это фундаментальная особенность языка.

Причины его поддержки:

1) Итераторы, карты и наборы - все действительные ES6. Отказ от их поддержки означает ограничение себя ES5, и это решение со временем становится все менее и менее оправданным.
2) Я создаю приложение, в котором внутренние данные хранятся в картах и ​​наборах. Вместо того, чтобы делать их доступными для пользовательского интерфейса, теперь мне нужно синхронизировать данные между ними вручную или написать шаблон и импортировать его в мои шаблоны, чтобы выполнять преобразование всякий раз, когда данные необходимы. Это именно то, чего Vue призван избегать.

Все 39 Комментарий

Дубликат https://github.com/vuejs/vue/issues/1319

@wenLiangcan , вы можете использовать что-то вроде этого:

<ul>
    <li v-for="[key, val] of get(map)">{{key}} - {{val}}</li>
</ul>

где get() - ваша функция.

ха-ха! подобные проблемы открываются постоянно, и люди настаивают на том, что они не могут оправдать реализацию, и люди хотят ее использовать. Это одно из оправданий. Я также могу перечислить миллиард закрытых проблем, которые задают одно и то же xD. Я также нашел тот, который действительно хорошо оправдывает вариант использования и ссылается на спецификацию es6, когда дело доходит до порядка карты -> все еще закрыто.

Люди, желающие использовать функцию, сами по себе не являются аргументом, который может оправдать необходимость наличия такой функции, необходимо взвесить стоимость и преимущества (какая проблема решается) от добавления такой функции.

Да, но все же аргументы, которые люди используют, чтобы закрыть проблему, все еще недействительны или, по крайней мере, не действительны для всех вариантов использования, например, пример elipen, который очень хорошо оправдал свои варианты использования, как я упоминал выше

Если вы хотите обсудить конкретный вопрос, дайте ссылку на него.

Кроме того, этот вопрос с функцией открыт. Нет смысла открывать более одной проблемы для одного и того же запроса.

Важно иметь возможность перебирать итераторы в циклах. Это кажется очевидным. Это фундаментальная особенность языка.

Причины его поддержки:

1) Итераторы, карты и наборы - все действительные ES6. Отказ от их поддержки означает ограничение себя ES5, и это решение со временем становится все менее и менее оправданным.
2) Я создаю приложение, в котором внутренние данные хранятся в картах и ​​наборах. Вместо того, чтобы делать их доступными для пользовательского интерфейса, теперь мне нужно синхронизировать данные между ними вручную или написать шаблон и импортировать его в мои шаблоны, чтобы выполнять преобразование всякий раз, когда данные необходимы. Это именно то, чего Vue призван избегать.

Поскольку №1319 закрыт, здесь стоит повторить текущее решение. Короче говоря, реализовать эту функцию нетривиально (на уровне механизма наблюдения), поэтому речь идет не об обосновании вариантов использования, а об объеме работы и компромиссах.

Я тоже был бы очень признателен за эту функцию. С другой стороны, если наблюдение за типами данных ES6 становится ужасно хакерским или, например, ставит под угрозу производительность или другие качества, то люди, которые в настоящее время не используют карты и наборы с Vue, могут не оценить это изменение.

Я полагаю, что использование Array.from () внутри вычисляемой функции на данный момент должно быть вашим лучшим другом. :разочарованный:

Любое решение для этого?

Небольшое обновление, это произойдет, если / когда Vue решит отказаться от «старых» браузеров и перейдет в Evergreen с Proxy вместо set / get для реактивности.

@ alexsandro-xpt, просто используйте вычисляемую функцию, которая возвращает Array.from(yourDataSet) .

@nickmessing Я пытаюсь использовать карту, не работает.
Значение длины вычисляемого массива всегда равно 0.

Просто Array.from , вероятно, не является решением, которое вам нужно из-за отсутствия реактивности (изменения в yourDataSet не будут распространены на Vue).

Как упоминалось ранее, Vue не наблюдает за наборами и картами. Чтобы использовать их - либо в v-for , или в вычисляемых свойствах, методах, наблюдателях, выражениях шаблонов и т. Д. - вам необходимо создать сериализуемую реплику этой структуры и предоставить ее Vue. Вот наивный пример, который использует простой счетчик для предоставления Vue информации об обновлении Set:

data() {
  mySetChangeTracker: 1,
  mySet: new Set(),
},

computed: {
  mySetAsList() { 
    // By using `mySetChangeTracker` we tell Vue that this property depends on it,
    // so it gets re-evaluated whenever `mySetChangeTracker` changes
    return this.mySetChangeTracker && Array.from(this.mySet);
  },
},

methods: {
  add(item) {
    this.mySet.add(item);
    // Trigger Vue updates
    this.mySetChangeTracker += 1;
  }
}

Это иллюстрирует своего рода хакерский, но на 100% рабочий метод для того, чтобы сделать ненаблюдаемые данные реактивными. Тем не менее, в реальных случаях я получал сериализованные версии наборов / карт (например, вы, вероятно, захотите сохранить модифицированные версии наборов / карт в локальном хранилище и, таким образом, сериализовать их в любом случае), поэтому никаких искусственных счетчиков / хаков не использовалось.

Я лично считаю, что это справедливое решение проблемы, но оно определенно заслуживает некоторой официальной документации - иначе невозможно оправдать это как нехакерский способ работы с внутренними компонентами Vue.

@ alexsandro-xpt, извините, я ошибался, вычисление будет хакерским, как сказал $forceUpdate с методом, вот пример скрипки

Спасибо @nickmessing и @inca , это отлично работает с моими new Map() !!

Прямо сейчас, когда вы выполняете «v-for» над «Map», v-for действует так, как если бы он получил пустой массив.

Независимо от результата расширенной дискуссии о том, поддерживать ли / как карты и наборы, это сэкономило бы многим людям много времени на отладку, если бы Vue просто предупредил: «Карты и наборы еще не поддерживаются - см. Https: // github .com / vuejs / vue / issues / 2410 ".

Ага, поиск этой функции в Google привел меня к этому тикету (после нескольких досадных путаниц с Vue.set)

👍 Это должно быть в документации v-for!

Воистину, должно быть в документации v-for!

/ cc @chrisvfritz давайте попробуем добавить примечание о поддержке этих типов в документацию для v-for (как API, так и раздел рендеринга списка) - я также рассмотрю их в 2.5.

@ yyx990803 Интересно,

Мы также уже очень четко указываем в документации, какие типы мы _do_ поддерживаем, а среди них нет Map и Set . Я определенно вижу аргумент в пользу того, почему можно _ надеяться_, что все итерируемые объекты будут работать с v-for , но я не думаю, что в настоящее время мы даем читателям какие-либо основания ожидать, что они будут.

Я не совсем понимаю аргумент против добавления поддержки Set .

Set сам по себе может быть чисто полифиллирован, и, если я чего-то не упускаю, похоже, что подход Vue к добавлению реактивности в массивы можно очень легко распространить на наборы. Нам нужно только обернуть .add() , .clear() и .delete() .

Мое лучшее предположение (пожалуйста, поправьте / извините, если я ошибаюсь): самая сложная часть - это обернуть конструктор Set , который принимает итерацию. Я не понимаю, как итерацию можно сделать наблюдаемой, потому что в общем виде это просто функция (например, next ) без состояния, на которое можно ссылаться (подумайте об итераторе на основе генератора в качестве примера).

Зачем нам нужно оборачивать конструктор? Разве мы не передали бы уже существующие наборы во Vue?

Согласно спецификации , конструктор Set немедленно проходит через весь итератор, эффективно сохраняя мелкую копию уникальных элементов, возвращаемых итератором. Если у вас есть экземпляр Set , не имеет значения, был он создан с помощью итератора или нет.

В этом отношении Set созданный из итератора, не должен отличаться от массива, созданного из итератора (через Array.from() ), который Vue уже поддерживает.

Вы можете использовать неизменяемые карты / наборы / любые структуры данных и разрешить с ними реактивность, но просто потому, что изменяется вся ссылка на фрагмент. Вы можете визуализировать их с помощью функции рендеринга или вычисленного сгенерированного массива (более ранний вариант лучше по производительности, поскольку он пропускает создание массива ..). Но изменчивые структуры данных, не так, если вы не найдете способ уведомить Vue о конкретных изменениях вручную, что было бы просто вашим собственным решением.

Это не хорошо. Ты не можешь этого сделать

@wenLiangcan

var map = new Map()
  map.set('key1','Test1')
  map.set('key2','Test2')
        <div class="file-size">{{value}}</div>
 </div>

Нет, это не отображается на странице

Заинтересован в поддержке этого :)

Я тоже

Есть ли планы на будущее по добавлению поддержки? Есть ли техническая причина, по которой Vue не может поддерживать Map and Set?

Текущая проблема с методом Vue.set для простого объекта заключается в том, что он запускает слишком много подписчиков, когда свойство добавляется к объекту. Фактически, все подписчики всех свойств срабатывают, когда добавляется только одно свойство.

Производительность представления сильно снижается, если карта, подобная коллекции, содержит сотые доли ключей. Например, в моем проекте тысячи подписчиков запускаются, когда один элемент добавляется на карту с помощью операции Vue.set:

Vue.set(state.items, itemId, item); // where items is a plain object.

Когда я глубоко вникаю в код Vue.js, я вижу, откуда взялась проблема. Зависимости, которые запускаются, являются зависимостями объекта, что означает, что если объект имеет одно свойство для каждого ключа, то все зависимости всех ключей запускаются при добавлении одного ключа.

Таким образом, использование простых объектов для имитации карты не выглядит правильным решением, и поэтому поддержка карты в vue более чем приветствуется для больших коллекций элементов.

Есть ли новости о планах на будущее и, возможно, о встроенной поддержке Map/Set ?

В этой статье подробно рассказывается о предстоящей поддержке в версии 2.6 - но в официальной дорожной карте ничего об этом нет, насколько я могу судить?

https://medium.com/@alberto.park/the -status-of-javascript-libraries-frameworks-2018 -yond-3a5a7cae7513

«Последняя версия ядра - 2.5.x. Следующий второстепенный выпуск (v2.6) будет поддерживать собственный импорт ESM, улучшенную обработку асинхронных ошибок, итератор в директиве 'v-for' и многое другое».

Не знаете, откуда они взяли эту информацию?

Обнаружил эту проблему во время отладки чертова поведения Vue над объектами данных Set . : мышление:

Для таких людей, как я, которые интересовались дорожной картой для этого, Эван Ю говорит в этом видео, что поддержка Map и Set «вероятно» появится в версии 2.6, но это было в мае, так что это все, что я знаю.

@ yyx990803 К сожалению, эта проблема в трекере помечена как закрытая, особенно если вы планируете добавить поддержку в ближайшем будущем. Где мы можем следить за развитием этой функции? Есть ли где-нибудь еще одна проблема?

Просто интересно для аргументации, и, возможно, я делаю это неправильно, но поскольку вы можете отслеживать мутацию массива с помощью методов мутации, не можете ли вы просто отслеживать массив объекта и быть логически завершенным? у вас нет всех тех же функций, реализованных в Map, но те, которые вам нужны, будут довольно легко решены, особенно если вы используете что-то вроде _ или lodash.

Это печально, но пока команда не добавит это, нам, возможно, придется использовать альтернативные структуры данных.

Просто хочу сказать, что мы собирались использовать Map для нашей структуры данных, а затем отказались от этого из-за отсутствия поддержки со стороны сторонних разработчиков.

Это планируется для vue.js v3.0.
Сравните: https://medium.com/the-vue-point/plans-for-the-next-iteration-of-vue-js-777ffea6fabf

поддерживается ли это сейчас в Vue3 (то есть реактивными Map и Set )?

Была ли эта страница полезной?
0 / 5 - 0 рейтинги