Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

  • 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?
like image 777
PirateApp Avatar asked Oct 19 '19 15:10

PirateApp


2 Answers

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)
like image 175
ManUtopiK Avatar answered Sep 23 '22 05:09

ManUtopiK


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>
like image 22
TenshiGoan Avatar answered Sep 20 '22 05:09

TenshiGoan