Tutorial hero
Lesson icon

Learning Vue for Ionic/Angular Developers – Part 3

Originally published November 28, 2017 Time 8 mins

Learning Vue for Ionic/Angular Developers – Part 1: Vue Syntax vs Angular Syntax
Learning Vue for Ionic/Angular Developers – Part 2: Navigation
Learning Vue for Ionic/Angular Developers – Part 3: Services/Providers and HTTP Requests (this tutorial)
Learning Vue for Ionic/Angular Developers – Part 4: Storing Data with Local Storage, IndexedDB, WebSQL, and SQLite
Learning Vue for Ionic/Angular Developers – Part 5: Building with Cordova and the Vue CLI

When learning a new framework, especially if you have primarily worked with a single framework previously, it is natural to attempt to project your understanding of the principles of one framework onto the other.

As I have mentioned in the previous articles, Angular is an opinionated framework that provides everything out of the box and, more or less, has a “right” way to do things. Vue is much less opinionated, not everything is provided out of the box and you are given more flexibility to structure your applications in the way you wish. Angular is designed to handle every aspect of your application, Vue is mostly just concerned with displaying your application.

In this tutorial, we are going to look at how to create “services” or “providers” in Vue that pull in some data via an HTTP request. However, this is a case of projecting Angular concepts onto Vue, and we’ll talk in a little more detail about this. We will be building an example that pulls in some posts from the Reddit API, just like we did with Ionic/Angular in Using Http to Fetch Remote Data from a Server in Ionic.

Getting Started

We’ve covered the basics of getting a Vue application set up with Ionic in the previous tutorials, so we are just going to quickly run through the setup steps here. If you are not familiar with these steps, I would recommend reading the previous two tutorials before continuing.

Create a new Vue project

vue init webpack service-http-example

Run the following commands to set up and run your project:

cd service-http-example
npm install
npm run dev

Add Ionic to the application by modifying index.html to reflect the following:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1.0" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
    />
    <meta name="format-detection" content="telephone=no" />
    <meta name="msapplication-tap-highlight" content="no" />
    <title>service-example</title>
  </head>
  <body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
    <script src="https://unpkg.com/@ionic/core@0.0.2-20/dist/ionic.js"></script>
  </body>
</html>

Services in Angular vs Vue

When it comes to pulling in data from some website to an Ionic/Angular application we would generally create a service/provider that handles the grunt work for us, and we would use the built-in Http API to fetch the data. We would then inject that provider into the component we want to use it in, and access the function we created.

There are not really any decisions to be made here. However, when it comes to doing the same thing with Vue/Ionic, things are not necessarily so pre-determined.

Coming from an Angular background we might want to create a “provider” in Vue, and then use whatever Vue’s version of “Http” is to fetch the data. But there is no concept of a “provider” or “service” or “injectable” in Vue, and there is no default library for HTTP requests. These are not things that the Vue framework concerns itself with.

So… how do we do it? You can do whatever you want, but of course, there are some more common norms/conventions/best-practices that we can follow. We are going to be taking an “Angular-esque” approach and creating something akin to a normal “provider” that you might use in Angular.

Creating a Service/Provider in Vue

We are going to create a services folders, and inside of that, we are going to manually create our services – in this case, we are just going to have a single reddit service.

Create a folder at src/services

Create a new file in that folder called reddit.js and add the following:

import Vue from 'vue';

export default {
  getPosts() {
    // do something
    return [];
  },
};

As you can see, the idea is more or less the same as in Angular, except that we aren’t using Angular specific terminology/syntax like @Injectable, we are just using plain ES6 syntax. By exporting functions in this file, we will be able to import them elsewhere to use.

Modify the script in src/components/HelloWorld.vue to reflect the following:

import RedditService from '../services/reddit';

export default {
  name: 'HelloWorld',
  data() {
    return {
      posts: [],
    };
  },
  created() {
    this.posts = RedditService.getPosts();
  },
};

Just like a provider would be imported in Angular, we also import the service we created here – unlike in Angular, however, there are no additional steps required. Once we have imported the service, we can access its methods through whatever we named the import. In this case, we use a created lifecycle hook which will run as soon as the component is created, and it will assign the result of the method to this.posts.

Making HTTP Requests

We have our service set up, but currently, it doesn’t do anything. We need to modify it so that it fetches some data from Reddit for us. Once again, Vue is not concerned with the ins and outs of your application, and it does not provide a “Vue way” to make an HTTP request.

Instead, we will need to install a library to help us make requests (or, if you prefer, you could just use vanilla JavaScript). Two popular libraries are vue-resource which was previously the “de facto” library, and axios. If you want to use either of these, then you will need to add them to your Vue project – we will be using vue-resource.

Run the following command to install vue-resource:

npm install vue-resource --save

Modify src/main.js to reflect the following:

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue';
import App from './App';
import router from './router';
import VueResource from 'vue-resource';

Vue.config.productionTip = false;

Vue.config.ignoredElements = [
  'ion-app',
  'ion-header',
  'ion-navbar',
  'ion-title',
  'ion-content',
  'ion-button',
  'ion-list',
  'ion-item',
];

Vue.use(VueResource);

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  template: '<App/>',
  components: { App },
});

After installing vue-resource, we have imported it into the main.js file, and then we have set the application to use it with the following line:

Vue.use(VueResource);

Note that we have also added the ignoredElements so that our use of Ionic components won’t cause any problems. Now that we have a way to make HTTP requests, we can modify our service.

Modify src/services/reddit.js to reflect the following:

import Vue from 'vue';

export default {
  getPosts() {
    return Vue.http.get(
      'https://www.reddit.com/r/gifs/top/.json?limit=20&sort=hot'
    );
  },
};

Modify the script in src/components/HelloWorld.vue to reflect the following:

import RedditService from '../services/reddit';

export default {
  name: 'HelloWorld',
  data() {
    return {
      posts: [],
    };
  },
  created() {
    RedditService.getPosts().then((response) => {
      this.posts = response.body.data.children;
    });
  },
};

Our service will now fetch the data from the gifs subreddit, and when the created lifecycle hook is triggered, it will assign the result of that to our posts member variable. Now we can modify our template to display the data that we get back.

Modify the template in src/components/HelloWorld.vue to reflect the following:

<template>
  <ion-app>
    <ion-header>
      <ion-navbar>
        <ion-title>REDDIT!</ion-title>
      </ion-navbar>
    </ion-header>

    <ion-content>
      <ion-list>
        <ion-item v-for="post in posts" v-bind:key="post.data.id">
          {{post.data.title}}
        </ion-item>
      </ion-list>
    </ion-content>
  </ion-app>
</template>

If you were to take a look at this in your browser now, you should see something like this:

Reddit API in Vue

Summary

An important thing to keep in mind when learning Vue, especially coming from an Angular background, is to remember that although there are many similarities, they are different frameworks with different approaches and you shouldn’t project what you know about Angular onto Vue.

Learn to build modern Angular apps with my course