The comparison between using multiple Vue.js instances and components, and implementing Ajax tabs

I am looking to incorporate ajax tabs using vue js. Each tab will need an ajax request to fetch both the template and data from an api.

Here is an example of the tabs:

<div id="tabs">
  <ul class="nav nav-tabs">
    <li class="active"><a href="#tab1" role="tab" data-toggle="tab">Tab1</a></li>
    <li><a href="#tab2" ajax-url="/tab2" role="tab" data-toggle="tab">Tab2</a></li>
    <li><a href="#tab3" ajax-url="/tab3" role="tab" data-toggle="tab">Tab3</a></li>
    <li><a href="#tab4" ajax-url="/tab4" role="tab" data-toggle="tab">Tab4</a></li>
  </ul>

  <div class="tab-content">
    <div role="tabpanel" class="tab-pane active" id="tab1"></div>
    <div role="tabpanel" class="tab-pane" id="tab2"></div>
    <div role="tabpanel" class="tab-pane" id="tab3"></div>
    <div role="tabpanel" class="tab-pane" id="tab4"></div>
  </div>
</div>

<script>
$('#tabs').on('shown.bs.tab', function (event) {
   var url = event.target.getAttribute("ajax-url");
   // fetch template and data..
   // init vue instance for the new tab
})
</script>

What would be the most effective way to integrate vue into this setup? Should I create separate vue instances for each tab, or use components? Additionally, I require the ability to preload some of the tabs.
Given that I need to initialize the vue instances on demand, I am uncertain about the best approach to handle this. In angular, I would define ng-controller for each tab. However, with vue.js it seems there may not be a standardized project architecture.

Answer №1

Utilize vue-router for organizing tabs.

Each tab will load a distinct View/Component when activated, leveraging the preloaded code in the vue.js bundle file.

The use of Vue Lifecycle hooks, like created and mounted, is commonplace for setting up or fetching additional data in each View.

It seems that your scenario is coherent enough to be managed by a single vue instance without the need for jQuery/AJAX.

If there are significant variations in your use-cases, it might be more efficient to construct multiple separate components, each compiled into their own JS file (typically achieved with Webpack's multiple 'entry' configuration).

UPDATE

You can bundle Vue components using the CLI; refer to: Compile .vue file into .js file without webpack or browserify

Note that each Component can mount a separate tab using the el attribute, similar to Angular's 'ng-controller' directive:

new Vue({
  el: '#tab1',
  data () {
    return {
      obj
    }
  }
})

However, attempting to control Vue instances externally from Vue (e.g., using jQuery) is generally discouraged.

If you opt for Webpack, Bootstrap can still be utilized. There are various methods to integrate Bootstrap, personally recommending importing the SCSS. Keep exploring online resources to support your progress.

Answer №2

If you prefer not to use the vue-router, it's recommended to utilize separate Vue instances. However, this approach may lead to memory leaks and other issues. To mitigate these issues, ensure that when making an AJAX request upon clicking a tab, you first destroy the current Vue instance before adding data to the DOM.


let app = new Vue({
    el: '#app',
})
// perform other actions
$.ajax({
    // ajax settings
    success: function(data){
        // ensure to destroy the old Vue instance here to prevent any potential issues
        app.$destroy()
        $('body').html(data);
    }
})

A more efficient solution would be to create a small JavaScript plugin. This plugin can handle AJAX requests when a link is clicked, fetch the data, and update the page while ensuring to destroy the previous Vue instance. Additionally, you can implement callbacks for loading indicators like page loaders.

In one of my projects, I implemented a jQuery AJAX-based plugin as shown below:


import $ from 'jquery';
import anime from 'animejs';

// Define Loader class
export let Loader = (function(window , document , undefined){

    // Constructor with initialization logic
    class Loader{

        constructor(options = null){
            // Configuration options
            this.options = Object.assign({ pageProgressBar : false , pageProgressBarDuraion: 2000 } , options);
            this.functions = [];
            this.xhr = null;
            this.routes = this.options.routes || [];

            window.addEventListener('load' , this.init.bind(this));
        }

        // Other methods and functionalities...

    }

    return Loader;

    // Private progress bar methods
    var $pageProgressBar = null;

    // Progress bar control functions

}(window , document , undefined));

The plugin comes equipped with progress bars and additional features which can be customized or removed according to your requirements. To implement the plugin, simply follow these steps:


window.Loader = new Loader({
    container: "#app-data",
})

Then, add the ajax-link attribute to the relevant tab links in your case. This will dynamically load content into the specified container. You can also utilize callback functions such as

Loader.beforeLoading = function(){
            app.$destroy();
        }
for added functionality.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The usage of 'import.meta' is restricted to within modules and cannot be utilized outside of them

I am working on a project that involves Node + Express + Babel + ES6. Within this project, I have the following files: /package.json { "name": "test-backend", "version": "1.0.0", "description": " ...

Using a Gridview within a ModalPopUpExtender can trigger the ModalPopUpExtender to unexpectedly close

I am facing an issue with a gridview inside a ModalPopUpExtender. The grid view contains buttons for add, delete, and edit functions. However, when I click one of the buttons in the gridview, the popup automatically closes. I want the popup to close only w ...

Retrieving environmental information within a Vue component

I am trying to display information from my .env file, specifically the APP_NAME, in my components. For example, I want to greet users with Welcome to {{APP_NAME}}. UPDATE After referring to this documentation, I have updated my env file as follows: MIX ...

Synchronize numerous PouchDB databases with a single CouchDB database

After reading the PouchDB documentation, I learned that sync occurs between a local database and a remote CouchDB database. Currently, I am working on developing a native application that includes a unique local database for each user (multiple databases) ...

Troubleshooting: Dealing with Stack Overflow Error when using setInterval in Vue Programming

I am facing a stack overflow error while creating a timer using Vue, and I'm struggling to understand the root cause. Can someone provide insights on the following code: Here is my template structure: <span class="coundown-number"> { ...

How to define an index signature in Typescript that includes both mandatory and optional keys

I am on a quest to discover a more refined approach for creating a type that permits certain keys of its index signature to be optional. Perhaps this is a scenario where generics would shine, but I have yet to unlock the solution. At present, my construc ...

Managing conflicting eslint rules within the AirBNB configuration can be challenging, but here are some best

Hey all, I'm new to Vue and I'm attempting to create a POC. I've set up ESLint with the AirBNB configuration, but I've run into an issue. Here is the section of code where I'm encountering problems within my Axios call: .catch((er ...

Attempting to prevent redundant loading of a component repeatedly

Welcome to the Code Zone Incorporating Laravel 5.8 and Vue.js components for an enhanced user experience. Identifying the Problem Within the code structure, there exist 3 tabs. When Component 1 is selected, it loads successfully. Then when Component 2 i ...

transferring data through AJAX using the POST method

When attempting to utilize the POST method to send a variable containing a name to a server asynchronously, I encountered an error message: SyntaxError: JSON.parse: unexpected end of data at line 1 column 1 of the JSON data. Unfortunately, this error was n ...

Passport is implementing multistrategies for multiple authentications simultaneously

After configuring Passport.js to utilize multiple strategies, I encountered an issue: passport.authenticate(['bearer', 'facebook-token', 'google-token', 'linkedin-token'],function(err, user, info) ... Although it i ...

Issue encountered in Angularjs during upgrade process from version 1.2.27 to 1.4.7

Recently, I upgraded my app from using AngularJS 1.2.27 to version 1.4.7, but now I am encountering an error in the AngularJS file. SyntaxError: Unexpected token : (angular.js:12477) at Function (native) at Object.sd. ...

Steps to turn off a Material UI CSS class for an element universally

Utilizing the Material UI Typography element with the css class MuiTypography-h1, I am seeking to globally disable its usage throughout the entire codebase. <Typography variant="h1" sx={{ width: '100px', height: '55px ...

Understanding the Typescript Type for a JSON Schema Object

When working with JSON-schema objects in typescript, is there a specific type that should be associated with them? I currently have a method within my class that validates whether its members adhere to the dynamic json schema schema. This is how I am doing ...

Showing information from JSON in a pie chart utilizing chart.js

Recently, I started using chart.js for the first time and encountered a minor issue that has me stumped. My code is only displaying the labels without rendering the pie chart itself. I've been referencing examples from the chart.js documentation avai ...

Clicking on the initial link will in turn prompt clicks on the subsequent links

Can you please provide instructions on how to correctly simulate a click on the remaining links if a click is made on the first link? jQuery('a.one_num').click(function() { jQuery('a.two_num').click(); jQuery('a.three_num&ap ...

troubleshooting problems with AJAX calls and routing in Angular

I am a beginner with Angular and I recently completed a tutorial on Single Page Application development using templates imported from PHP files, along with Resource and Route modules. Below is the JavaScript code from my project: (function(){ var app ...

Executing a function within the same file is referred to as intra-file testing

I have two functions where one calls the other and the other returns a value, but I am struggling to get the test to work effectively. When using expect(x).toHaveBeenCalledWith(someParams);, it requires a spy to be used. However, I am unsure of how to spy ...

Using Bootstrap Multiselect and making AJAX GET requests with nested objects

I'm having difficulties with retrieving nested objects using $.ajax and dynamically populating Bootstrap Multiselect dropdown select options. This issue is similar to the ones discussed in the following Stack Overflow threads: Issue with Data returnin ...

How can I revert a date format using date-fns?

Greetings from Thailand! I have a question regarding the reverse formatting using date-fns. Is there a way to create a function that will change "saturday-9-september-2564" back to "2022-09-24" using date-fns? Any insights or methods on achieving this wo ...

What is the best way to bring in a variable initialized by an IIFE from a JavaScript file into a TypeScript class?

I'm currently working towards integrating the steelseries.js library (found at https://github.com/HanSolo/SteelSeries-Canvas) into a Grafana plugin built with React. It's quite a complex task, but I'm up for the challenge. Right now, my ma ...