Qual é o equivalente ao serviço Angular no VueJS?


95

Quero colocar todas as minhas funções que se comunicam com o servidor e buscam dados em um único arquivo reutilizável no VueJS.

Plugins não parecem ser a melhor alternativa. Molde menos componentes ..?

Respostas:


57

No total, existem 4 maneiras:

  • Serviço sem estado: então você deve usar mixins
  • Serviço com estado: use Vuex
  • Serviço de exportação e importação de um código vue
  • qualquer objeto global javascript

4
Parece muito estranho tentar aderir às esquisitices Vuex de chamar métodos com literais de string para serviços quando você poderia fazer uma classe TypeScript / JS que contenha o estado e a lógica para ela? Como você pode usar uma classe com estado como um serviço no Vue?
Douglas Gaskell

37

Estou usando axios como cliente HTTP para fazer chamadas API, criei uma gatewayspasta em minha srcpasta e coloquei arquivos para cada backend, criando instâncias de axios , como a seguir

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'
  }
})

Agora, em seu componente, você pode ter uma função que buscará dados da API como a seguir:

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

Como suponho que você queira reutilizar esse método em vários componentes, você pode usar mixins de vue.js:

Mixins são uma maneira flexível de distribuir funcionalidades reutilizáveis ​​para componentes Vue. Um objeto mixin pode conter qualquer opção de componente. Quando um componente usa um mixin, todas as opções do mixin serão “combinadas” com as opções do próprio componente.

Então você pode adicionar um método no mixin e ele estará disponível em todos os componentes, onde o mixin será misturado. Veja o seguinte exemplo:

// 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
como você atualizará o X-Auth-Token de myApi.js quando o usuário fizer login
Amarjit Singh

3
geralmente este não é um valor estático
Amarjit Singh

30

Estou usando principalmente o recurso Vue.

1. Eu crio um novo arquivo onde faço a conexão com o endpoint da API usando Vue.http.xxx. Então, digamos que temos um endpoint que produz os posts. Crie um novo diretório em seu projeto, eu o chamo servicese, em seguida, crio o arquivo chamado PostsService.js- o conteúdo se parece com isto:

import Vue from 'vue'

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

Então vou para o componente onde desejo usar este serviço e o 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 obter mais informações sobre essa abordagem, sinta-se à vontade para verificar meu repositório no GitHub https://github.com/bedakb/vuewp/tree/master/public/app/themes/vuewp/app


7
De acordo com Evan You, a Vue-Resource vai se aposentar e, em vez disso, recomenda a Axios. Leia o artigo dele , realmente gosto da sua abordagem, que parece mais angular 2
codamente

@noypee VueResource ainda funciona. Mas não importa usar o que quiser, seria exatamente a mesma abordagem com o Axios.
Belmin Bedak de

1
Sim, Vue2 continuará a acomodar vue-resource também de acordo com seu artigo
codamente

2
Isso é muito bom, mas como testar esse componente com o mock-PostsService?
Shrike

@noypee, vue-resource não está sendo aposentado - Evan afirmou que ele está apenas "aposentando-o do status de recomendação oficial" . Ele esclareceu ainda porque sua equipe concluiu que não havia mais a necessidade de uma biblioteca oficial AJAX. O artigo vinculado explica bem. E deve-se notar que o vue-resource ainda é mantido ativamente e uma opção perfeitamente viável.
squidbe

8

Eu sugiro criar um provedor de API que você possa acessar de qualquer lugar em seu aplicativo.

Simplesmente crie uma src/utilspasta e dentro dela um arquivo chamado api.js.

Nele, exporte seu wrapper que sabe como se comunicar com sua API como um objeto ou uma classe estática ES6 (eu prefiro como esta última parece e funciona se você não tem medo de classes). Este provedor pode usar qualquer biblioteca de solicitação de HTTP de sua preferência e você pode trocá-la facilmente mais tarde, alterando um único arquivo (este) em vez de procurar por toda a base de código. Aqui está um exemplo de uso de axios, assumindo que temos uma API REST disponível em 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
})

Em seguida, em seu main.jsarquivo ou onde quer que você inicialize o aplicativo Vue, faça o seguinte:

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

Vue.$api = api

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

Agora você pode acessá-lo em qualquer lugar em seu aplicativo Vue, bem como em qualquer lugar para importar o próprio 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>

ou:

// 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 isto ajude.


3

Eu acho que para sua pergunta simples, a resposta poderia ser qualquer módulo ES6 contendo funções (equivalente a métodos em classe em ANgular) e importando-as diretamente em componentes usando importações e exportações ES6. Não existem serviços que possam ser injetados em componentes.


1

Você pode fazer seu próprio serviço onde pode colocar todas as suas chamadas de servidor HTTP e, em seguida, importá-lo para os componentes onde deseja usá-los.

O melhor é usar o Vuex para aplicativos complexos de gerenciamento de estado porque no Vuex você é capaz de lidar com todas as chamadas assíncronas por meio de ações que sempre são executadas de forma assíncrona e, em seguida, confirmar a mutação assim que tiver o resultado. A mutação irá interagir diretamente com o estado e será atualizada de uma maneira imutável (que é preferível). Esta é uma abordagem com estado.

Existem outras abordagens também. Mas esses são os que sigo em meu código.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.