DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Enterprise AI Trend Report: Gain insights on ethical AI, MLOps, generative AI, large language models, and much more.

2024 Cloud survey: Share your insights on microservices, containers, K8s, CI/CD, and DevOps (+ enter a $750 raffle!) for our Trend Reports.

PostgreSQL: Learn about the open-source RDBMS' advanced capabilities, core components, common commands and functions, and general DBA tasks.

AI Automation Essentials. Check out the latest Refcard on all things AI automation, including model training, data security, and more.

Related

  • Building Micro-Frontends With Vue and Reusable Components
  • Validation Forms in Vue.js Apps Using Vuelidate library
  • Are Your ELT Tools Ready for Medallion Data Architecture?
  • Why and How to Transition to SaaS Cloud Enterprise Applications

Trending

  • Code Complexity in Practice
  • Spring Boot 3.2: Replace Your RestTemplate With RestClient
  • Types of Data Breaches in Today’s World
  • Building Safe AI: A Comprehensive Guide to Bias Mitigation, Inclusive Datasets, and Ethical Considerations
  1. DZone
  2. Coding
  3. JavaScript
  4. 4 AJAX Patterns for Vue.js Apps

4 AJAX Patterns for Vue.js Apps

By 
Anthony Gore user avatar
Anthony Gore
DZone Core CORE ·
Updated Feb. 04, 20 · Tutorial
Like (7)
Save
Tweet
Share
15.7K Views

Join the DZone community and get the full member experience.

Join For Free

If you ask two Vue.js developers "what's the best way to use AJAX in an app?" you'll get three different opinions.

Vue doesn't provide an official way of implementing AJAX, and there are a number of different design patterns that may be used effectively. Each comes with its own pros and cons and should be judged based on the requirements. You may even use several simultaneously!

In this article, I'll show you four places you can implement AJAX in a Vue app:

  1. Root instance.
  2. Components.
  3. Vuex actions.
  4. Route navigation guards.

I'll explain each approach, give an example, and cover the pros and cons as well.

1. Root Instance

With this architecture, you issue all your AJAX requests from the root instance and store all state there too. If any subcomponents need data, it will come down as props. If subcomponents need refreshed data, a custom event will be used to prompt the root instance to request it.

Example:

JavaScript
 




x
22


 
1
new Vue({
2
  data: {
3
    message: ''
4
  },
5
  methods: {
6
    refreshMessage(resource) {
7
      this.$http.get('/message').then((response) {
8
        this.message = response.data.message;
9
      });
10
    }
11
  }
12
})
13

          
14
Vue.component('sub-component', {
15
  template: '<div>{{ message }}</div>',
16
  props: [ 'message' ]
17
  methods: {
18
    refreshMessage() {
19
      this.$emit('refreshMessage');
20
    }
21
  }
22
});



Pros

  • Keeps all your AJAX logic and data in one place.
  • Keeps your components "dumb" so they can focus on presentation.

Cons

  • A lot of props and custom events are needed as your app expands.
You may also like: Creating a Real-Time Data Application Using Vue.js.

2. Components

With this architecture, components are responsible for managing their own AJAX requests and state independently. In practice, you'll probably want to create several "container" components that manage data for their own local group of "presentational" components.

For example, filter-list might be a container component wrapping filter-input and filter-reset, which serve as presentational components. filter-list would contain the AJAX logic, and would manage data for all the components in this group, communicating via props and events.

See Presentational and Container Components by Dan Abramov for a better description of this pattern.

To make implementation of this architecture easier, you can abstract any AJAX logic into a mixin, then use the mixin in a component to make it AJAX-enabled.

JavaScript
 
xxxxxxxxxx
1
22


 
1
let mixin = {
2
  methods: {
3
    callAJAX(resource) {
4
      ...
5
    }
6
  }
7
}
8

          
9
Vue.component('container-comp', {
10
  // No meaningful template, I just manage data for my children
11
  template: '<div><presentation-comp :mydata="mydata"></presentation-comp></div>', 
12
  mixins: [ myMixin ],
13
  data() {
14
    return { ... }
15
  },
16

          
17
})
18

          
19
Vue.component('presentation-comp', {
20
  template: <div>I just show stuff like {{ mydata }}</div>,
21
  props: [ 'mydata' ]
22
})



Pros

  • Keeps components decoupled and reusable.
  • Gets the data when and where it's needed.

Cons

  • Not easy to communicate data with other components or groups of components.
  • Components can end up with too many responsibilities and duplicate functionality.

3. Vuex Actions

With this architecture, you manage both state and AJAX logic in your Vuex store. Components can request new data by dispatching an action.

If you implement this pattern, it's a good idea to return a promise from your action so you can react to the resolution of the AJAX request, e.g. hide the loading spinner, re-enable a button, etc.

JavaScript
 




xxxxxxxxxx
1
34


 
1
store = new Vuex.Store({
2
  state: {
3
    message: ''
4
  },
5
  mutations: {
6
    updateMessage(state, payload) {
7
      state.message = payload
8
    }
9
  },
10
  actions: {
11
    refreshMessage(context) {
12
      return new Promise((resolve) => {
13
        this.$http.get('...').then((response) => {
14
          context.commit('updateMessage', response.data.message);
15
          resolve();
16
        });
17
      });
18
    }
19
  }
20
});
21

          
22
Vue.component('my-component', {
23
  template: '<div>{{ message }}</div>',
24
  methods: {
25
    refreshMessage() {
26
      this.$store.dispatch('refeshMessage').then(() => {
27
        // do stuff
28
      });
29
    }
30
  },
31
  computed: {
32
    message: { return this.$store.state.message; }
33
  }
34
});



I like this architecture because it decouples your state and presentation logic nicely. If you're using Vuex, this is the way to go. If you're not using Vuex, this might be a good enough reason to.

Pros

  • All the pros of the root component architecture, without needing props and custom events.

Cons

  • Adds the overhead of Vuex.

4. Route Navigation Guards

With this architecture, your app is split into pages, and all data required for a page and its subcomponents is fetched when the route is changed.

The main advantage of this approach is that it really simplifies your UI. If components are independently getting their own data, the page will re-render unpredictably as component data gets populated in an arbitrary order.

A neat way of implementing this is to create endpoints on your server for each page e.g. /about, /contact etc, which match the route names in your app. Then you can implement a generic beforeRouteEnter hook that will merge all the data properties into the page component's data:

JavaScript
 




xxxxxxxxxx
1


 
1
import axios from 'axios';
2

          
3
router.beforeRouteEnter((to, from, next) => {
4
  axios.get(`/api${to.path}`).then(({ data }) => {
5
    next(vm => Object.assign(vm.$data, data))
6
  });
7
})



Pros

  • Makes the UI more predictable.

Cons

  • Slower overall, as the page can't render until all the data is ready.
  • Not much help if you don't use routes.

Bonus Pattern: Server-Render the First AJAX Call Into the Page

It’s not advisable to use AJAX to retrieve application state on the initial page load, as it requires an extra round-trip to the server that will delay your app from rendering.

Instead, inject initial application state into an inline script in the head of the HTML page so it’s available to the app as a global variable as soon as it’s needed.

HTML
 




xxxxxxxxxx
1
12


 
1
<html>
2
...
3
<head>
4
  ...
5
  <script type="text/javascript">
6
   window.__INITIAL_STATE__ = '{ "data": [ ... ] }';
7
  </script>
8
</head>
9
<body>
10
  <div id="app"></div>
11
</body>
12
</html>



AJAX can then be used more appropriately for subsequent data fetches.

If you're interested in learning more about this architecture, check out my article Avoid This Common Anti-Pattern In Full-Stack Vue/Laravel Apps.

Thanks to React AJAX Best Practices by Andrew H. Farmer for inspiration.

AJAX app Data (computing) Vue.js Architecture

Published at DZone with permission of Anthony Gore, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Building Micro-Frontends With Vue and Reusable Components
  • Validation Forms in Vue.js Apps Using Vuelidate library
  • Are Your ELT Tools Ready for Medallion Data Architecture?
  • Why and How to Transition to SaaS Cloud Enterprise Applications

Partner Resources


Comments

ABOUT US

  • About DZone
  • Send feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: