I'm using Nuxt JS v2.4.5 with Bootstrap Vue, I have a fixed header and a page footer that are located inside of my default.vue file.
When I scroll to the bottom of a page and click a link in the footer, using the following, it takes me to the top of the new page as expected, however the content appears to occasionally flicker for a few ms before loading the content, I'm using:
router: {
scrollBehavior: function (to, from, savedPosition) {
return { x: 0, y: 0 }
}
}
This appears to be a common problem in Nuxt JS as it's of course not technically a page refresh, how could I go about fixing this?
Many Thanks.
Related
I am trying to make Nuxt change routes and appear at the top of the new route, but without seeing it scrolling.
Right now it's either saving the last position, or it's changing the route while scrolling.
I don't want to see the page scrolling.
Setting this code in nuxt.config does nothing:
router: {
saveScrollPosition: false
}
Setting this code in app/router.scrollBehavior.js scrolls to top visibly:
export default function (to, from, savedPosition) {
return { x: 0, y: 0 }
}
Nuxt version 2.15.8
Vue version 2.7.10
I'm trying to generate a blank page after the user clicks on a navbar button.
I imported a Vue router to my project on codepen.
var demo = new Vue({
// A DOM element to mount our view model.
el: '#main',
// This is the model.
// Define properties and give them initial values.
data: {
active: 'what'
},
// Functions we will be using.
methods: {
makeActive: function(item){
// When a model is changed, the view will be automatically updated.
this.active = item;
}
}
});
When I click on How, and About in the navbar, the text successfully changes to
"You chose: How/about"
so I know the navbar code is working. But I want to generate a completely fresh page.
When I click on How or About, I want the front page text to completely disappear, and a new page to appear for the user. How do I make the title page text disappear, and generate a completely new, black page?
If you are using Vue Router you will need to import that into your application when you create your Vue instance with the new Vue({...}) command. In your example above you are not including Vue Router.
If you include VueRouter you will have to create a routes page that has routes for /how and /about. Then in your Nav you will need to surround the links for these two routes with:
<router-link to="/how">How</router-link>
<router-link to="/about">About</router-link>
These routes will then open the appropriate component you specify in the routes page.
I have the following code in one of my layouts.
bodyAttrs: {
class: this.$store.state.user.theme + '-scheme'
}
unfortunately, i am using an old bootstrap theme css. I DO NOT want to redo it as such i have to figure out some work arounds.
The theme color for the bootstrap theme attaches itself to the body tag. Unfortunately the body tag is a no no in nuxt.
What i have noticed is, that upon refresh the page is rendered with the base state value.
example :
//store/index.js <- not modular
var state = () => ({
user: {
id: 0,
avatar: 'default.jpg',
status: 'offline',
nickname: 'Guest',
admin: false,
theme: 'brownish' //-> this is the value
}
})
The entire page renders with the users details but the theme variable is not placed into the render. If i go to another page(ajax routing), the page is updated with the correct color.
Essentially the page loads brown and then on subsequent pages it will load blue. If the page is refreshed then the color reverts to brown and then on subsequent pages it will turn blue again.
How can i get the SSR to display the correct bodyAttr?
I am using vuex-persistedstate and cookies both are client side
The nuxt server does not have any sessions as this is handled on a separate domain(api)
I couldn't find a pure vuejs way to do this so i made a fix.
This is technically a bad idea as it is directly modifying the DOM which is a no-no in vue. However, vue doesnt use reactivity on the body tag. Therefore i think it is fairly safe to use. Also, using vuex-presistedstate will ensure that vue set the proper state variable on subsequent loads..
//This is layouts/default.vue
head() {
return {
bodyAttrs: {
class: this.$store.state.user.theme + '-scheme'
}
}
},
mounted() {
window.onNuxtReady(() => {
document.body.className = this.$store.state.user.theme + '-scheme'
})
}
Are you using the cookies based version of vuex-persistedstate? Customize Storage
Remember to enable the ssr mode for the plugin in nuxt.config.js
Without reloading the whole page I need to reload the current route again (Only a component reload) in a vue app.
I am having a path in vue router like below,
{
path: "/dashboard",
name: "dashboard",
component: loadView("Dashboard"),
},
When user clicks on the Dashboard navigation item user will be redirected to the Dashboard page with vue router programmatic navigation
this.$router.push({ name: "dashboard" });
But when user already in the dashboard route and user clicks the Dashboard nav item again nothing happens. I think this is vue router's default behaviour. But I need to force reload the Dashboard component (Not to refresh the whole page).
I can't use beforeRouteUpdate since the router is not updated. Also I have tried the global before guards like beforeEach. But it is also not working.
How can I force reload the dashboard component without reloading the whole page?
It can be done in two ways.
1) Try doing vm.$forceUpdate(); as suggested here.
2) You can take the strategy of assigning keys to children, but whenever you want to re-render a component, you just update the key.
<template>
<component-to-re-render :key="componentKey" />
</template>
<script>
export default {
data() {
return {
componentKey: 0,
};
},
methods: {
forceRerender() {
this.componentKey += 1;
}
}
}
</script>
Every time that forceRerender is called, the prop componentKey will change. When this happens, Vue will know that it has to destroy the component and create a new one.
What you get is a child component that will re-initialize itself and “reset” its state.
Not mentioned here, but as the offered solutions require a lot of additional work just to get the app to render correctly, which imo is a brittle solution.. we have just implemented another solution which works quite well..
Although it is a total hack.
if (this.$route.name === redirect.name) {
// this is a filthy hack - the vue router will not reload the current page and then have vue update the view.
// This hack routes to a generic page, then after this has happened the real redirect can happen
// It happens on most devices too fast to be noticed by the human eye, and in addition does not do a window
// redirect which breaks the mobile apps.
await this.$router.push({
name: RouteNames.ROUTE_REDIRECT_PLACEHOLDER
});
}
... now continue to do your normal redirect.
Essentially, redirect to a placeholder, await the response but then immediately continue to another page you actually wanted to move toward
I read the documentation of vue-router (https://router.vuejs.org/guide/essentials/navigation.html)
This is the method called internally when you click a ,
so clicking is the equivalent of calling
router.push(...)
As far as I know clicking router-link element navigates to the URL placed in "to" attribute. However, according to History API
(https://developer.mozilla.org/en-US/docs/Web/API/History_API#Examples), history.pushState(...) only changes the history and does not navigate to a new URL.
So... how can we explain this contradiction?
I think you need to define exactly what you mean by "navigate to a new URL"; to me it can mean either reloading the page at a new URL, or simply changing the URL in the address bar without reloading the page.
history.pushState() does change the URL, but it doesn't cause the browser to perform a full page reload as is typical when you click a link. This is how "single page apps" work – they intercept <a> clicks and use history.pushState() to prevent the page from reloading.
history.pushState(...) only changes the history and does not navigate to a new URL.
Here I think "and does not navigate to a new URL" is wrong – it does, except the page doesn't reload.
There is no contradiction here. There is no reason why the Vue Router could not do a change to the url with the history api and change the component as rendered in various router-view components.
When you include a router-link in your code, this is a component like any other. Vue will render this component. The interesting part is this:
const router = this.$router
// And later
const handler = e => {
if (guardEvent(e)) {
if (this.replace) {
router.replace(location)
} else {
router.push(location)
}
}
}
const on = { click: guardEvent }
if (Array.isArray(this.event)) {
this.event.forEach(e => { on[e] = handler })
} else {
on[this.event] = handler
}
For the history api, you can see in the source that for a this.$router.push(..) we transition, and we push the state with this pushState function. The transition itself can be found in history/base.js.