What's the equivalent of Angular Service in Vu

2019-01-16 04:02发布

I want to put all my functions that talk to the server and fetch data into a single reusable file in VueJS.

Plugins don't seem to be the best alternative. Template less components..?

5条回答
祖国的老花朵
2楼-- · 2019-01-16 04:31

There are 4 ways:

  • Stateless service: then you should use mixins
  • Statefull service: use Vuex
  • Export service and import from a vue code
  • any javascript global object
查看更多
迷人小祖宗
3楼-- · 2019-01-16 04:35

I suggest creating an API Provider that you can access from anywhere in your app.

Simply create a src/utils folder and inside of it a file called api.js.

In it, export your wrapper that knows how to communicate with your API as an object or a ES6 static class (I prefer how the latter looks and works if you're not afraid of classes). This provider can use any HTTP request library that you like and you can easily swap it later by changing a single file (this one) instead of hunting down the whole codebase. Here's an example of using axios, assuming we have a REST API available at api.example.com/v1 that uses 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
})

Next, in your main.js file or wherever else you bootstrap the Vue app, do the following:

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

Vue.$api = api

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

Now you can access it anywhere in your Vue app as well as anywhere you import Vue itself:

<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>

or:

// 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
}

Hope this helps.

查看更多
成全新的幸福
4楼-- · 2019-01-16 04:42

I'm using Vue Resource mostly.

1.I create new file where I do connection to API endpoint using Vue.http.xxx.So let's say we have endpoint that output the posts.Create new directory in your project, I call it services, and then create file called PostsService.js - content looks like this:

import Vue from 'vue'

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

Then I go to component where I want use this service, and import it

import PostsService from '../services/PostsService'

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

For more info about this approach, feel free to check my repo on GitHub https://github.com/bedakb/vuewp/tree/master/public/app/themes/vuewp/app

查看更多
狗以群分
5楼-- · 2019-01-16 04:47

I am using axios as HTTP client for making api calls, I have created a gateways folder in my src folder and I have put files for each backend, creating axios instances, like following

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

Now in your component, You can have a function which will fetch data from the api like following:

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

As I assume you want to re-use this method in multiple components, you can use mixins of vue.js:

Mixins are a flexible way to distribute reusable functionalities for Vue components. A mixin object can contain any component options. When a component uses a mixin, all options in the mixin will be “mixed” into the component’s own options.

So you can add a method in mixin and it will be available in all the components, where mixin will be mixed. See following example:

// 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')
  }
})
查看更多
手持菜刀,她持情操
6楼-- · 2019-01-16 04:49

I think for your simple question the answer could be any ES6 module containing functions (equivalent to methods in class in ANgular) and directly importing them in components using ES6 imports and exports. There are no such services that could be injected in components.

查看更多
登录 后发表回答