Need help figuring out why vue-router isn't working for my simple tab control scenario - vue.js

I have a very simple sample app with a tab control. I'd like either component A or component B to be displayed when a tab is selected. This should be handled by vue-router fairly easily but I don't know what's wrong with my config.
When I click on either tab button, nothing happens. None of my components display.
What am I missing?
main.js
import Vue from 'vue';
import {
Tabs,
} from 'buefy';
import 'buefy/dist/buefy.css';
import App from './App.vue';
import './registerServiceWorker';
import router from './router';
import store from './store';
Vue.use(Tabs);
Vue.config.productionTip = false;
new Vue({
router,
store,
render: (h) => h(App),
}).$mount('#app');
App.vue
<template>
<div id="app">
<section>
<b-tabs type="is-toggle">
<b-tab-item label="Component A" to="/ComponentA"></b-tab-item>
<b-tab-item label="Component B" to="/ComponentB"></b-tab-item>
</b-tabs>
</section>
<router-view />
</div>
</template>
<style>
</style>
router\index.js
import Vue from 'vue';
import VueRouter from 'vue-router';
import ComponentA from '#/components/ComponentA.vue';
import ComponentB from '#/components/ComponentB.vue';
Vue.use(VueRouter);
const routes = [
{
path: '/ComponentB',
name: 'ComponentA',
component: ComponentA,
},
{
path: '/ComponentB',
name: 'ComponentB',
component: ComponentB,
},
];
const router = new VueRouter({
routes,
});
export default router;
components\ComponentA.vue
<template>
<div>Hello From Component A</div>
</template>
components\ComponentB.vue
<template>
<div>Hello From Component B</div>
</template>

I think this is an existing issue with Tabs & Router in Buefy. You could do something like this:
<b-tabs>
<router-link
label="Component A"
:to="{ name: 'ComponentA' }"
>
Component A
</router-link>
<router-link
label="Component B"
:to="{ name: 'ComponentB' }"
>
Component B
</router-link>
</b-tabs>
Or use a Buefy component that supports Vue Router, e.g:
<b-button tag="router-link" to="/ComponentA" type="is-link">
Component A
</b-button>

Related

Vue 2: vue-router-3.x not redirecting/pushing from App.vue

I made a Vue 2 web page and tried to use vue-router v3 to route to a different page. The web page is as follows:
src/App.vue: the web page opens from here
<template>
<div id="app">
<GoHere/>
</div>
</template>
<script>
import GoHere from './views/gohere/GoHere.vue'
export default {
name: 'App',
components: {
GoHere
}
}
</script>
src/main.js:
import Vue from 'vue'
import App from './App.vue'
import router from "./router/router"
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App),
}).$mount('#app')
src/views/gohere/GoHere.vue: the page from which the issue arises
<template>
<div>
<v-btn #click="goHere()">
Go Here
</v-btn>
</div>
</template>
<script>
export default {
name: "GoHere",
methods: {
goHere() {
this.$router.push("/menu")
}
}
}
</script>
src/views/menu/Menu.vue: the page to redirect to
<template>
<div>
Menu
</div>
</template>
<script>
export default {
name: "Menu",
}
</script>
src/router/router.js: the router file
import Vue from 'vue'
import VueRouter from 'vue-router'
import GoHere from '../views/gohere/GoHere'
import Menu from '../views/menu/Menu'
Vue.use(VueRouter)
const routes = [
{ path: '/', name: "gohere", component: GoHere},
{ path: '/menu', name: "menu", component: Menu}
]
const router = new VueRouter({
routes
})
export default router
When I clicked on the button in GoHere.vue, the URL changes into "http://localhost:8080/#/menu" but the content does not change into the content for Menu.vue. How can the problem be solved?
The component from the current route will automatically render in <router-view></router-view>
App.vue:
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
Check the docs

the switching of the Vue Router is not working

I have a menu with 2 buttons. But the switching is not working. Moreover, the main page is invisible.
My sandbox https://codesandbox.io/s/serene-neumann-mpqs0?file=/src/App.vue
This is router.js
const routes = [
{
path: "/",
component: Main
},
{
path: "/history",
component: History
},
{
path: "/favorites",
component: Favorites
}
];
const router = new VueRouter({
routes
});
export default router;
This is Header
<template>
<header class="sticky top-0 z-40 w-full flex bg-yellow-500 md:h-16 shadow-md">
<div class="w-1/4 flex justify-end">
<router-link to="/favorites">
<button title="Favorites" class="p-2 hover:text-red has-tooltip">
Favorites
</button>
</router-link>
<button class="p-2 hover:text-red" title="History">
<router-link to="/history"> History </router-link>
</button>
</div>
</header>
</template>
App.vue
<template>
<Header/>
<router-view></router-view>
</template>
<script>
import Header from './components/Header.vue'
export default {
name: "App",
components: {
Header
},
};
</script>
and main.ts
import { createApp } from "vue";
import App from "./App.vue";
import "./assets/index.css";
import router from "./router";
const app = createApp(App);
app.use(router);
app.mount("#app");
You have kind of a mix between vue-router v3/v4.
Update everything to the latest versions and adapt the Router, so it works according to the latest docs should work:
https://codesandbox.io/s/keen-morning-rufbo?file=/src/router.js

Vue-router: do i need to define the default route for vue-router

Experimenting with vue-router, when i click on <router-link to="/about">Go to About</router-link> it doesnt redirect me to anywhere so for example: if i was on localhost:8080/#/ and i click the Go to About button, i still remain on localhost:8080/#/. Also if i change the url directly to localhost:8080/#/about nothing happens (ie no change to the website as if i am still on localhost:8080/#/)
The code:
/router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router';
Vue.use(VueRouter);
const routes = [
{
path: '/about',
component: () => {
import ('../views/About.vue');
}
}
]
const router = new VueRouter({
routes
})
export default router;
./App.vue
<template>
<div>
<div id='nav'>
<router-link to="/about">Go to Foo</router-link>
</div>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App',
components: {
//
},
data: () => ({
//
}),
};
</script>
./views/About.vue
<template>
<p>Testing out vue-routes</p>
</template>
./main.js
import Vue from 'vue'
import App from './App.vue'
import vuetify from './plugins/vuetify';
import store from './store';
import router from './router';
Vue.config.productionTip = false;
new Vue({
vuetify,
store,
router,
render: h => h(App)
}).$mount('#app')
I tried running the following code. it gave no error on serving. (I am also using vuetify and vuex but i dont think that is the problem?)
EDIT
I have edited the code such that it works by creating another vue app and using the default that vue has provided with but i cant seem to understand why the edited code works and why the previous code ^^ above didnt. It seems like the reason was that the default localhost:8080/#/ needs to have its own route in ./App.vue as well and is not there by default? can someone confirm this (can't seem to find something like this explanation online?)
Revised working code:
./App.vue
<template>
<div id="app">
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</div>
<router-view />
</div>
</template>
./views/Home.vue
<template>
<h1>This is the home page</h1>
</template>
<script>
export default {
name: 'Home',
components: {
//
},
data: () => ({
//
}),
};
</script>
./main.js
import Vue from 'vue'
import App from './App.vue'
import vuetify from './plugins/vuetify';
import store from './store';
import router from './router';
Vue.config.productionTip = false;
new Vue({
vuetify,
store,
router,
render: h => h(App)
}).$mount('#app')
./router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router';
import Home from "../views/Home.vue";
Vue.use(VueRouter);
const routes = [
{
path: "/",
name: "Home",
component: Home
},
{
path: "/about",
name: "About",
component: () =>
import("../views/About.vue")
}
];
const router = new VueRouter({
routes
})
export default router;
./views/About.vue
<template>
<p>Testing out vue-routes</p>
</template>
You need to have a <router-view/> where the routes are going to resolve.
You can read more about it here: documentation

Vue using router-link to single page components

All the code is at https://github.com/shanegibney/vue-component-routes
Using Vue3.8.3, I am trying to use and to link to single page components. These components are registered in src/routes/index.js here is the file
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '#/components/Home.vue'
import About from '#/components/About.vue'
Vue.use(VueRouter)
export default new Router({
routes: [{
path: '/',
name: 'Home',
component: Home
}, {
path: '/about',
name: 'About',
component: About
}]
})
That should set up the routes.
Then Home.vue component contains a menu which should link to these components.
Home.vue
<template>
<div class="home">
<b-navbar type="light" variant="light" toggleable="md">
<b-navbar-toggle target="nav_collapse"></b-navbar-toggle>
<b-collapse is-nav id="nav_collapse">
<b-navbar-nav>
<router-link to="/">Home</router-link>
<router-link to="/about">About</router-link>
</b-navbar-nav>
</b-collapse>
</b-navbar>
<div>
<router-view></router-view>
</div>
</div>
</template>
<script>
export default {
name: 'Home'
}
</script>
<style>
</style>
Also the App.vue file looks like this,
<template>
<div id="app">
<div class="">
I am app.vue
</div>
<Home />
</div>
</template>
<script>
import Home from '#/components/Home.vue'
export default {
name: 'app',
components: {
Home
}
}
</script>
all this really does is calls the Home.vue component.
If the components are registered in src/routes/index.js should they be globally accessible?
Also after I installed routes using $npm install vue-router I created the directory routes inside src because it did not exist. Then I put index.js inside routes. Perhaps this is not correct.
Not sure if it is helpful but main.js looks like this,
import Vue from 'vue'
import '#babel/polyfill'
import 'mutationobserver-shim'
import VueRouter from 'vue-router'
import './plugins/bootstrap-vue'
import App from './App.vue'
Vue.use(VueRouter)
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
The error I get mentions a 'mismatch',
[Vue warn]: Error in render: "TypeError: Cannot read property 'matched' of undefined"
I presume this is something to do with the routes in index.js not matching with the "to" paths in router-link.
How can I ensure index.js in being included in the app?
Any help would be greatly appreciated.
Thanks,
You forgot to inject your router in the Vue app:
import Vue from 'vue'
import '#babel/polyfill'
import 'mutationobserver-shim'
import VueRouter from 'vue-router'
import './plugins/bootstrap-vue'
import App from './App.vue'
import router from './router' // <= here
Vue.use(VueRouter)
Vue.config.productionTip = false
new Vue({
router, // <= and here
render: h => h(App),
}).$mount('#app')

Use vue component in other vue component file

I tried to use a vue component(Global.vue) in other component(App.vue), but there
Failed to mount component: template or render function not defined
error.
Global.vue:
<template>
<div class="global-view">
<p>Global </p>
</div>
</template>
<script>
export default {
name: 'global'
}
</script>
App.vue:
<template>
<div id="app">
<global></global>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'app'
}
</script>
main.js:
import Vue from 'vue'
import App from './App'
import router from './router'
Vue.component('global', require('./components/Global'))
Vue.config.productionTip = false
new Vue({
el: '#app',
router,
template: '<App/>',
components: { App }
})
You need to import the component within the component file that you want to use it in.
`import Global from './components/Global'
From there you need to add a new key inside your components option that will "register" the component.
Here is what you want your app component to look like.
<template>
<div id="app">
<global></global>
<router-view></router-view>
</div>
</template>
<script>
import Global from './components/Global
export default {
name: 'app'
components: {
'global': Global,
}
}
</script>
<global></global> should be able to render at this point.
I use import instead of require(in main.js) and it works for me:
import Global from './components/Global.vue
Vue.component('global', Global)`