อะไรเทียบเท่ากับ Angular Service ใน VueJS?


99

ฉันต้องการใส่ฟังก์ชันทั้งหมดของฉันที่พูดคุยกับเซิร์ฟเวอร์และดึงข้อมูลลงในไฟล์ที่ใช้ซ้ำได้ใน VueJS

ปลั๊กอินดูเหมือนจะไม่ใช่ทางเลือกที่ดีที่สุด แม่แบบส่วนประกอบน้อย .. ?

คำตอบ:


61

มีทั้งหมด 4 วิธี:

  • บริการไร้สัญชาติ: คุณควรใช้มิกซ์อิน
  • บริการสถานะ: ใช้ Vuex
  • บริการส่งออกและนำเข้าจากรหัส vue
  • วัตถุส่วนกลาง javascript ใด ๆ

6
ดูเหมือนอึดอัดมากที่จะพยายามและปฏิบัติตามวิธีการเรียกที่แปลกประหลาดของ Vuex ด้วยตัวอักษรสตริงสำหรับบริการเมื่อคุณสามารถสร้างคลาส TypeScript / JS ที่มีสถานะและตรรกะสำหรับมัน? คุณจะใช้ stateful class เป็นบริการภายใน Vue ได้อย่างไร?
Douglas Gaskell

VueX ไม่ใช่วิธีแก้ปัญหาที่ดีสำหรับส่วนหน้าที่ต้องใช้บริบทอื่นที่ไม่ใช่ส่วนประกอบ / เพื่อแชร์กับหลาย ๆ องค์ประกอบ บริการ Angular (2.x +) เป็นตัวอย่างที่สมบูรณ์แบบของวิธีการทำสิ่งนี้ให้สำเร็จโดยไม่จำเป็นต้องมีความซับซ้อนและวิศวกรรมมากเกินไป
Kody

37

ฉันใช้axiosเป็นไคลเอนต์ HTTP ในการโทร api ฉันได้สร้างgatewaysโฟลเดอร์ในsrcโฟลเดอร์ของฉันและฉันได้ใส่ไฟล์สำหรับแบ็กเอนด์แต่ละตัวสร้างอินสแตนซ์ axiosดังต่อไปนี้

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

ตอนนี้ในส่วนประกอบของคุณคุณสามารถมีฟังก์ชันที่จะดึงข้อมูลจาก api ดังต่อไปนี้:

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

ตามที่ฉันคิดว่าคุณต้องการใช้วิธีนี้ซ้ำในหลาย ๆ องค์ประกอบคุณสามารถใช้mixinsของ vue.js:

Mixins เป็นวิธีที่ยืดหยุ่นในการกระจายฟังก์ชันที่ใช้ซ้ำได้สำหรับส่วนประกอบ Vue ออบเจ็กต์ mixin สามารถมีตัวเลือกส่วนประกอบใด ๆ เมื่อคอมโพเนนต์ใช้มิกซ์อินตัวเลือกทั้งหมดในมิกซ์อินจะถูก "ผสม" ลงในตัวเลือกของคอมโพเนนต์

ดังนั้นคุณสามารถเพิ่มวิธีการใน mixin และจะมีอยู่ในส่วนประกอบทั้งหมดโดยจะผสม mixin ดูตัวอย่างต่อไปนี้:

// 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
คุณจะอัปเดต X-Auth-Token ของ myApi.js อย่างไรเมื่อผู้ใช้จะเข้าสู่ระบบ
Amarjit Singh

3
โดยปกติจะไม่ใช่ค่าคงที่
Amarjit Singh

30

ฉันใช้ Vue Resource เป็นส่วนใหญ่

1. ฉันสร้างไฟล์ใหม่ที่ฉันเชื่อมต่อกับปลายทาง API โดยใช้Vue.http.xxxสมมติว่าเรามีปลายทางที่ส่งออกโพสต์สร้างไดเร็กทอรีใหม่ในโปรเจ็กต์ของคุณฉันเรียกมันว่าservicesแล้วสร้างไฟล์ชื่อPostsService.js- เนื้อหามีลักษณะดังนี้:

import Vue from 'vue'

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

จากนั้นฉันไปที่ส่วนประกอบที่ฉันต้องการใช้บริการนี้และนำเข้า

import PostsService from '../services/PostsService'

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

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับแนวทางนี้โปรดตรวจสอบ repo ของฉันบน GitHub https://github.com/bedakb/vuewp/tree/master/public/app/themes/vuewp/app


7
ตาม Evan You Vue-Resource จะเลิกใช้งานและแนะนำ Axios แทน อ่านบทความของเขา ฉันชอบวิธีการของคุณซึ่งให้ความรู้สึกเหมือนเชิงมุม 2 มากขึ้น
รหัส

@noypee VueResource ยังคงใช้งานได้ แต่ไม่เป็นไรใช้สิ่งที่คุณต้องการมันจะเป็นแนวทางเดียวกันกับ Axios
Belmin Bedak

1
ใช่ Vue2 จะยังคงรองรับ vue-resource เช่นกันตามบทความของเขา
เขียนโค้ดเมื่อ

2
นี่เป็นสิ่งที่ดีมาก แต่จะทดสอบส่วนประกอบดังกล่าวด้วย mock-PostsService ได้อย่างไร?
Shrike

@noypee, Vue ทรัพยากรไม่ได้ถูกเกษียณ - อีวานบอกว่าเขาเป็นเพียงการ"ถอนตัวออกจากสถานะคำแนะนำอย่างเป็นทางการ" เขาชี้แจงเพิ่มเติมว่าเหตุใดทีมของเขาจึงสรุปว่าไม่จำเป็นต้องมีห้องสมุด AJAX อย่างเป็นทางการอีกต่อไป บทความที่เชื่อมโยงอธิบายได้ดี และควรสังเกตว่า vue-resource ยังคงได้รับการดูแลอย่างแข็งขันและเป็นตัวเลือกที่ทำงานได้อย่างสมบูรณ์แบบ
Squidbe

8

ฉันขอแนะนำให้สร้างผู้ให้บริการ API ที่คุณสามารถเข้าถึงได้จากทุกที่ในแอปของคุณ

เพียงสร้างsrc/utilsโฟลเดอร์และภายในไฟล์ชื่อapi.js.

ในนั้นส่งออกกระดาษห่อหุ้มของคุณที่รู้วิธีสื่อสารกับ API ของคุณเป็นวัตถุหรือคลาสแบบคงที่ ES6 (ฉันชอบรูปลักษณ์และการทำงานแบบหลังถ้าคุณไม่กลัวคลาส) ผู้ให้บริการรายนี้สามารถใช้ไลบรารีคำขอ HTTP ใดก็ได้ที่คุณต้องการและคุณสามารถสลับได้อย่างง่ายดายในภายหลังโดยการเปลี่ยนไฟล์เดียว (ไฟล์นี้) แทนการค้นหาโค้ดเบสทั้งหมด นี่คือตัวอย่างของการใช้ axios โดยสมมติว่าเรามี REST API ที่api.example.com/v1ใช้ 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
})

ถัดไปในmain.jsไฟล์ของคุณหรือที่ใดก็ตามที่คุณบูตสแตรปแอป Vue ให้ทำดังต่อไปนี้:

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

Vue.$api = api

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

ตอนนี้คุณสามารถเข้าถึงได้ทุกที่ในแอป Vue ของคุณและทุกที่ที่คุณนำเข้า 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>

หรือ:

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

หวังว่านี่จะช่วยได้


3

ฉันคิดว่าสำหรับคำถามง่ายๆของคุณคำตอบอาจเป็นโมดูล ES6 ใด ๆ ที่มีฟังก์ชัน (เทียบเท่ากับวิธีการในคลาสใน ANgular) และนำเข้าโดยตรงในส่วนประกอบโดยใช้การนำเข้าและส่งออก ES6 ไม่มีบริการดังกล่าวที่สามารถฉีดเข้าไปในส่วนประกอบได้


1

คุณสามารถสร้างบริการของคุณเองโดยที่คุณสามารถเรียกใช้เซิร์ฟเวอร์ HTTP ทั้งหมดของคุณจากนั้นนำเข้าสู่คอมโพเนนต์ที่คุณต้องการใช้

วิธีที่ดีที่สุดคือการใช้ Vuex สำหรับแอปพลิเคชันการจัดการสถานะที่ซับซ้อนเนื่องจากใน Vuex คุณสามารถจัดการการเรียกแบบ async ทั้งหมดผ่านการดำเนินการที่ทำงานแบบอะซิงโครนัสเสมอจากนั้นจึงทำการกลายพันธุ์เมื่อคุณได้ผลลัพธ์แล้วการกลายพันธุ์จะโต้ตอบกับสถานะโดยตรงและจะอัปเดต ในลักษณะที่ไม่เปลี่ยนรูป (ซึ่งเป็นที่ต้องการ) นี่เป็นวิธีการที่เป็นรัฐ

มีแนวทางอื่นเช่นกัน แต่นี่คือสิ่งที่ฉันปฏิบัติตามในรหัสของฉัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.