2

I use vue 3

I have a view that loads components inside it. Each time you click a text, router.push is called , and loads a component, with some params

click here
<h3 @click="handleClick('intro', 'abc')" >intro</h3>  
to load component here
<router-view></router-view>

the click is handled as such

  setup(){
     
    const router = useRouter();

    const handleClick = (part, term)=>{ 
      router.push({name:part, params: {term}}).catch(err => {}); 
    } 

    return{handleClick}
    
  } 

so router.push loads in <router-view> another smaller component (named intro), according to the router of the app, that is set like so

path: '/book',
name: 'book',
component: book,
children:[
  {
    path: 'intro/:term',
    name: 'intro',
    component: Intro
  }, 
]

The component is loaded inside the view and the url is like /book/intro/abc

inside the intro component, to handle the change in the route and scroll down the abc id , I do

const route = useRoute();
let id = false; 
let mounted = ref(false);

//grab the term from route, to set it as id and if component is mounted, scroll to id
watchEffect(()=>{
  id = route.params.term; 
  let el = document.getElementById(id);
  if (mounted && el) {
    el.scrollIntoView({behavior: "smooth"});
    id = false;
  }
}) 

//check if mounted and if also id that came from route exists, scroll to id
onMounted(() => {
  mounted = true;
  let el = document.getElementById(id);
  if (id && el) { 
    el.scrollIntoView({behavior: "smooth"});
    id = false;
  }
}) 

ISSUE This works and is based on the route, to load the component and also set the id where it will scroll to.

But if I scroll to an id, then scroll randomly in the page and then click the same id to scroll, it will NOT scroll to that id again, because the id does not change, so route does not fire another event.

example : The url is /book/intro/abc. If I scroll randomly and then click the abc , url is the same, no event is fired, it will not scroll back to abc again.

How do I fix this? I want to avoid having hashtags or queries or questionmarks in my urls. Ideally I want "clean" urls like /book/part/term and I want to load that part indicated by the url, inside the view, not having all the parts loaded inside the view, as a super long text .

EDIT I also want to avoid reloads

Thanks

codebot
  • 517
  • 8
  • 29
  • 55
  • If [you scroll](https://stackoverflow.com/a/68290633/8816585) to an ID, it should not update the URL IMO. Sorry if I'm wrong. – kissu Apr 27 '22 at 10:30
  • Well, if you had just HTML and some anchor like `go there `, it would update the url, with no refreshing and it would scroll there. I am trying to reproduce the same, using Vue 3 route, but if I click the same link twice, it will not scroll, because the url is the same and route does not fire a new event. – codebot Apr 27 '22 at 11:17
  • Hm, so you really didn't even gave a read to what I've linked in my previous comment. I've tried it and it's working fine on my side, using `template refs`. – kissu Apr 27 '22 at 11:21
  • @kissu does he even use nuxt? or does it work with vue3 too? – h0p3zZ Apr 27 '22 at 12:16
  • 1
    @h0p3zZ totally unrelated to Nuxt so far, I mean it's a regular Vue plugin. Nuxt requires a bit more config but you can skip this one and import it in Vue3 (regarding the docs). – kissu Apr 27 '22 at 12:19

1 Answers1

3

You can watch the whole route object and force the router change with the force option.

/* In the template */
<router-link :to="{ path: 'some-path', force: true }">link</router-link>
// In the script
const route = useRoute()
watch(() => route, () => {
  console.log('route changed')
}, {
  deep: true
})
Duannx
  • 7,501
  • 1
  • 26
  • 59
  • FYI, [it is mentioned](https://router.vuejs.org/api/interfaces/routelocationoptions.html#force) now. – benvd Dec 05 '22 at 11:03