I have this vue js script
const NotfoundComponent = {
template: '<h1>Not found</h1>'
};
const HomeComponent = {
template: '<h1>Home</h1>'
};
const AboutComponent = {
template: '<h1>About</h1>'
};
const routes = [
{
path: '/',
component: HomeComponent
},
{
path: '/about',
component: AboutComponent
},
{
path: '*',
component: NotfoundComponent
}
];
const router = new VueRouter({
mode: 'history',
routes
});
new Vue({
el: '#app',
router
});
that uses vue-router. I am running vue js inside a jsp page inside a spring mvc app. I would like to have load the jsp page normally as served by jetty and only use vue js router to navigate between components inside the page.
I have the router setup and working inside the page, however on link click, i do not want any of this vue js links
<div id="app">
<router-link to="/">home</router-link>
<router-link to="/about">about</router-link>
<router-link to="/something">no route</router-link>
<router-view></router-view>
</div>
to modify the current address bar or append anything new to it.
Can that be done using vue js?.
You want 'abstract' mode.
const router = new VueRouter({
mode: 'abstract',
routes
});
This requires you push an initial URL:
// you main Vue instance
new Vue({
el: '#app',
router,
template: '<App/>',
components: { App },
mounted() {
this.$router.replace('/') // added this
}
})
CodeSandbox demo here.
Please Check below link, you want to use abstract
https://jsfiddle.net/qpnaokhf/
const router = new VueRouter({
routes,
mode: 'abstract'
})
Related
I'm currently using VueJS in browser mode, without build tools, using scripts in the header of my page:
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-router/dist/vue-router.js"></script>
and then in the body:
<script>
var router = new VueRouter({
mode: 'history',
routes: []
});
var app = new Vue({
el: "#graphe_app",
router,
[...]
});
</script>
I'd like to use the vue-gtap component using the following script in my header but without build tools:
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue-gtag#2.0.1/dist/vue-gtag.umd.min.js"></script>
I read the tutorial for vue-gtag but it only explains how to use the component with build tools:
import { createApp } from "vue";
import { createRouter, createWebHashHistory } from 'vue-router';
import VueGtag from "vue-gtag";
import App from "./App.vue";
import Home from "./Home.vue";
import About from "./About.vue";
const router = new VueRouter({
history: createWebHashHistory(),
routes: [
{ name: 'Home', path: '/', component: Home },
{ name: 'About', path: '/about', component: About },
]
});
const app = createApp(App);
app.use(router);
app.use(VueGtag, {
config: {
id: "GA_MEASUREMENT_ID",
},
}, router); // <----- add your router here
app.mount("#app");
Do you know how I can adapt the above code without build tools to automatically track page changes with router and send them to GA?
Thanks a lot for your help!
Alex
I have a backoffice in Laravel with dynamic routes, however, I don't know how I do this in vue js, that is, create routes dynamically, so that a controller or something like that returns me the correct view!
You could try Vue Router's Dynamic Route matching, passing different values for route parameters: https://router.vuejs.org/guide/essentials/dynamic-matching.html
Small example for you.
Laravel part
Your "web" routes in Laravel
Route::get('/{any}', 'AppController')->where('any', '.*');
Inside invoke controller
public function __invoke()
{
return view('app');
}
In app.blade
#extends('layouts.app')
#section('content')
<div id="app">
<app/>
</div>
#endsection
Vuejs part:
Your router file
import Login from "./views/Login";
import Home from "./views/Home";
import NotFound from "./views/NotFound";
Vue.use(VueRouter);
let router = new VueRouter({
routes: [
{ path: '/login', name: 'login', component: Login },
{ path: "/", name: 'home', component: Home },
{ path: "*", name: '404', component: NotFound }
});
In app.js
import router from './router';
const app = new Vue({
store,
router,
i18n,
el: '#app',
});
All post, put, patch routes should be "api" routes.
I am using this simple-router example, but with my own components:
$( document ).ready(function() {
const Home = { template: '<div id="login"><login-comp></login-comp></div>' };
const Foo = { template: '<div>Foo</div>' };
const router = new VueRouter({
mode: 'history',
routes: [
{ path: '/', component: Home },
{ path: '/foo', component: Foo }
]
})
new Vue({
router,
el: '#router',
data: {
msg: 'Hello World'
}
})
});
It works fine but as a change from one route to another the page redirect to my base url, for example my site is:
https://example.com/vue/index.jsp
after changing to /foo, the url changes to
https://example.com/foo
My index.jsp router:
<div id="router">
<router-link to="/">/home</router-link>
<router-link to="/foo">/foo</router-link>
<router-view></router-view>
</div>
Thank's for any help.
That is how it's meant to work, when you set mode to history:
mode: 'history'
Remove that part, and you'll get a hash after your url, and it will work properly.
Got this working with a single page. It's when I introduce vue-router that nothing will render.
In main.js, if I return app.js with sample text and few edits; it renders fine with no issues. Seems it has to do with how I'm instantiating vue-router. Also, no console errors in my environment.
main.js
define(function(require) {
'use strict';
var Vue = require('vue');
var VueRouter = require('vue-router');
var App = require('app');
var Foo = { template: '<div>oijsdfoijsdoifjdsf</div>' }
var Bar = { template: '<div>bar</div>' }
Vue.use(VueRouter);
var routes = [
{ path: '/aaa', component: Foo },
{ path: '/bbb', component: Bar }
]
var router = new VueRouter({
routes: routes
});
return new Vue({
el: '#vue',
router: router,
render: function(h) {
h(App);
}
});
});
app.js
define(function(require) {
'use strict';
var Vue = require('vue');
return new Vue({
template: '<div id="vue"><router-view></router-view></div>'
});
});
From my experience, you can change your router configuration to:
const router = new VueRouter({
base: __dirname, // or '/'
routes: routes
})
You haven't defined a root route, e.g. /. So you wouldn't see any component render at /. Can you navigate to /aaa and see something? Also, shouldn't those route components be passed to Vue.component?
How do I create the routes array dynamically, after fetching it via ajax?
Is there a way to add/push new routes to the router after it has been initialized?
This doesn't work:
new Vue({
el: '#app',
template: '<App/>',
data: {
content: []
},
created: function () {
this.$http.get('dummyjsondatafornow').then((response) => {
// this doesn't work when creating the VueRouter() outside the Vue instance, as in the docs.
// this.$router.options.routes.push({ path: '/about', component: About })
let routes = [
{ path: '/about', component: About }
]
// this doesn't work either
this.router = new VueRouter({
routes: routes
})
})
},
// router: router,
components: { App }
})
I don't believe there is no.
That said you can wildcard the route so that may provide you with an alternative.
I built a site where the backend (and in turn pages created) were controlled via a CMS which served all pages to Vue as JSON. This meant Vue wasn't aware of the routes the backend was creating.
Instead we passed all the CMS pages to Vue Router via a single * wildcard component. In Vue Router 2 this would look like:
const routes = [
{ path: '*', component: AllPages }
]
Vue Router 2 allows for Advanced Matching Patterns
These allow you to set a wide variety of conditions, therefore whilst you can't inject the object passed back via ajax into your router you can add a dynamic component to an AllPages component that is wildcard matched. This would allow you to pass the name of the component to load via your ajax request and then load that component when the page is called. i.e.
Your Ajax response:
{
// url: component name
'/about/': 'about',
'/about/contact/': 'contact',
...
}
Then in an AllPages vue component:
<template>
<component v-bind:is="currentView"></component>
</template>
<script>
module.exports = {
data () {
return {
currentView: '',
ajaxRoutes: {}, // loaded via ajax GET request
...
}
},
// watch $route to detect page requests
watch: {
'$route' (to, from) {
if (this.ajaxRoutes[to]) {
this.currentView = this.ajaxRoutes[to]
}
}
},
...
}
</script>
The above is a rather abbreviated idea but essentially you dynamically load the component based on the path the user requested.
I think this is fixed in version 2.3.0. You can now run
router.addRoutes(routes);
to dynamically add routes.
https://github.com/vuejs/vue-router/commit/0e0fac91ab9809254174d95c14592e8dc2e84d33
I have the same situation wherein my routes are built on the backend as it is maintained thru a CMS. With that, I was able to retrieve my routes thru an API call then return it on the vue router. Here's my take:
routes.js
const router = store.dispatch('cms/fetchRoutes').then((response) => {
const router = new VueRouter({
routes: response,
mode: 'history',
...
});
...
return router;
});
export default router;
main.js
import router from './router';
....
router.then((router) => {
const app = new Vue({
router,
store,
render: (h) => h(App),
}).$mount('#app')
...
});
Basically I do an axios call to fetch my routes then inject the response to the VueRouter routes property. Then on the main.js, do another then and inject the return on the Vue.
By then, my menus are now being retrieved from the database. No more hard coded paths.