September 30, 2019

Провайдер данных во Vue.js

Перевод статьи Data Provider component in Vue.js

Использование фреймворков / библиотек на основе компонентного подхода, таких как Vue.js, не означает, что все компоненты должны основываться на отображении и отрисовке UI.

Одним из моих самых любимых способов продвинутого повторного использования компонентов в больших приложениях - это использование композиции компонентов.

В слотах с ограниченной областью видимости (scoped slots), в статье «Использование слотов с ограниченной областью видимости во Vue.js», мы узнали о том, как можно инкапсулировать логику в компоненте и передавать ее в slots через props. Это позволяет нам создавать UI и поведение нового компонента, комбинируя все в одном месте .

Сегодня я собираюсь вам показать пример компонента провайдера данных.

Провайдер данных - это компонент без рендеринга (renderless component), то есть ему ничего не нужно отображать.

Основой для создания renderless component является создание scoped slots из функции render и передачей ему props:

render() {
  return this.$scopedSlots.default({
    loading: !this.loaded,
    data: this.data
  })
}

Из-за несогласованности в scoped slots (было исправлено в версии 2.6), вы можете сделать так, чтобы это работало везде (в версиях до 2.6):

render() {
  const slot = this.$scopedSlots.default({
    loading: !this.loaded,
    data: this.data
  })

  return Array.isArray(slot) ? slot[0] : slot
}

Для создания компонента провайдера данных необходимо выполнить ajax/fetch запрос при создании компонента (created), а затем передать эти данные в scoped slot.

Окончательная версия DataProvider.js выглядит следующим образом:

import axios from 'axios'

export default {
  props: ["url"],

  data: () => ({
    data: null,
    loaded: false
  }),

  created() {
    axios.get(this.url).then(({ data }) => {
      this.data = data
      this.loaded = true
    })
  },

  render() {
    const slot = this.$scopedSlots.default({
      loading: !this.loaded,
      data: this.data
    })

    return Array.isArray(slot) ? slot[0] : slot
  }
}

Обратите внимание на то, что файл имеет расширение .js. Так как он содержит в себе только часть script компонента, мы можем не создавать файл с расширением .vue

Компонент «Провайдер данных» также содержит в себе состояние loading (загрузки данных), поэтому мы можем использовать это состояние для отображения UI (к примеру: спинер загрузки данных) в зависимости от состояния загрузки данных. Пример:

<template>
  <DataProvider url="https://jsonplaceholder.typicode.com/users">
    <div v-slot="{ data, loading }">
      <div v-if="loading">Loading...</div>
      <div v-else>
        <h2>Result: {{ data.length }} users</h2>
        <p v-for="user in data" :key="user.id">{{ user.name }}</p>
      </div>
    </div>
  </DataProvider>
</template>

Вот и все!

Если вы хотите посмотреть на пример работы этого компонента, то перейдите в CodeSandbox!

Послесловие

Подписывайся на нас в социальных сетях:
Vue.js

Nuxt.js

Наши друзья uWebDesign: