ChatGPT解决这个技术问题 Extra ChatGPT

Vue.js:定义一个服务

我正在将 Vue.js 视为 Angular 的替代品,到目前为止我真的很喜欢它。为了感受一下,我将现有的 Angular 项目重构为 Vue 项目。我正处于需要与我的 REST API 通信的地步。

在 Angular 中,我曾经为此定义一个服务,该服务被注入到每个需要它的控制器中。据我所知,Vue 似乎并不知道“服务”结构。这在 Vue 中如何实现?

我考虑过 vue-resource,但据我所知,它仅适用于 http 功能。因为我也使用 jQuery,所以这已经过时了。

例子:

我有 vueComponent1vueComponent2。两者都需要访问相同的 REST 资源。为了处理这个问题,我需要一个中央服务,这两个组件都可以用于对 REST 资源的请求。 Angular 有“服务”组件,它正是这样做的。 Vue 没有。

提供您需要的具体示例。 http 足以与 REST 通信
看看 vue-resource:github.com/vuejs/vue-resource

M
Marc

来自 Vue.js 文档。

Vue.js 本身并不是一个成熟的框架——它只专注于视图层。

作为一个专注于 MVC 中 V 的库,它不提供服务之类的东西。

您是否在使用某种模块加载器,例如 Browserify 或 Webpack?然后你可以利用 ES6 的模块系统自己创建一个服务。您所要做的就是创建一个由这个新模块导出的纯 JavaScript 类。

一个示例可能如下所示:

export default class RestResource {

  sendRequest() {
    // Use vue-resource or any other http library to send your request
  }

}

在您的 vue 组件 1 和 2 中,您可以通过导入类来使用此服务。

import RestResource from './services/RestResource';

const restResourceService = new RestResource();

restResourceService.sendRequest();

感谢您的报价。这意味着视图和模型下方没有结构或任何东西。如果我想拥有一项服务,我需要构建自己的服务,例如使用纯 JS。
当我使用这个时,我得到了 movieslist.vue?1be4:38Uncaught TypeError: _resource.Resource is not a constructor...
您错过了与 Angular 背景所期望的显着差异。在这种情况下,“服务”被实例化了多次,而在共享服务注入中,只传递了一个实例
是的,您可以通过这种方式获得同一服务的多个实例。当它只执行 Ajax 请求时这不是问题(只是效率低下),但是当您将服务用于数据模型时,您需要在声明服务的地方实例化它,并且只导出实例。
如果您想要一个“Angular 风格”的单例服务,您可以简单地在您的应用程序的某处创建此类的一个实例,然后将其导出:export const restResourceService = new RestResource();,然后将其导入到您希望的任何位置。然而,这实际上是在为我们自己创建的问题创建一个解决方案——为什么不直接使用一个函数呢? export function sendRequest() { // Make the request } 最后,请注意,您甚至不一定需要一个库来发出 http 请求 - 根据您的项目要求,您可以简单地使用 JavaScript fetch API。
M
Max Oriola

您可以为您的服务导出一个类的实例:

export default new class {
   ...
}

在您的组件或任何其他地方,您可以导入实例,并且您将始终获得相同的实例。这样,它的行为类似于注入的 Angular 服务,但不使用 this

import myService from '../services/myservice';

Vue.component('my-component', {
  ...
  created: function() {
    myService.oneFunction();
  }
  ...
})

C
Community

来自 Building Large-Scale Apps 上的 Vue.js 文档。

社区贡献了 vue-resource 插件,它提供了一种使用 RESTful API 的简单方法。您还可以使用任何您喜欢的 Ajax 库,例如 $.ajax 或 SuperAgent。

Vue 不要求您遵循特定的架构,因为它仅指 MVC 或 MVVM 架构中的 View 层。正如 @Marchis answer 中所说,一个好的做法是使用像 Browserify 或 Webpack 这样的模块加载器,这样您就可以在单独的文件中创建“服务”,并将它们导入到您需要的地方。使用 vue-cli 使用模块加载器来构建您的应用程序非常容易。

事实上,我个人非常喜欢基于组件的应用程序的 Flux 架构,那么我建议您看看 Vuex,这是一种受 Flux 启发的应用程序架构,专为管理 Vue.js 应用程序内部的状态而设计。

这样,您可以创建使用 vue-resource 来请求您的 API 的操作,然后您可以在数据到达时调度 Mutations,所有需要该数据的组件已经绑定到全局状态,自动做出反应。换句话说,您的组件本身不需要调用服务,它们只需对 Mutations 调度的状态更改做出反应。


请注意,不再推荐使用 vue-resource。 source
查看详细信息:Retiring vue-resource 由 Evan You 撰写
Axios 目前是推荐使用的插件,而不是 vue-resource。
A
Alexander

你在这个问题中有一些很好的答案What's the equivalent of Angular Service in VueJS?

正如@Otabek Kholikov 所说的那样-您有4个选择:

无状态服务:那么您应该使用 mixins 有状态服务:使用 Vuex 导出服务并从 vue 代码中导入任何 javascript 全局对象

在我的项目中,我更喜欢 (4)。它为我提供了最大的灵活性,并且只有我需要的实现(例如,我不带 Vuex,也不应该严格遵守它的规则,也没有“魔法”——所有代码都是我的)。您在我上面提到的 Question 中有一个实施示例。


t
tony19

如果您不使用模块加载器,则可以定义自定义 plugin。一些示例代码:

var myPlugin = {
        install: function (Vue, options) {
            //private
            var myPrivateProperty = 'Private property';

            //instance properties and methods
            Vue.prototype.$myPublicProperty = 'Public Property';

            Vue.prototype.$myAddedMethod = function () {
                return myPrivateProperty;
            };
            Vue.prototype._getData = function (url) {
                return url;
            };

            //static properties and methods
            Vue.myStaticProperty = 'My static prop';
            Vue.myStaticMethod = function () {
                console.log('in');
            }
        }
    };

    Vue.use(myPlugin);

    new Vue({
        el: '#app',
        created: function () {
            //using instance
            console.log(this.$myAddedMethod());
            console.log('my get data: ' + this._getData('some url'));
            console.log(this.$myPublicProperty);

            //using static
            console.log(Vue.myStaticProperty);
            Vue.myStaticMethod();
        }
    });

也可以插入其他库,this post展示了如何插入axios.js


请注意,这将使您的服务可以从任何组件访问,并且按照这种逻辑,如果您使用 Vue 路由器,尤其是在静态站点生成器上,它将可以从每个页面访问。在极少数的极端情况下,您可能还不希望服务被实例化,因此您必须找出一种不同的方式来管理此类服务。这样做的原因是,如果您的服务包含任何对象并且您的模板在代码中引用此类对象,则这些对象甚至需要在“创建”生命周期方法之前进行实例化(您可以在根元素上使用 v-if 来控制它)。
@OzzyTheGiant 他说的,当然。自从 Blazor 出现以来,还没有处理过 Vue。 (不是赞助评论:P)
W
Wallace Maxters

您可以将 vue 资源全局配置为

Vue.http.options.root = "your base url"

现在在每次 http 调用中,您都可以简单地通过资源名称调用 -

this.$http.get('');
this.$http.get('users')

w
wolframhempel

您可以在创建 Vue 实例时指定 Vue-Instance 特定服务

new Vue({
    el: '#app-container',
    myService: new MyService()
})

并从您的组件中访问它们

this.$root.$options.myService.doStuff()

P
Pascal R.

2022年的答案

对于有状态服务,使用内置的 Vue 状态管理:https://vuejs.org/guide/scaling-up/state-management.html

或 Pinia(以前的 Vuex)用于高级用例:https://pinia.vuejs.org/