I'm doing a project with vue 3 and I have a problem with generate a pageNOTfound. So, I'm going to show my code cause I can't see the problem.
Route.js:
import { createRouter, createWebHistory } from "vue-router";
import Home from "#/views/Home.vue";
import NotFound from "#/views/NotFound.vue";
const routes = [
{
path: "/",
name: "Home",
component: Home,
},
{
path: "/:pathMatch(.*)*",
component: NotFound,
},
];
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;
main.js
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router"; // <---
// estilos app
import "./styles/styles.scss";
createApp(App).use(router).mount("#app");
NotFound.vue
<template>
<h1>404: Lo sentimos, la página que buscas no existe</h1>
</template>
<script>
export default {
name: "NotFound",
};
</script>
<style scoped lang="scss"></style>
App.vue
<template>
<div id="app">
<app-header />
<div class="app-container">
<Home />
</div>
<Footer />
</div>
</template>
<script>
import AppHeader from "#/components/AppHeader.vue";
import Home from "#/views/Home.vue";
import Footer from "#/components/Footer.vue";
export default {
name: "App",
components: {
AppHeader,
Home,
Footer,
},
};
</script>
I can't see where is my problem cause pageNOTfound is not working at this time. I tried a lot of changes but I don't know how can it works.
If you want to have 404 as a completely seperate page, without footer and header, then you need these files:
App.vue
<template>
<router-view></router-view>
</template>
<script>
export default {
name: "App",
};
</script>
Home.vue
<template>
<div>
<app-header />
<div class="app-container">
... other home content here ...
</div>
<Footer />
</div>
</template>
<script>
import AppHeader from "#/components/AppHeader.vue";
import Footer from "#/components/Footer.vue";
export default {
name: "Home",
components: {
AppHeader,
Footer,
},
};
</script>
This way the App.vue does not contain header or footer, but the Home.vue. And the 404 page will be displayed without header and footer.
Related
I've been fiddling with Vue for a side project and have been trying to implement routing using vue-router, but I can't seem to find a solution to this TypeError I'm getting, which is preventing the site to load at all on localhost:
Uncaught TypeError: Cannot read properties of null (reading 'parent') vue-router.mjs:2478
Here is how I've set up each of my files:
main.js
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
createApp(App).use(router).mount("#app");
router.js
import { createWebHistory, createRouter } from "vue-router";
import Home from "#/views/Home.vue";
import About from "#/views/About.vue";
const routes = [
{
path: "/",
name: "Home",
component: Home,
},
{
path: "/about",
name: "About",
component: About,
},
];
const router = createRouter({
history: createWebHistory(),
routes: routes,
});
export default router;
App.vue
<script setup>
import Navbar from "./components/Navbar.vue";
</script>
<template>
<RouterView />
<Navbar />
</template>
<style scoped></style>
Navbar.vue
<template>
<nav class="navbar navbar-expand-md navbar-custom">
<RouterLink class="navbar-brand" to="/">
<span class="navbar-brand-logo"></span>
</RouterLink>
...
</nav>
</template>
Home.vue
<template>This is the homepage.</template>
About.vue
<template>This is the about page.</template>
I'm rocking Vue v3.2.41 and vue-router v4.1.6. Not exactly sure what's going wrong here. When I pull out use(router) from main.js, the navbar I have renders, so it's clearly something going wrong with vue-router. Would appreciate any help with it!
In your app.vue or anywhere you want to re-use your component make sure to define your imported component in a components property like this:
<script>
import Navbar from "./components/Navbar.vue";
export default {
...
components: {
Navbar
},
</script>
I'm using VueJS 3 applications using vue-router, vue and core-js applications where I want using compoments. I have in views dirrectory Home.vue file which looks like this:
<template>
<div class="wrapper">
<section v-for="(item, index) in items" :key="index" class="box">
<div class="infobox">
<PictureBox image="item.picture" />
<PropertyBox itemProperty="item.properties" />
</div>
</section>
</div>
</template>
<script>
import { ref } from 'vue'
import { data } from '#/data.js'
import { PictureBox } from '#/components/PictureBox.vue'
import { PropertyBox } from '#/components/PropertyBox.vue'
export default {
components: {
PictureBox,
PropertyBox,
},
methods: {
addRow() {
console.log('This add new row into table')
},
},
setup() {
const items = ref(data)
return {
items,
}
},
}
</script>
I have 2 compoments in compoments directory
src/compoments
|- PictureBox.vue
|- PropertyBox.vue
and for example in PictureBox.vue I have this content:
<template>
<div class="infobox-item-picturebox">
<img class="infobox-item-picturebox-image" :src="require(`#/static/${image}`)" alt="item.title" />
</div>
</template>
<script>
import { reactive, toRefs } from 'vue'
export default {
props: {
image: {
type: String,
},
},
setup() {
const state = reactive({
count: 0,
})
return {
...toRefs(state),
}
},
}
</script>
But I have Warning at compiling:
WARNING Compiled with 2 warnings 10:58:02 PM
warning in ./src/views/Home.vue?vue&type=script&lang=js
"export 'PictureBox' was not found in '#/components/PictureBox.vue'
warning in ./src/views/Home.vue?vue&type=script&lang=js
"export 'PropertyBox' was not found in '#/components/PropertyBox.vue'
App running at:
- Local: http://localhost:8080/
- Network: http://172.19.187.102:8080/
Also in Browser Developer mode I have same warnings:
My Directory structure looks like this:
And my main.js looks like here:
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import './assets/style.css'
createApp(App).use(router).mount('#app')
And router page (I'm not using router actually looks like here)
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
const routes = [
{
path: '/',
name: 'Home',
component: Home,
},
]
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes,
})
export default router
Please, can you help me why I have this warning and my content from <template> in PictureBox or in PropertyBox was not loaded? Thank you so much for any advice
The component instance is exported as default (export default {...) in its single file and it should be imported like :
import PictureBox from '#/components/PictureBox.vue'
instead of:
import { PictureBox } from '#/components/PictureBox.vue'
When I use async setup () in Vue 3, my component disappears. I used the solution found here:
why i got blank when use async setup() in Vue3 ... it worked, but I have a blank page when I am using the router-view.
<template>
<div v-if="error">{{error}}</div>
<Suspense>
<template #default>
<router-view></router-view>
</template>
<template #fallback>
<Loading />
</template>
</Suspense>
</template>
<script>
import Loading from "./components/Loading"
import { ref, onErrorCaptured } from "vue"
export default {
name: 'App',
components: { Loading },
setup() {
const error = ref(null)
onErrorCaptured(e => {
error.value = e
})
}
}
</script>
main.js:
import { createApp } from 'vue'
import router from "./router"
import App from './App.vue'
createApp(App).use(router).mount('#app')
When I replace router-view with one of my components, it shows up.
Router:
import { createWebHistory, createRouter } from "vue-router";
import Portfolio from "#/views/Portfolio.vue";
import Blog from "#/views/Blog/Blog.vue";
import Detail from "#/views/Blog/Detail.vue";
import NotFound from "#/views/NotFound.vue";
const routes = [
{
path: "/",
name: "Home",
component: Portfolio,
},
{
path: "/blog",
name: "blog",
component: Blog,
},
{
path: "/blog/:slug",
name: "detail",
component: Detail,
},
{
path: "/:catchAll(.*)",
component: NotFound,
},
];
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;
<Suspense>'s default template should contain an async component (i.e., one with async setup()), but you've put <router-view> in there instead.
You'd have to refactor the <Suspense> into its own wrapper component (e.g., HomeView.vue) that contains the async component, leaving <router-view> itself in App:
<!-- App.vue -->
<template>
<router-view />
</template>
<!-- HomeView.vue -->
<template>
<Suspense>
<template #default>
<MyAsyncComponent />
</template>
<template #fallback>
<Loading />
</template>
</Suspense>
</template>
Then update your router config to use that wrapper:
const routes = [
{
path: '/'
name: 'Home',
component: HomeView
},
//...
]
Vue doc has an example to show how to use <Suspense> with other components
<RouterView v-slot="{ Component }">
<template v-if="Component">
<Transition mode="out-in">
<KeepAlive>
<Suspense>
<!-- main content -->
<component :is="Component"></component>
<!-- loading state -->
<template #fallback>
Loading...
</template>
</Suspense>
</KeepAlive>
</Transition>
</template>
</RouterView>
Ref: https://vuejs.org/guide/built-ins/suspense.html#combining-with-other-components
I am learning VueJs and trying to understand how to extract route params via props.
I was looking at the following documentation, where it seems to have three options to have this done, but I cannot understand it quite well so far - https://github.com/vuejs/vue-router/tree/dev/examples/route-props.
I have tried adding props: true to my router object array (routes.js file posted below) with no success as well.
As this is vue-cli study project I will post the separate pertinent blocks of code in order to try to illustrate this properly.
Main - App.vue below:
<template>
<div class="container">
<div class="row">
<div class="col-xs-12 col-sm-8 col-sm-offset-2 col-md-6 col-md-offset-3">
<h1>Routing</h1>
<hr>
<app-header></app-header>
<router-view></router-view>
</div>
</div>
</div>
</template>
<script>
import Header from './components/Header.vue'
export default {
components: {
appHeader: Header
}
}
</script>
<style>
</style>
Component - Header.vue below:
<template>
<ul class="nav nav-pills">
<router-link to="/" tag="li" active-class="active" exact><a>Home</a></router-link>
<router-link to="/user/10" tag="li" active-class="active"><a>User 1</a></router-link>
<router-link to="/user/5" tag="li" active-class="active"><a>User 2</a></router-link>
</ul>
</template>
Component - User.vue below:
<template>
<div>
<h1>The User Page</h1>
<hr>
<br>
<p>Route ID: {{id}}</p>
<button class="btn btn-primary" #click="goHome">Go to Home</button>
</div>
</template>
<script>
export default {
data(){
return {
id: this.$route.params.id
}
},
watch: {
'$route'(to, from) {
this.id = to.params.id;
}
},
methods: {
goHome(){
this.$router.push('/')
}
}
}
</script>
main.js below:
import Vue from 'vue'
import VueRouter from 'vue-router'
import App from './App.vue'
import {routes} from "./routes";
Vue.use(VueRouter)
export const router = new VueRouter({
routes,
mode: 'history'
})
new Vue({
el: '#app',
router,
render: h => h(App)
})
routes.js below (located at SRC folder):
import User from './components/user/User.vue'
import Home from './components/Home.vue'
export const routes = [
{path: '', component: Home},
{path: '/user/:id', component: User}
]
Do I need to also set Props at User.vue component as well in order to make it work and quit using watch?
In other words, I would like to see my user route being listened at <p>Route ID: {{id}}</p> from this hardcoded 10 to 5 using this new method which I cannot understand, mentioned at the top of this post.
Could anyone please walk me through this issue in this specific situation?
Thanks in advance to all.
According to the docs on passing Props to Route components, you can decouple it, with the props option on the router config.
import User from './components/user/User.vue'
import Home from './components/Home.vue'
export const routes = [
{path: '', component: Home},
{path: '/user/:id', component: User, props: true}
]
<template>
<div>
<h1>The User Page</h1>
<hr>
<br>
<p>Route ID: {{id}}</p>
<button class="btn btn-primary" #click="goHome">Go to Home</button>
</div>
</template>
<script>
export default {
props: ['id'],
methods: {
goHome() {
this.$router.push('/')
}
}
}
</script>
The program must shows the page when that is selected from tab using Vue Material Tab. I've configured routes and installed dependencies but when I click on the tab not is showed. The code have two Vue components to test two screens content. The ideia is show a row like toolbar at top of view and populate it with tabs. The two screens are Menu and Home.
App.vue
<template>
<div>
<md-tabs md-sync-route>
<md-tab id="tab-home" md-label="Home" to="/components/Home" exact></md-tab>
<md-tab id="tab-pages" md-label="Pages" to="/components/Menu"></md-tab>
</md-tabs>
<router-view/>
</div>
</template>
<script>
export default {
name: 'App',
}
</script>
index.js
import Vue from 'vue'
import Router from 'vue-router'
import Home from '#/components/Home'
import Menu from '#/components/Menu'
import VueMaterial from 'vue-material'
import 'vue-material/dist/vue-material.min.css'
import 'vue-material/dist/theme/default.css'
Vue.use(VueMaterial)
Vue.use(Router)
export default new Router({
mode: 'history',
routes: [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/Home',
name: 'Home',
component: Home
},
{
path: '/Menu',
name: 'Menu',
component: Menu
},
]
})
Menu.vue
<template>
<div>
<h1>Menu</h1>
</div>
</template>
<script>
export default {
name: 'Menu'
}
</script>
Home.vue
<template>
<div>
<h1>Home</h1>
</div>
</template>
<script>
export default {
name: 'Home',
}
</script>
Yo don't have routes with path /components/Home and /components/Menu in your router config. So provide correct path's.
<md-tab id="tab-home" md-label="Home" to="/Home" exact></md-tab>
<md-tab id="tab-pages" md-label="Pages" to="/Menu"></md-tab>