You have to use seperate Vue instances in case you don't want the vue-router
..
but it will cause some memory leaks some issues so to some this ..
when ever you will make an ajax request when a tab is clicked you have to first destroy the current Vue instance.. then add the data to the dom
let app = new Vue({
el: '#app',
})
// doo other stuff
$.ajax({
// ajax settings
success: function(data){
// here you should destroy the Old Vue instance otherwise it will make issues
app.$destroy()
$('body').html(data);
}
})
I would suggest you to make a small javascript plugin..
when a link is clicked it will take the url of the link perform an ajax request and serve the data to the page on every request it will fire a callback .. where you destory the old new Instance..
and for some kind of loader you can use another call back before ajax request to show the page loader or something..
I have used this technique in one of my project.. i'hv made a plugin with jquery ajax...
here it is...
import $ from 'jquery';
import anime from 'animejs';
export let Loader = (function(window , document , undefined){
class Loader{
constructor(options = null){
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));
}
init(){
if(this.options.container)
this.$container = $(this.options.container).length ? $(this.options.container) : $(document.body)
else
this.$container = $(document.body)
this.functions['popstate'] = this.onPopState.bind(this);
window.addEventListener('popstate' , this.functions['popstate'] );
this.functions['handleLinks'] = this.handleLinks.bind(this);
window.addEventListener('click' , this.functions['handleLinks']);
}
pushHistory(type , url){
var state = {url : url , type : type};
window.history.pushState(state , '' , url);
}
onPopState(e){
var state = e.state;
if(state == null)
return true;
this.loadUrl(state.url)
}
handleLinks(e){
if(!e.target.matches('[ajax-link]'))
return ;
e.preventDefault();
var url = e.target.href;
var self = this;
this.loadUrl(url).then(function(){
self.pushHistory('get' , url);
});
}
load(url)
{
let self = this;
return new Promise(function(resolve , reject){
self.loadUrl(url).then(function(){
self.pushHistory('get' , url);
resolve();
});
});
}
loadUrl(url){
var isError = true;
if(this.xhr)
{
isError = false;
if(this.options.onAbort)
this.options.onAbort();
this.xhr.abort();
if(this.options.pageProgressBar)
restartProgressBar();
this.xhr = null;
}
var route = this.getMatchingRoute(url);
if(route)
{
if(route.beforeLoad)
route.beforeLoad();
}
if(this.beforeLoading)
this.beforeLoading();
var self = this;
return new Promise(function(resolve , reject){
self.xhr = $.ajax({
url : url,
type: 'get',
cache : false,
beforeSend (xhr){
if(self.options.onLoading)
self.options.onLoading(xhr);
if(self.options.pageProgressBar)
startProgressBar( self.options.pageProgressBarDuration );
},
success (data){
self.$container.html(data);
self.xhr = null;
resolve();
if(route && route.afterLoad)
route.afterLoad();
if(self.options.onLoaded)
self.options.onLoaded(data);
if(self.options.pageProgressBar)
endProgressBar();
},
error (response){
if(response.response)
window.location = url;
},
});
});
}
reload(){
this.loadUrl(window.location.href);
}
getMatchingRoute(url){
if(this.routes)
{
for(let i = 0; i< this.routes.length ; i++)
{
var route = this.routes[i];
if(url.indexOf(route.route) >= 0 ){
return route;
}
};
}
return null;
}
destory(){
window.removeEventListener('popstate' , this.functions['popstate'] );
}
}
return Loader;
// Provate progressbar methods
var $pageProgressBar = null;
function restartProgressBar(){
$pageProgressBar.remove();
anime.remove($pageProgressBar[0]);
}
function startProgressBar( duration = 3000){
$pageProgressBar = $('<div>').addClass('page-progressbar')
$('body').append($pageProgressBar)
anime({
targets: $pageProgressBar[0],
width: '70%',
easing : 'easeInOutQuad',
duration : 3000
});
}
function endProgressBar(){
anime.remove($pageProgressBar[0]);
var $prog = $('.page-progressbar');
$prog.css({ width: '100%' , transition :".35s all" , 'webkit-transition' : ".35s all" });
setTimeout(()=>{
$prog.css({ opacity: '0'});
setTimeout( () => $pageProgressBar[0].remove() , 200);
},350);
}
}(window , document , undefined));
it has some progress bars and other things you can remove that modify it
now all you have to do is
window.Loader = new Loader({
// tell it the tag you want to put data in
container :"#app-data",
})
then add the ajax-link
attribute to any link in your case its tabs links
it will pull the url and put the contents to the container you specfied
and there are some call backs
you can add a Loader.beforeLoading = function(){
app.$destroy();
}
and thats it