I have many pages with a list of items. Appeal to some api and display the resulting, something like:

Template:

<template> <div class="container"> <div class="row"> <div class="col-12"> <h1>City</h1> <div> <div v-if="errored" class="alert alert-danger"> <p>Произошла ошибка: {{ this.error_text }}</p> </div> <div v-else> <div v-if="loading" class="alert alert-info">Loading...</div> <div v-else> <table class="table"> <tr v-for="item in info" :key="item.id"> <td>{{ item.id }}</td> <td>{{ item.verified }}</td> <td>{{ item.title }}</td> </tr> </table> </div> </div> </div> </div> </div> </div> </template> 

Script:

 <script> import ApiService from '@/services/api'; export default { name: 'City', data() { return { info: null, loading: false, errored: false, error_text: '', }; }, methods: { makeReq: function makeReq() { this.loading = true; ApiService.post('/cityApi/all', {}) .then((response) => { this.info = response.data.cities; }) .catch((error) => { this.errored = true; this.error_text = ApiService.get_error(error); }) .finally(() => { this.loading = false; }); }, }, mounted() { this.makeReq(); }, }; </script> 

And somehow I recently thought that constantly repeating the same boilerplate in such pages:

  1. In the template there is always some custom section with a table, and I constantly copy the rest of the binding, with this header and display of load / error
  2. In the code, I always have the same variables loading, errored and expired with the same values ​​- I would like to declare them once in some basic component and add only new ones if necessary
  3. The request is exactly the same, always different, except the url

In the guidelines on vue.js I did not come across sections that would help to bring all such uniform code into some basic components and be inherited. How can such a thing be done in vue?

  • one
    Dig to the side of mixins. vuejs.org/v2/guide/mixins.html#Basics - Dmytryk
  • @ Dmytryk Thanks for the tip! I understand correctly that nothing can be done with templates, mixins for code only? - AK
  • one
    Yes, mixins are for code only. However, the template can be connected by reference. It looks like this <template src="./hello.html"><template><script></script><style></style> - Dmytryk
  • 2
    Why not just use the slot for custom content? en.vuejs.org/v2/guide/components-slots.html - yar85 1:49 pm
  • one
    About the inheritance of components - Rustam Gimranov

1 answer 1

In general, I came to such an organization of the project.

In the src / mixins folder I created BaseApiRequestMixin:

 import ApiService from '@/services/api'; const BaseApiRequestMixin = { data() { return { loading: false, errored: false, error_text: '', }; }, methods: { request: function request(url, data, response) { this.loading = true; ApiService.post(url, data) .then(response) .catch((error) => { this.errored = true; this.error_text = ApiService.get_error(error); }) .finally(() => { this.loading = false; }); }, }, }; export default BaseApiRequestMixin; 

And I use in components:

 <script> import BaseApiRequestMixin from '@/mixins/BaseApiRequestMixin'; export default { name: 'City', mixins: [BaseApiRequestMixin], mounted() { this.request('/cityApi/all', { }, (response) => { this.cities = response.data.cities; }); }, }; </script> 

This is a good clean script code. I did not understand the slots and the connection of templates.

From the noted shortcomings - Vetur swears that Property 'errored' does not exist on type 'CombinedVueInstance', it is necessary to correct .vscode / settings.json:

 "vetur.experimental.templateInterpolationService": false, 

Thank you all for the advice.