Хобрук: Ваш путь к мастерству в программировании

VUEJS V-FOR ведет себя странно

Мне нужен простой v-for для отображения свойств объекта в списке.

<div
   v-if="profileData && profileData.length > 0"
>
  <ul
    v-for="value in profileData"
    :key="value.id"
  >
    <li>{{value.id}}</li>
  </ul>
</div>

В сценарии:

profileData: {},
created() { 
  const userId = this.$route.params.userId
  const currentUser = this.$store.getters.currentUser
  const profileData = this.$store.getters.profileData 
  console.log('profileData in seeProfile: ', profileData) }

(profileData исходит из ответа API)

Я сделал то же самое на двух других страницах (просто отображая разные объекты), и это сработало. С помощью этого кода в консоли я получаю value is undefined. Если я уберу :key="value.id" (в редакторе он становится красным, но все равно работает), а вместо элементов списка наберу только {{ value }}}, то отрисуются свойства объекта (но в уродливом формате js-объекта). Как это может быть? Что я делаю не так? Спасибо

09.09.2019

  • profileData не является массивом, поэтому вы перебираете значения его объектов. 09.09.2019
  • Понятно. Так? Должен ли я связывать значения вместо ключей? 09.09.2019
  • Чего вы хотите достичь? Это до этого. Я бы отладил его, сначала напечатав объект {{ profileData }}. Затем вы можете увидеть структуру. Если это массив, вы можете просмотреть элементы с помощью <li v-for="item in profileData">{{ item }}</li>. Затем вы можете увидеть отдельные элементы в <li> элементах. Если вы хотите перебрать объект, вы можете сделать это так: <li v-for="(itemValue, itemKey) in profileData">{{ itemKey }}: {{ itemValue }}</li>. Если это работает, вам нужно привязать уникальный ключ к элементу <li>, чтобы сделать его более производительным. 09.09.2019
  • @ ssc-hrep3 Журнал консоли возвращает список свойств, profileData действительно является объектом, поэтому мне нужен цикл по его свойствам. Я уже пробовал то, что вы предложили, но это не работает. Странно, не знаю куда смотреть.... 09.09.2019
  • console.log может напечатать объект, отличный от того, который вы просматриваете в шаблоне, в зависимости от того, когда вы печатаете его на консоли. Добавление его в шаблон должно всегда представлять вам текущий. Например. когда наблюдатель меняет этот объект, а вы этого не ожидали. 09.09.2019

Ответы:


1

Ваш v-if никогда не будет отображаться, даже если profileData имеет данные, потому что вы не можете напрямую проверить длину объекта в javascript.

Несколько вещей:

  1. Вы не можете проверить длину объекта, он вернет undefined. Если вы должны использовать объект, вам нужно будет проверить наличие Object.keys(obj).length.

let obj = {
  first: {
    name: "first",
    meta: "data"
  },
  second: {
    name: "second",
    meta: "data"
  }
};

console.log("Object.length is: ", obj.length);
console.log("Object.keys().length is: ", Object.keys(obj).length);

  1. Вы избыточны, вам не нужно проверять profileData и его длину (и вам не нужно> 0), вы можете просто проверить v-if="Object.keys(profileData).length". Если в объекте нет записей, он не будет отображаться, потому что if(0) является ложным.
  2. Я настоятельно рекомендую работать с массивами для итерации с v-for. Я бы использовал вычисляемые свойства и возвращал массив и повторял бы его. Реактивность объектов работает в JS неинтуитивно, поэтому позже вы будете ломать голову, когда попытаетесь выяснить, почему что-то не обновляется в вашем представлении:
computed: {
    listData() {
        let list = Object.values(this.profileData);
        return list;
    }
}

С учетом:

<div v-if="listData.length"/>

Кроме того, не используйте индекс входа массива в качестве :key, потому что если у вас есть другой массив с v-for, у вас будут дублированные ключи в вашей модели. Я бы использовал что-то вроде v-for="(item, key) in list" :key="'list-item-' + key"

10.09.2019

2

Ставьте v-for на li, а не на ul.

<ul>
    <li v-for="value in profileData"
    :key="value.id">{{value.id}}</li>
</ul>

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

<ul>
    <li v-for="value in Object.values(profileData)"
    :key="value.id">{{value.id}}</li>
</ul>
<ul>
    <li v-for="value in Object.keys(profileData)"
    :key="value.id">{{value.id}}</li>
</ul>

Или используйте поведение Vue по умолчанию.

<ul>
    <li v-for="(value,key) in profileData"
    :key="value.id">{{value.id}}</li>
</ul>
09.09.2019
  • Это правильно, но это не решит проблему, отмеченную в комментарии, поэтому ничего не будет отображаться. (profileData.length будет undefined, так как profileData — это объект.) 09.09.2019
  • @ Стивен Я поместил v-for в li, как вы предложили, и удалил директиву v-if, как указал Стивен, но значения все равно не отображаются. Хотя ошибок в консоли нет. 09.09.2019
  • Почему вы используете Object.values? Это не нужно, и вам даже нужен полифилл для этого в IE. См. документацию: vuejs.org/v2/guide/ list.html#v-для-с-объектом 09.09.2019
  • Как указано в предоставленной вами ссылке: v-for с объектом. Вы также можете использовать v-for для перебора свойств объекта. ``` ‹ul id=v-for-object class=demo› ‹li v-for=value in object› {{ value }} ‹/li› ‹/ul›``` Я так и сделал, но это не Работа. 09.09.2019
  • Похоже, ваш объект не такой, как вы ожидаете, во время цикла ????‍♂️ Распечатайте его в шаблоне, чтобы увидеть, выглядит ли объект так, как должен. 09.09.2019
  • @ ssc-hrep3 Я использую Object.values, чтобы прояснить, что вы получаете, вместо того, чтобы полагаться на default, что неудобно, учитывая, что for-in вернет что-то другое, чем for-of. Без сомнения, более ранние реализации JS до ES6 принимали ужасные решения. 10.09.2019
  • v-for в шаблоне vue.js ведет себя иначе, чем for..in, поскольку всегда возвращает значение свойства (в качестве первого аргумента, ключ в качестве необязательного второго и индекс в качестве необязательного третьего). Это специфично для Vue.js и правильно описано в документации как единственный способ напрямую перебрать объект в шаблоне. Но вы, конечно, можете сначала сопоставить его с массивом, а затем перебрать его. 10.09.2019
  • Это правда, Vue перебирает объекты не так, как JS. Более того, кастинг, как я сделал, делает код более понятным. У вас по-прежнему есть доступ к индексу в качестве второго аргумента. В любом случае, вот ссылка на документы, на которые вы ссылались. vuejs.org/v2/guide/list.html# v-для-с-объектом. Я обновил решение с этим синтаксисом. 10.09.2019
  • Таким образом, простое написание <div> <ul> <li>{{profileData}}</li> </ul> </div> показывает {} в шаблоне. Итак, я предполагаю, что шаблон обращается к объекту profileData до того, как он будет заполнен API. Как убедиться, что это происходит только тогда, когда все данные загружены? Я читал о наблюдателях и хуках жизненного цикла, но не знаю, как их использовать в коде. 10.09.2019
  • В моем коде есть только created() { const userId = this.$route.params.userId const currentUser = this.$store.getters.currentUser this.currentUser = currentUser console.log('STORE IN SEE PROFILE: ', this.$store.state) console.log('currentUser in seeProfile: ', currentUser) const profileData = this.$store.getters.profileData console.log('profileData in seeProfile: ', profileData) } 10.09.2019
  • Для вашего первого вопроса вы используете v-if/v-else: <div v-if='! profileData'>Loading...</div><div v-else>{{profileData}}</div> 10.09.2019
  • Пожалуйста, обновите свой вопрос, указав раздел данных вашего компонента и созданный метод. 10.09.2019

  • 3

    Изменен API, поэтому рабочий код немного отличается от исходного. Вот шаблон:

    <div
      v-if="listData.length"
    >
      <ul>
        <li>Name: <b>{{ profileData.user.first_name }}</b></li>
        <li>Surname: <b>{{ profileData.user.last_name }}</b></li>
        <li>Username: <b>{{ profileData.user.username }}</b></li>
        <li>Car: <b>{{ profileData.if_cars_owned }}</b></li>
        <li v-if="profileData.if_cars_owned === true">
          Car model: {{ profileData.user_car_type }}
        </li> 
        <li v-if="profileData.if_cars_owned === true">
          Car power: {{ profileData.user_car_powered_by }}
        </li> 
        <li>Motorcycle: <b>{{ profileData.if_motorcycle_owned }}</b></li>
        <li v-if="profileData.if_motorcycle_owned === true">
          Motorcycle model: {{ profileData.user_motorcycle_characteristic }}
        </li>
      </ul>
    </div>
    

    Скрипт:

    created(){
        const profileData = this.$store.getters.profileData
        this.profileData = profileData
        console.log('profile data in profilo: ', profileData)
      },
    

    я тоже обновил

    <div
      v-if="listData.length"
    >
    

    и в сценарии

    computed: {
        ...,
        listData() {
          let list = Object.values(this.profileData);
          return list;
        }
    },
    

    следуя совету @Adrián S. Basave. Спасибо всем, кто пытался помочь. Икс

    10.09.2019
    Новые материалы

    Не зря же это называют интеллектом
    Стек — C#, Oracle Опыт — 4 года Работа — Разведывательный корпус Мне пора служить Может быть, я немного приукрашиваю себя, но там, где я живу, есть обязательная военная служба на 3..

    LeetCode Проблема 41. Первый пропущенный положительный результат
    LeetCode Проблема 41. Первый пропущенный положительный результат Учитывая несортированный массив целых чисел, найдите наименьшее пропущенное положительное целое число. Пример 1: Input:..

    Расистский и сексистский робот, обученный в Интернете
    Его ИИ основан на предвзятых данных, которые создают предрассудки. Он словно переходит из одного эпизода в другой из серии Черное зеркало , а вместо этого представляет собой хронику..

    Управление состоянием в микрофронтендах
    Стратегии бесперебойного сотрудничества Микро-фронтенды — это быстро растущая тенденция в сфере фронтенда, гарантирующая, что удовольствие не ограничивается исключительно бэкэнд-системами..

    Декларативное и функциональное программирование в стиле LINQ с использованием JavaScript с использованием каррирования и генератора ...
    LINQ - одна из лучших функций C #, которая обеспечивает элегантный способ написания кода декларативного и функционального стиля, который легко читать и понимать. Благодаря таким функциям ES6,..

    Структуры данных в C ++ - Часть 1
    Реализация общих структур данных в C ++ C ++ - это расширение языка программирования C, которое поддерживает создание классов, поэтому оно известно как C с классами . Он используется для..

    Как я опубликовал свое первое приложение в App Store в 13 лет
    Как все началось Все началось три года назад летом после моего четвертого класса в начальной школе. Для меня, четвертого класса, лето кажется бесконечным, пока оно не закончится, и мой отец..