How do I change the URL of the page in Nuxt SSR mode without reloading the whole page?

13,253

Solution 1

Without reloading the page or refreshing the dom, history.pushState can do the job.
Add this method in your component or elsewhere to do that:

addHashToLocation(params) {
  history.pushState(
    {},
    null,
    this.$route.path + '#' + encodeURIComponent(params)
  )
}

So anywhere in your component, call addHashToLocation('/my/new/path') to push the current location with query params in the window.history stack.

To add query params to current location without pushing a new history entry, use history.replaceState instead.

Should work with Vue 2.6.10 and Nuxt 2.8.1.  

Be careful with this method!
Vue Router don't know that url has changed, so it doesn't reflect url after pushState.

As Vue Router doesn't reflect change, it's not possible to get params of url. So we have to handle a different logic to pass data between routes. This can be done with dedicated Vuex store, or simply with the Nuxt global bus events.

// main component
created() {
  // event fire when pushState
  this.$nuxt.$on('pushState', params => {
    // do your logic with params
  })
},
beforeDestroy() {
  this.$nuxt.$off('pushState')
},
...

// Where there are history.pushState
this.$nuxt.$emit('pushState', params)

Solution 2

you can try to split page in 2 parts: "/pages/arcticles.vue" and "/pages/arcticles/_id.vue". This approach similar with your first, list not reload list. With speed i don't know what to do. Resulting page size is 15Mb.

arcticles.vue

<template>
  <div class="root">
    <div class="left">
      <ul>
        <li v-for="i in sortedArticles" :key="i.feedItemId">
          <nuxt-link :to="'/articles/' + i.feedItemId">
            Article {{ i.title }}
          </nuxt-link>
        </li>
      </ul>
    </div>
    <nuxt-child class="right"></nuxt-child>
  </div>
</template>

arcticles/_id.vue

<template>
  <div>
    Article {{ $route.params.id }}
  </div>
</template>
Share:
13,253

Related videos on Youtube

PirateApp
Author by

PirateApp

Updated on September 15, 2022

Comments

  • PirateApp
    PirateApp over 1 year
    • I am trying to build a Master Detail View where list and detail are shown side by side on desktop but on different pages on mobile as shown in the image below
    • I may have between 500 to 10000 items on the list to display
    • I simulated both approaches with 10000 items, feel free to change the number in server/app.js file

    enter image description here

    • When I click on an item in the list, I want the URL to change so that I click back button I go to the previous button.
    • The page should not reload for doing this and it should be in SSR mode

    What have I tried?

    Approach 1 Dynamic Routes

    • Inside pages folder, I put an articles folder and _id.vue file and added a nuxt-link

    • This setup is VERY VERY slow, takes 20 seconds for the summary to change

    • Here is Approach 1 on CodeSandbox

    Approach 2 Custom @nuxtjs/router module with push

    • Instead of the default router, I tried using the custom @nuxtjs/module

    • Links are selected much much faster in this approach and the URL is also changing

    • However if I click on item 4877, it reloads the page and the scrollbar goes back to the top of the page?

    • How do I keep the scrollbar wherever it is or PREVENT reloading the page?

    • Here is Approach 2 on CodeSandbox with Custom Router

    Simple Question

    • What do I do in SSR mode to change the URL as I select an item in the list without reloading the page?
    • Which approach is better?
  • PirateApp
    PirateApp over 4 years
    upvoted! the only issue is that i cannot find out which id was selected anymore, $route.params.id is undefined, i guess this is what you were trying to say by vue router doesnt know url has changed, is there any way to get the id that was selected, also when moving back and forth, it doesnt scroll to the desired item
  • ManUtopiK
    ManUtopiK over 4 years
    Yes, $route.params doesn't reflect url after pushState. So, you have to pass data logic in a different way. You can use the store if you already have business logic here, but you can also use custom router events. I will edit my answer to explain that...