Vue.js - пишем компонент по работе с API

Vue.js - пишем компонент по работе с API

Во vue.js существуют очень интересное понятие - так называемые headless компоненты. Ещё их называют renderless-компоненты. Цель этих компонентов - максимальная гибкость посредством выделения логики рендеринга. Это особенно полезно, когда компонент содержит большую бизнес-логику.

Во vue.js существуют очень интересное понятие - так называемые headless компоненты. Ещё их называют renderless-компоненты. Цель этих компонентов - максимальная гибкость посредством выделения логики рендеринга. Это особенно полезно, когда компонент содержит большую бизнес-логику.

Когда мы работаем с компонентами во Vue.js, то чаще всего мы совершаем различные ajax-запросы с использованием axios. И зачастую axios-запросы - это копипаст кусков кода из компонента в компонент. Использовать миксины в этом случае часто плохая затея, т.к. иногда нам нужно менять параметры запроса, адрес и прочее. Поэтому здесь нам на помочь призодят headless-компоненты.

Давайте вспомним, как происходит отправка запросов с использованием axios:

axios.get('https://jsonplaceholder.typicode.com/posts/1')

.then(repsponse => {

console.log(response.data);

})

.catch(error => {

console.error(error);

})

 

Для данного публичного API ответ будет следующим:

 

{

  "userId": 1,

  "id": 1,

  "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",

  "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"

}

 

Чтобы получить заголовок, нам потребуется обратиться к объекту по следующему пути: response.data.title.

Вооружившись этими знаниями, мы можем написать специальный компонент request, задача которого будет состоять в отправке запроса, обработке данных. Использовать компонент мы можем следующим образом:

    <request url="https://jsonplaceholder.typicode.com/posts/1">

      <template v-slot:default="{ loading, data }">

        <div v-if="loading">Loading...</div>

        <div v-else>

          <h1>

            {{data.title}}

          </h1>

          <p>

            {{data.body}}

          </p>

        </div>

      </template>

    </request>

 

В нашем примере компонент request использует входной параметр url, по которому компонент и осуществляет отправку запроса.

В ответ от данного компонента мы получаем на только обработанные данные в data, но и параметр loading, по которому мы определяем, показывать ли нам индикатор загрузки или нет. Только после того, как закончена загрузка, мы показываем данные ответа.

 

    Vue.component("Request", {

      render() {

        return this.$scopedSlots.default({

          loading: this.loading,

          data: this.response && this.response.data

        })[0];

      },

      props: {

        url: String

      },

      data() {

        return {

          loading: true,

          response: null

        }

      },

      created() {

        axios.get(this.url)

          .then(response => {

            this.response = response;

            this.loading = false;

          })

      }

    });

 

В этом максимально простом примере в качестве входного параметра мы принимаем только url и управляем данными ответа, состоянием загрузки. Вся процедура отправки ajax-запроса происходит в хуке created. В его задачу входит не только отправка запроса, но и его обработка, сохранение ответа, смена флага loading. После обработки данных, вся информация отправляется через scoped slots родительскому компоненту.

Есть одна очень важная деталь - у нашего компонента нет внутреннего состояния. Как и в обычном компоненте мы можем инициировать события, а в родительском компоненте подписываться на них.

И согласитесь, очень удобно, что мы теперь этот большой компонент со всей бизнес-логикой обработки ajax-запросов можем использовать неограниченное количество раз с разными типами шаблонов. Ведь заметьте, что в компоненте вообще отсутствует отрисовка шаблона. Она осуществляется в родительском компоненте, а здесь мы только передаём наверх данные