Получение данных пользователей во vue.js. Json api

95
27 ноября 2020, 22:40

Составил на сервере (laravel) json запрос, который получает комментарии статьи

/api/articles/articleUrl/comments

 {
           "data": [
              {
                 "type": "comments",
                 "id": "1",
                 "attributes": {
                    "content": "content"
                 },
                 "relationships": {
                    "user": [
                       {
                          "type": "user",
                          "id": "3",
                          "attributes":{
                            "username":"Aisha Quitzon"
                          }
                       }
                    ]
                 }
              },
             ....
           ]
        }

Я получил все комментарии через fetch:

Vue:

 async fetchComments(){
                this.comments = await fetch('/api/articles/' + articleUrl + '/comments').then(res => {
                    return res.json();
                }).then(comments => comments.data)
            }

Перебираю через v-for

<div v-for="(comment, index) in comments" :key="index">
        <div>{{ comment.attributes.content }}</div>
        <a id="username">{{ comment.relationships.user[0].attributes.username }}</a> 
        </div>

Мне не нравится, то чтобы получить данные от пользователя, приходится длинный код писать comment.relationships.user[0].attributes.username

Нужно ли к примеру в колонки user "attributes":{..} ?
Или лучше user - перенести на отдельный api запрос?

Подскажите, как можно это все упростить.

Answer 1

А почему comment.relationships.user - это массив? Должно быть примерно так:

class Comment extends Model
{
  public function author()
  {
    return $this->belongsTo(User::class, 'user_id', 'id', 'user');
  }
}

На счет самого вопроса, есть несколько вариантов:

  • парсить данные, перебирая ч/з forEach, тем самым подготовить массив для шаблона vue;
  • воспользоваться деструктурированием, плюс создавать вложенный компонент для пользователя куда ч/з атрибуты передавать свойства.

Расшифровка реляционных данных (relationships) должны быть в поле included:

{ 
  "data": [{ 
    "type": "articles", 
    "id": "1", 
    "attributes": { 
      "title": "JSON:API paints my bikeshed!", 
       "user_id": "9" 
    }, 
    "links": { 
      "self": "http://example.com/articles/1" 
    }, 
    "relationships": { 
      "author": { 
        "links": { 
          "self": "http://example.com/articles/1/relationships/author", 
          "related": "http://example.com/articles/1/author" 
        }, 
        "data": { "type": "people", "id": "9" } 
      }, 
      "comments": { 
        "links": { 
          "self": "http://example.com/articles/1/relationships/comments", 
          "related": "http://example.com/articles/1/comments" 
        }, 
        "data": [ 
          { "type": "comments", "id": "5" }, 
          { "type": "comments", "id": "12" } 
        ] 
      } 
    } 
  }], 
  "included": [{ 
    "type": "people", 
    "id": "9", 
    "attributes": { 
      "first-name": "Dan", 
      "last-name": "Gebhardt", 
      "twitter": "dgeb" 
    }, 
    "links": { 
      "self": "http://example.com/people/9" 
    } 
  }, { 
    "type": "comments", 
    "id": "5", 
    "attributes": { 
      "body": "First!" 
    }, 
    "relationships": { 
      "author": { 
        "data": { "type": "people", "id": "2" } 
      } 
    }, 
    "links": { 
      "self": "http://example.com/comments/5" 
    } 
  }, { 
    "type": "comments", 
    "id": "12", 
    "attributes": { 
      "body": "I like XML better" 
    }, 
    "relationships": { 
      "author": { 
        "data": { "type": "people", "id": "9" } 
      } 
    }, 
    "links": { 
      "self": "http://example.com/comments/12" 
    } 
  }] 
}

UPD Ссылки на спецификацию и реализации

UPD Пример реализации по просьбе ТС. В снипете НЕ работает. Использует json указанный в снипете выше.

Vue.component('user-card', { 
  template: `<div> 
            <b>{{ fullName }}</b> 
        </div>`, 
 
  props: { 
    attributes: Object, 
  }, 
 
  computed: { 
    fullName() { 
      return `${this.attributes['first-name']} ${this.attributes['last-name']}` 
    } 
  } 
}) 
 
 
new Vue({ 
  el: '#app', 
  data() { 
    return { 
      articles: [], 
      comments: [], 
      users: [] 
    } 
  }, 
  computed: { 
    getUser() { 
      return (user_id) => { 
        return this.users.find((item) => user_id == item.id) 
      } 
    } 
  }, 
  mounted() { 
    this.fetchResource() 
  }, 
  methods: { 
    async fetchResource() { 
      const response = await fetch('articles.json') 
      const json = await response.json() 
 
      this.articles = json.data 
      this.comments = json.included.filter(item => 'comments' === item.type) 
      this.users = json.included.filter(item => 'people' === item.type) 
    } 
  } 
})
<div id="app"> 
  <div v-for="({ id, attributes: {title, user_id} }, index) in articles" :key="id"> 
    <div>{{ title }}</div> 
    <user-card v-bind="getUser(user_id)"></user-card> 
  </div> 
</div>

READ ALSO
setInterval / setTimeout / clearInterval - Валидация поля - Нужна помощь по поводу ОСТАНОВКИ ТАЙМЕРА после &ldquo;Вставки&rdquo; значения через контекстное меню

setInterval / setTimeout / clearInterval - Валидация поля - Нужна помощь по поводу ОСТАНОВКИ ТАЙМЕРА после “Вставки” значения через контекстное меню

Событие keyup - пока печатается всё с клавиатуры - всё хорошоПользователь вводит текст, обработчик проверяет на правильность и если что-то неправиьлно...

125
Динамическое добавление блока

Динамическое добавление блока

у меня есть небольшая форма которая представляет из себя чек, в которой в селекте выбирается товар и рядом в инпуте количество этого товараВ...

104
Как правильно добавлять новую DOM Node?

Как правильно добавлять новую DOM Node?

Вырезал пример из моего проекта и сильно упростил: Данный код создаст один нужный мне фрагментДело в том, что я хочу создавать неограниченное...

119