I have coded a vue 3 app with vue-router (4.0.13).
When I scroll a bit down on any page, then click a button to another route and then click the back button, the router leads me to a slightly different position than I was before.
But the Router should lead back to the exact same position as it was.
My router configuration:
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes,
scrollBehavior(to, from, savedPosition) {
if (savedPosition) {
return savedPosition
} else {
return { top: 0, behavior: 'instant' }
}
}
})
When I remove the part "else {return { top: 0, behavior: 'instant' }}", then the back button behavior works fine.
What could be the issue here?
Here the link to my application: https://www.test.timetip.app/
Related
Im using Gridsome frame work for VUE JS
I am navigating to a new page by using this.$router.push(PATH, PARAMS)
this.$router.push({path: `/${value.sectionLink}/`, params: {pageOBJ: value}})
The page route works fine - however the PROP, pageOBJ is undefined in the page as seen in the VUE inspector:
it should be an object (which is what VALUE is set to) i.e.
I've tried a number of different techniques to resolve this but have not managed to figure this out so I assume I have missed something here?
gridsome auto generates the page routes when you add a new PAGE.VUE file to the /pages folder -
Is this the issue?
Gridsome also references graphQI, are you supposed to grab the data using graph and not by pushing Props?
Any help would be amazing here - please let me know if you need any further information.
Thanks -
W
UPDATE BASED ON CURRENT ANSWERS:
I have already added props:true to the component as shown below, but the issue is still present.
CODE SNIPPET - SUMMARY:
User clicks on the SectionTitle component, this then emits the page link
(each of the SectionTitle is a object from : sections array of Object)
To see the current online version of this please look at
wtwd.ninjashotgunbear.com
<template>
<Layout>
<div class="navs" v-for="section in sections" :key="section.sectionTitle">
<!-- On click delay for screen to come ove top -->
<!-- router to be put here -->
<SectionTitle :data="section" #routeChange="reRoute($event)"/>
</div>
<PageTransition :dataObj="transitionObj"/>
</Layout>
</template>
<script>
import SectionTitle from '#/components/SectionTitle.vue';
import PageTransition from '#/components/PageTransition.vue'
export default {
metaInfo: {
title: 'Hello, world!'
},
components: {
SectionTitle,
PageTransition
},
data(){
return {
// data to be passed to the components
sections: [
{
sectionTitle: 'Clients',
sectionLink: 'clients',
sectionSubTitle: '"Some of the amazing humans I have had the pleasure of working with"',
backgroundColor: '#F08080',
titleColor: '#E65454'
},
{
sectionTitle: 'Projects',
sectionLink: 'projects',
sectionSubTitle: '"I LIKE TO MAKE PROJECTS THAT WILL TEST MY KNOWEDGE AND EXPOSE MY WEAKNESSES"',
backgroundColor: '#20B2AA',
titleColor: '#11DACF'
},
{
sectionTitle: 'Skills',
sectionLink: 'skills',
sectionSubTitle: `"LEARNING WILL NEVER END, SO LONG AS YOUR AMBITIONS ARE STOKED, AND I've got plenty of ambition"`,
backgroundColor: '#A921B2',
titleColor: '#CA14D6'
},
{
sectionTitle: 'About Me',
sectionLink: 'aboutme',
sectionSubTitle: `"My joruney becoming a developer so far"`,
backgroundColor: '#FFFFFF',
titleColor: '#D1D1D1'
},
{
sectionTitle: 'Contact Me',
sectionLink: 'contactme',
sectionSubTitle: `"If you have any questions or want to reach out about a project then i'd love to speak with you"`,
backgroundColor: '#2185B2',
titleColor: '#0076AB'
}
],
divText: null,
transitionObj: null
}
},
methods:{
reRoute(value){
// 1)A) - change the text of the div to say the section it is being moved to
this.divText = value.sectionTitle
this.transitionObj = value
// FIND center pixcle value to place text - scrolled height + windowHeight / 2 = centerPos
let centerPos = window.scrollY+(window.innerHeight/2)
// Apply secific Title color - and center possitioning
document.querySelector('.leaveScreen p').style.cssText=`color: ${value.titleColor}; top: ${centerPos}px`
// 1) animate the loading screen
let screen = document.querySelector('.leaveScreen');
screen.style.cssText=`background: ${value.backgroundColor}; left: 0%`;
// 2) re-route the page
setTimeout(()=>{
this.$router.push({path: `/${value.sectionLink}/`, params: {pageOBJ: value}}) // << says that the route name is not found
// this.$router.push(value.sectionLink)
}, 700)
}
}
}
</script>
<style lang="scss">
// **** ERROR CAUSED BY NOT INSTALLING SCSS package ****
// https://gridsome.org/docs/assets-css/ &&&& npm install -D sass-loader node-sass
// Universal Font being used - LEMON MILK
#font-face {
font-family: LemonMilk;
src: url('../assets/fonts/LemonMilk.otf');
}
* {
box-sizing: border-box;
}
.navs {
font-family: LemonMilk;
}
.SectionTitle{
cursor: pointer;
}
</style>
Pass name rather than path in this.$router.push()
this.$router.push({name: ${value.sectionLink}, params: {pageOBJ: value}})
You should add props:true to the route definition :
{
path:'/thepath/:theParam',
component:SomeComponent,
props:true
}
I try to smooth scroll using the function: goTo("#how") provided by Vuetify. It worked fine but when I go to a different router page it gives an error.
[Vue warn]: Error in v-on handler: "Error: Target element "#how" not found."
In my knowledge, it means that the target element does not exist.
I tried changing goTo("/#how"), goTo("/how") but it seems to be of no hope.
//App.vue where the header, footer of my app exist and the button that calls the function: goTo()
<v-btn #click="() => this.$vuetify.goTo('#how')">How it Works</v-btn>
//The section where the page should scroll when the button is clicked
<section id="how">
</section>
//the goTo scroll function provided by Vuetify
scrollBehavior: (to, from, savedPosition) => {
let scrollTo = 0
if (to.hash) {
scrollTo = to.hash
} else if (savedPosition) {
scrollTo = savedPosition.y
}
return goTo(scrollTo)
}
I expect it when on another route page and the button is clicked, it should scroll smoothly to the section.
So, I have found a solution to my problem. It may not be the cleanest way but it works.
My solution is to put a conditional statement for the buttons.
//First check if the current route is on landing page (or wherever your #foo is) then set the click function for it.
<v-btn v-if='this.$route.path == "/"' color="white" #click="() => this.$vuetify.goTo('#foo')" flat>How it Works</v-btn>
//If route.path is not at "/" then we call the router push to redirect first to Landing and then scroll.
<v-btn v-else color="white" #click="() => this.$router.push('/#foo')" flat>How it Works</v-btn>
I am using nuxt-links in my website navigation, most of them point to hashed elements/anchors in the home page like:
<nuxt-link
v-else
class="text-link"
:to="localePath('index') + `#${item.hash}`"
>
and it does its job if currently on the home page but when I navigate to a different site, eg. /about and I click on a navbar nuxt-link (so I want to navigate from /about to /#hash or /any-other-site#hash) I got a nuxt error displayed to check the console where it reads "Cannot read property 'offsetTop' of null"
My router configuration in nuxt.config (without it I wouldn't be even able to scroll to an anchored element being in the same site as the element!):
router: {
scrollBehavior(to) {
if (to.hash) {
return window.scrollTo({ top: document.querySelector(to.hash).offsetTop + window.innerHeight, behavior: 'smooth' });
}
return window.scrollTo({ top: 0, behavior: 'smooth' });
}
},
You have not defined the hash in your nuxt-link. Use:
<nuxt-link
v-else
class="text-link"
:to="{ path: localePath('index'), hash:`#${item.hash}` }"
>
I'm using Vue.js 2.3.3 with vue-router 2.5.3. I created a Navbar component that has bookmarks (or links) pointing to specific sections on the landing page, like so:
<router-link to="/#our-services" class="nav-item item is-tab">
Our Services <!-- Jumps to #our-services on the home page -->
</router-link>
I defined my router in the following way:
export default new VueRouter({
routes, // routes are defined in a var above...
mode: 'history',
scrollBehavior(to, from, savedPosition) {
if (to.hash) {
return { selector: to.hash }
} else {
return { x: 0, y: 0 }
}
},
linkActiveClass: 'is-active'
})
Now, this does seem work; if I click on "Our Services" link in the navbar, it jumps to #our-services. However:
If I scroll away from #our-services div element, and click on "Our Services" link again, it doesn't bring me back to the div; clicking on the link does not produce anything;
Moreover, the <a> element of the router-link retains the is-active class even though you scrolled away from the section; it would be nice to keep track of where you are on the page and adjust the is-active class on the link appropriately.
Any suggestions on how to solve these two problems? Should I listen to the scroll event in the second case? Thanks!
Whatever your scrolling object is (likely window), you should add an event listener to handle scroll events:
window.addEventListener('scroll', scrollHandler, false);
Your scrollhandler function should check whether there is a hash on the current window location, and if so, check whether the associated element is out of range, and if so, clear the hash.
I can't use the real location hash or window in a snippet, but this is kind of what you would want to do.
let hash = '#second';
const scrollingEl = document.querySelector('.scrollingArea');
function handleScrollEvent() {
if (hash) {
const winY = scrollingEl.scrollTop;
const hashElY = document.querySelector(hash).getBoundingClientRect().top;
if (hashElY < 0 || hashElY > winY + scrollingEl.height) {
hash = '';
}
console.log(winY, hashElY);
}
}
scrollingEl.addEventListener('scroll', handleScrollEvent, false);
.scrollingArea {
height: 400px;
overflow-y: scroll;
}
.scrollingArea>div {
height: 250px;
}
<div class="scrollingArea">
<div id="first">First</div>
<div id="second">Second</div>
<div id="third">Third</div>
<div id="fourth">Fourth</div>
</div>
We make use of modal component from https://github.com/yuche/vue-strap. When browser back button is clicked, the default behavior is back to previous path but the modal popup isn't closed. How can I change the behavior to close the modal popup upon browser's back button click event?
This helped me.
https://jessarcher.com/blog/closing-modals-with-the-back-button-in-a-vue-spa/
created() {
const backButtonRouteGuard = this.$router.beforeEach((to, from, next) => {
if (from.name == 'menu') {
/* Blocking back button in menu route */
next(false);
this.yourCallBackMethod()
} else {
/* allowing all other routes*/
next(true);
}
});
this.$once('hook:destroyed', () => {
backButtonRouteGuard();
});
},
methods: {
yourCallBackMethod() {
// Go to the previous step, or close the modal
}
},
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>