Can't change router component - vue.js

I have a .vue file with the following
<template>
<div class="container">
<div class="row">
<div class="column">
<h2>Create your MIA</h2>
<p><img src="../../static/intro.gif"/></p>
<p><a v-on:click="go()" href="javascript:void(0)" class="button">Enter</a></p>
</div>
</div>
</div>
</template>
<script>
export default {
methods: {
go: function () {
console.log(this.$router.go)
this.$router.go({ path: '/app' })
}
}
}
</script>
and in a main index.html file I have
<main class="container center">
<div id="logo"></div>
<div id="section">
<router-view></router-view>
</div>
</main>
and in my main.js
import Vue from 'vue'
import Resource from 'vue-resource'
import Router from 'vue-router'
import App from './components/app'
import Intro from './components/intro'
Vue.use(Resource)
Vue.use(Router)
const route = new Router({hashbang: false,
history: true,
linkActiveClass: 'active',
mode: 'html5'})
// Pointing routes to the components they should use
route.map({
'/': {
component: Intro,
subRoutes: {
'app': {
component: App
}
}
},
'/app': {
component: App
}
})
// Any invalid route will redirect to home
route.redirect({
'*': '/app'
})
route.start(Intro, '#section')
When the stuff is compiled I am able to get the Intro component but click on the button only changes the hash but not the component....
Based on the documentation the only thing that I'm doing different is that I am changing the route programmatically.
What am I doing wrong here?

Related

error vue.js Uncaught TypeError: Cannot read properties of undefined (reading 'use')

I have made a simple blog in vue.js to practice vue.js. I have installed a router and now it doesnt wanna show anything on the localhost.
Im using directories views where i put files to show, components are for now empty. router is an own directory with a file index.js where i connect the router.
(I have not included the style in this message)
Here is the error in the console:
app.js:378 Uncaught TypeError: Cannot read properties of undefined (reading 'use')
at eval (index.js?5aa4:6:1)
at ./src/router/index.js (app.js:96:1)
at __webpack_require__ (app.js:375:33)
at fn (app.js:609:21)
at eval (main.js:4:65)
at ./src/main.js (app.js:85:1)
at __webpack_require__ (app.js:375:33)
at app.js:1497:109
at __webpack_require__.O (app.js:421:23)
at app.js:1498:53
Here is the app.vue;
<template>
<div class="container">
<div>
<img class="img" src="#/assets/bloglogo.jpg">
</div>
<div class="nav-div">
<navbar class="nav">
<ul class="navbar">
<div class="li"><router-link to="/homePosts">Home</router-link</div>
<div class="li"><router-link to="/writePost">Write a post</router-
link></div>
</ul>
</navbar>
</div>
<div>
<router-view></router-view>
</div>
</div>
</template>
<script>
export default {
name: "App",
}
</script>
here is the main.js;
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
createApp(App).use(router).mount('#app')
here is the index.js inside the router directory
import vue from 'vue'
import home from '../views/homePosts'
import writePost from '../views/writePost'
import { createRouter, createWebHistory } from 'vue-router'
vue.use(createRouter,createWebHistory)
const routes = [
{
name: 'Home',
component: home,
path: '/'
},
{
name: 'writepost',
component: writePost,
path: '/writePost'
}
];
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
one of the view files;
<template>
<div class="post-container">
<h1>Blog Posts</h1>
<div class="post-mini-container">
<div class="post">
<img class="img-post" src="#/assets/person1.jpg">
<h4>Blog headline here</h4>
<h6>Writer name</h6>
</div>
<div>
<h5 class="blog-text">Lorem
</h5>
</div>
<div class="read-me">
<h6 class="read-more">Read more..</h6>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'homePosts'
}
</script>
Why are you using vue.use(createRouter,createWebHistory) in your router file?
index.js - router directory
import { createRouter, createWebHistory } from 'vue-router'
const routes = [
{
name: 'Home',
component: () => import('../views/homePosts'),
path: '/'
},
{
name: 'writepost',
component: () => import('./views/writePost'),
path: '/writePost'
}
];
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
It will be much healthier if you remove the line you use vue.use(createRouter,createWebHistory) and import the components in this way. And I believe that this way the problem will be solved.
If you are wondering why we imported the components this way, I suggest you read this source (Lazy Loading).

vue.js router help what error could mean in console router-link router-view vue.js

Hi im working on the blog-app to practice vue.js. I have now made it so my nav-bar is showing but I have a problem with the routing.
Here is the errors in the console and the directories and files.
here is my main.js;
import { createApp } from 'vue'
import App from './App.vue'
import router from './routers'
import navBar from './components/navbar/navBar.vue';
const app = createApp(App)
app.component('app-navbar', navBar)
app.mount('#app')
app.use(router)
here is my app.vue
<template>
<div class="container">
<app-navbar></app-navbar>
<div>
<router-view></router-view>
</div>
</div>
</template>
<script>
export default {
}
</script>
here is my routers.js;
import { createRouter, createWebHistory } from 'vue-router'
const routes = [
{
name: 'homePosts',
component: () => import ('./views/homePosts'),
path: '/homePosts'
},
{
name: 'writePost',
component: () => import('./views/writePost'),
path: '/writePost'
}
];
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
here is my writePost.vue;
<template>
<div>
<form class="form">
<label for="">Writer name: </label>
<input type="text" max="500">
<br>
<label for="img">Select image:</label>
<input type="file" id="img" name="img" accept="image/*">
<br>
<label for="">Your blogtext: </label>
<textarea name="" id="" cols="30" rows="30"></textarea>
</form>
</div>
</template>
<script>
Here is my directories;
here is navbar.vue
<template>
<div class="container">
<div>
<img class="img" src="#/assets/bloglogo.jpg">
</div>
<div class="nav-div">
<navbar class="nav">
<ul class="navbar">
<div class="li"><router-link to="/views/homePosts">Home</router-link></div>
<div class="li"><router-link to="/views/writePost">Write a post</router-link></div>
</ul>
</navbar>
</div>
</div>
</template>
Firstly, you forgot to download the vue-router package or I don't know. Because as soon as I run the project, I got the error "Vue-router module not found".
To install the vue-router package:
pnpm install vue-router#latest
or
npm install vue-router#latest
Then I examined your router.js file. You should only import and use .vue files as components.
router.js
import { createRouter, createWebHistory } from "vue-router";
const routes = [
{
name: "Home",
path: "/",
redirect: { name: "homePosts" },
},
{
name: "homePosts",
component: () => import("./views/homePosts.vue"),
path: "/home-posts",
},
{
name: "writePost",
component: () => import("./views/writePost.vue"),
path: "/write-post",
},
];
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;
When I came to the / path, I directed it to the /home-posts path. However, if you want, you can create a new component and assign it to / path.
Also, I suggest you give your path names as kebab-case. Like /home-posts
And finally I edited your main.js file a bit.
main.js
import { createApp } from "vue";
import App from "./App.vue";
import router from "./routers";
import navBar from "./components/navbar/NavBar.vue";
const app = createApp(App);
app.use(router);
app.component("app-navbar", navBar);
app.mount("#app");
When you follow these steps, your problem should be completely resolved.
Also, as I said in the comment, there is only 1 warning message left, unfortunately I do not know the solution for it.

How to properly register a component in a Vue 3 + Composition API app?

I'm trying to build an app with two layout, one with header and everything, one with just the background for some special pages(like login pages).
I've tried the following:
Created 2 view page:
layouts/Default.vue
<template>
<header class="flex justify-around">
<Header class="w-10/12 max-w-screen-lg"></Header>
</header>
<div class="grow h-full flex justify-around">
<div class="bg-white m-5 rounded-lg p-3 w-10/12 max-w-screen-lg shadow-lg">
<slot />
</div>
</div>
</template>
<script setup lang="ts">
import Header from "../components/Header.vue";
</script>
and
layouts/Plain.vue
<template>
<div class="grow h-full flex justify-around">
<div class="bg-white m-5 rounded-lg p-3 w-10/12 max-w-screen-lg shadow-lg">
<slot />
</div>
</div>
</template>
In my router/index.ts, I provide a "meta"
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'home',
component: HomeView,
},
{
path: '/login',
name: 'login',
component: LoginView,
meta: { layout: 'plain' },
},
{
path: '/about',
name: 'about',
// route level code-splitting
// this generates a separate chunk (About.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import('../views/AboutView.vue'),
},
],
});
In my App.vue: I try to use this to create a component that wraps my routerView:
<script setup lang="ts">
import { computed } from "vue";
import { RouterView, useRoute } from "vue-router";
const route = useRoute();
const layout = computed(() => {
return (route.meta.layout || 'default');
});
</script>
<template>
<div id="root"
class="min-h-full bg-gradient-to-br from-indigo-500 via-purple-500 to-pink-500 flex flex-col">
<component :is="layout">
<RouterView></RouterView>
</component>
</div>
</template>
And more important, in my main.ts file, I did try to register them:
import { createPinia } from 'pinia';
import Vue, { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import './assets/main.css';
import Plain from './layouts/Plain.vue';
import Default from './layouts/Default.vue';
const app = createApp(App);
app.component('default', Default);
app.component('plain', Plain)
app.use(createPinia());
app.use(router);
app.mount('#app');
But when I try to display ANY page, I get this:
Uncaught SyntaxError: The requested module '/node_modules/.vite/deps/vue.js?v=7cc2bcdd' does not provide an export named 'default' (at main.ts:2:8)
So I guess, that app.component('vue-name', component) is not the correct approach, but I can't find how?
The error is unrelated to your component registration, but rather it points to this:
πŸ‘‡ // The requested module 'vue.js' does not provide an export named 'default'
import Vue, { createApp } from 'vue';
In Vue 3, the vue module has no default export, so import Vue from 'vue' would fail. The Vue import also isn't used anywhere in main.ts, so you apparently don't even need it. The solution is to remove it:
import { createApp } from 'vue'; βœ…
demo
According to official docs you should import them inside the App.vue and use them as variables :
<script setup lang="ts">
import { computed } from "vue";
import { RouterView, useRoute } from "vue-router";
import Plain from '../layouts/Plain.vue';
import Default from '../layouts/Default.vue';
const route = useRoute();
const layout = computed(() => {
return route.meta.layout==='plain'? Plain : Default;
});
</script>
<template>
<div id="root"
class="min-h-full bg-gradient-to-br from-indigo-500 via-purple-500 to-pink-500 flex flex-col">
<component :is="layout">
<RouterView></RouterView>
</component>
</div>
</template>
You could use normal script without setup to get globally registered components, by using vite try out vite-plugin-vue-layouts to register your layouts dynamically.

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

How to listen to music without pausing, while changing the page?

How could i continue music playback even while changing pages using Vue js?
Principle of operation:
1. The user starts listening to music on page example.com
2. He goes to the example.com/about and the music he started to listen to doesn't stop.
I guess that i have to the music in the parent component as it’s own separate component, but i am not sure.
App.vue
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'app'
}
</script>
main.js
import Vue from 'vue'
import App from './App'
import VueRouter from 'vue-router'
import About from './components/About'
import Main from './components/main'
Vue.use(VueRouter);
const routes = [
{ path: '/', component: Main },
{ path: '/about', component: About }
];
const router = new VueRouter({
routes,
mode: 'history'
});
new Vue({
el: '#app',
template: '<App/>',
components: { App },
router
}).$mount('#app');
About.vue
<template>
<div id="about">
<h1>The about page</h1>
<br>
<router-link to="/">Back to main page</router-link>
<br>
<audio controls oncontextmenu="return false">
<source src="../bruh.mp3">
</audio>
</div>
</template>
<script>
export default {
name: 'about'
}
</script>
main.vue
<template>
<div id="about">
<h1>The main page</h1>
<br>
<router-link to="/about">Go to about page</router-link>
<br>
<audio controls oncontextmenu="return false">
<source src="../bruh.mp3">
</audio>
</div>
</template>
<script>
export default {
name: 'about'
}
</script>
Create a new component for the audio, and import that into your App.vue and place it outside <router-view></router-view>. E.g:
/components/AudioComponent.vue (can't use Audio.vue because there is already an audio HTML element)
<template>
<audio controls oncontextmenu="return false">
<source src="../bruh.mp3">
</audio>
</template>
<script>
export default {
// maybe take the src filename and controls on/off attribute as props?
// maybe provide some methods for external control via an event bus or shared state
}
</script>
/App.vue
<template>
<div id="app">
<!-- put a shared header here, e.g. links to routes, top bar, sidebar menu, etc -->
<router-view></router-view>
<audio-component></audio-component>
<!-- put a shared footer here -->
</div>
</template>
<script>
import AudioComponent from './components/AudioComponent.vue'
export default {
name: 'app',
components: {
AudioComponent,
}
}
</script>