¿Cuál es el equivalente de Angular Service en VueJS?


95

Quiero poner todas mis funciones que se comunican con el servidor y obtienen datos en un solo archivo reutilizable en VueJS.

Los complementos no parecen ser la mejor alternativa. Plantilla sin componentes ..?

Respuestas:


58

En total hay 4 formas:

  • Servicio sin estado: entonces deberías usar mixins
  • Servicio con estado: use Vuex
  • Exportar servicio e importar desde un código vue
  • cualquier objeto global de javascript

4
Parece muy incómodo tratar de adherirse a las rarezas de Vuex de llamar a métodos con cadenas literales para servicios cuando podría hacer una clase TypeScript / JS que contenga el estado y la lógica para ello. ¿Cómo se puede utilizar una clase con estado como servicio dentro de Vue?
Douglas Gaskell

37

Estoy usando axios como cliente HTTP para hacer llamadas a la API, he creado una gatewayscarpeta en mi srccarpeta y he puesto archivos para cada backend, creando instancias de axios , como sigue

myApi.js

import axios from 'axios'
export default axios.create({
  baseURL: 'http://localhost:3000/api/v1',
  timeout: 5000,
  headers: {
    'X-Auth-Token': 'f2b6637ddf355a476918940289c0be016a4fe99e3b69c83d',
    'Content-Type': 'application/json'
  }
})

Ahora en su componente, puede tener una función que obtendrá datos de la API como sigue:

methods: {
 getProducts () {
     myApi.get('products?id=' + prodId).then(response =>  this.product = response.data)
  }
}

Como supongo que desea reutilizar este método en múltiples componentes, puede usar mixins de vue.js:

Los mixins son una forma flexible de distribuir funcionalidades reutilizables para componentes de Vue. Un objeto de mezcla puede contener cualquier opción de componente. Cuando un componente utiliza un mixin, todas las opciones del mixin se "mezclarán" en las opciones propias del componente.

Entonces puedes agregar un método en mixin y estará disponible en todos los componentes, donde se mezclará mixin. Vea el siguiente ejemplo:

// define a mixin object
var myMixin = {
  methods: {
     getProducts () {
         myApi.get('products?id=' + prodId).then(response =>  this.product = response.data)
      }
  }
}

// define a component that uses this mixin
var Component = Vue.extend({
  mixins: [myMixin]
})

// alternate way to have a mixin while initialising
new Vue({
  mixins: [myMixin],
  created: function () {
    console.log('other code')
  }
})

3
¿Cómo actualizará X-Auth-Token de myApi.js cuando el usuario inicie sesión
Amarjit Singh

3
por lo general, este no es un valor estático
Amarjit Singh

30

Estoy usando Vue Resource principalmente.

1.Creo un nuevo archivo donde me Vue.http.xxxconecto al punto final de la API usando . Entonces, digamos que tenemos un punto final que genera las publicaciones. Cree un nuevo directorio en su proyecto, lo llamo services, y luego creo el archivo llamado PostsService.js- el contenido se ve así:

import Vue from 'vue'

export default {
  get() {
    return Vue.http.get('/api/posts)
  }
}

Luego voy al componente donde quiero usar este servicio y lo importo

import PostsService from '../services/PostsService'

export default {
  data() {
   return {
     items: []
   }
  },
  created() {
   this.fetchPosts()
  },
  methods: {
   fetchPosts() {
    return PostsService.get()
      .then(response => {
        this.items = response.data
      })
   }
  }
}

Para obtener más información sobre este enfoque, no dude en consultar mi repositorio en GitHub https://github.com/bedakb/vuewp/tree/master/public/app/themes/vuewp/app


7
Según Evan You, Vue-Resource se retirará y recomienda Axios en su lugar. Lea su artículo Me gusta mucho su enfoque, que se siente más como angular 2
código

@noypee VueResource todavía funciona, pero no importa si usa lo que quiera, sería exactamente el mismo enfoque con Axios.
Belmin Bedak

1
Sí, Vue2 continuará acomodando vue-resource también según su artículo
codely

2
Esto es muy bueno, pero ¿cómo probar un componente de este tipo con mock-PostsService?
Shrike

@noypee, vue-resource no se está retirando - Evan declaró que simplemente lo está "retirando del estado de recomendación oficial" . Además, aclaró por qué su equipo concluyó que ya no era necesaria una biblioteca AJAX oficial. El artículo vinculado lo explica bien. Y debe tenerse en cuenta que vue-resource todavía se mantiene activamente y es una opción perfectamente viable.
squidbe

8

Sugiero crear un proveedor de API al que pueda acceder desde cualquier lugar de su aplicación.

Simplemente cree una src/utilscarpeta y dentro de ella un archivo llamado api.js.

En él, exporta tu contenedor que sepa cómo comunicarse con tu API como un objeto o una clase estática de ES6 (prefiero cómo se ve y funciona esta última si no le tienes miedo a las clases). Este proveedor puede usar cualquier biblioteca de solicitudes HTTP que desee y puede intercambiarla fácilmente más tarde cambiando un solo archivo (este) en lugar de buscar todo el código base. Aquí hay un ejemplo del uso de axios, asumiendo que tenemos una API REST disponible en api.example.com/v1que usa SSL:

import axios from 'axios'

import { isProduction, env } from '@/utils/env'

const http = null // not possible to create a private property in JavaScript, so we move it outside of the class, so that it's only accessible within this module

class APIProvider {
  constructor ({ url }) {
    http = axios.create({
      baseURL: url,
       headers: { 'Content-Type': 'application/json' }
    })
  }

  login (token) {
    http.defaults.headers.common.Authorization = `Bearer ${token}`
  }

  logout () {
    http.defaults.headers.common.Authorization = ''
  }

  // REST Methods
  find ({ resource, query }) {
    return http.get(resource, {
      params: query
    })
  }

  get ({ resource, id, query }) {
    return http.get(`${resource}/${id}`, {
      params: query
    })
  }

  create ({ resource, data, query }) {
    return http.post(resource, data, {
      params: query
    })
  }

  update ({ resource, id, data, query }) {
    return http.patch(`${resource}/${id}`, data, {
      params: query
    })
  }

  destroy ({ resource, id }) {
    return http.delete(`${resource}/${id}`)
  }
}

export default new APIProvider({
  url: env('API_URL')  // We assume 'https://api.example.com/v1' is set as the env variable
})

A continuación, en su main.jsarchivo o en cualquier otro lugar donde inicie la aplicación Vue, haga lo siguiente:

import api from '@/src/utils/api'

Vue.$api = api

Object.defineProperty(Vue.prototype, '$api', {
  get () {
    return api
  }
})

Ahora puede acceder a él en cualquier lugar de su aplicación Vue, así como en cualquier lugar donde importe Vue:

<template>
  <div class="my-component">My Component</div
</template>

<script>
export default {
  name: 'MyComponent',
  data () {
    return {
      data: []
    }
  },
  async created () {
    const response = await this.$api.find({ resource: 'tasks', query: { page: 2 } })

    this.data = response.data
  }
}
</script>

o:

// actions.js from Vuex
import Vue from 'vue'

export async function fetchTasks ({ commit }) {
  const response = await Vue.$api.find({ resource: 'tasks', query: { page: 2 } })

  commit('SAVE_TASKS', response.data)

  return response
}

Espero que esto ayude.


3

Creo que para su pregunta simple, la respuesta podría ser cualquier módulo ES6 que contenga funciones (equivalente a los métodos en clase en ANgular) e importarlos directamente en componentes utilizando importaciones y exportaciones de ES6. No existen tales servicios que puedan inyectarse en componentes.


1

Puede crear su propio servicio donde puede colocar todas sus llamadas al servidor HTTP y luego importarlo a los componentes donde desea usarlos.

Lo mejor es hacer uso de Vuex para aplicaciones complejas de administración de estado porque en Vuex puede manejar todas las llamadas asíncronas a través de acciones que siempre se ejecutan de forma asincrónica y luego cometen la mutación una vez que tenga el resultado.La mutación interactuará directamente con el estado y se actualizará de una manera inmutable (lo que se prefiere). Este es un enfoque con estado.

También hay otros enfoques. Pero estos son los que sigo en mi código.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.