Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Silently update url without triggering route in vue-router

I need to update the hash of the url, without actually triggering the vue-router to go to that route. Something in the likes of:

router.replace('my/new/path', {silent:true})

This would update the url to .../#/my/new/path, but the router itself would not route to that path.

Is there an elegant way to achieve this?

like image 996
Rinux Avatar asked Jul 14 '18 09:07

Rinux


People also ask

How do I change my URL in vue?

To navigate to a different URL, use router. push . This method pushes a new entry into the history stack, so when the user clicks the browser back button they will be taken to the previous URL.

How do you update data on a page without refreshing on the vue JS?

Another solution explained in vue-router doc. Simply use the watch system applied to the $route native attribute. You'll be able to detect new route even if they use the same component and fetch the data in consequence.

Can vue router open a link in a new tab?

Opening the link in a new tab To open the link in a new tab, we need to add the target attribute with a value _blank to the <router-link> component.

How do I refresh my vue router?

To reload a route with Vue Route, we can call the this. $router.go() method. If it has no arguments, then it'll reload the current route. This way, it'll notice when the path changes and it'll trigger a reload of the component with new data.


3 Answers

Without reloading the page or refreshing the DOM, history.pushState can do the job.

For example: add this method in your component or elsewhere to do that:

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

Then anywhere in your component you can call addHashToLocation('/my/new/path') to push query params to the window.history stack.

To add query parameters 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, as Vue Router does not know that the URL has changed.

like image 140
ManUtopiK Avatar answered Oct 16 '22 12:10

ManUtopiK


The Vue router is either on or off, so you cannot "make it not detect certain urls". That said, Vue does re-use components if it doesn't need to destroy them and allows you to alias urls. This allows you to have the urls from your iframe application as aliases in your route, and keep the same component alive during that time, preventing your iframe from getting reloaded.

// router.js
import Comp1 from "./components/Comp1";
import Comp2 from "./components/Comp2";

export default [
  {
    path: "/route1",
    component: Comp1,
    alias: ["/route2", "/route3", "/route4"]
  },
  {
    path: "/otherroute",
    component: Comp2
  }
];
// main.js
import Vue from "vue";
import App from "./App";
import VueRouter from "vue-router";
import routes from "./router";

Vue.config.productionTip = false;
Vue.use(VueRouter);

const router = new VueRouter({
  routes
});

/* eslint-disable no-new */
new Vue({
  el: "#app",
  router,
  components: { App },
  template: "<App/>"
});

In this example, route1, route2, route3 and route4 will all be treated as if route1 has to be loaded, causing your component Comp1 to stay alive.

Edit Vue Template

like image 10
Sumurai8 Avatar answered Oct 16 '22 13:10

Sumurai8


if what you are trying to do is update the url to show the page state (perhaps something like ?search=something) then you can do a trick like this. the key idea is using a toggle this.respondToRouteChanges to ignore changes when the url is updated by your code.

when updating the route (eg. in a vue method in your component)

          this.respondToRouteChanges = false;
          this.$router.replace({query: { search: this.search })
              .finally(() => {
                this.respondToRouteChanges = true;
              });

and in the component code that would normally watch/handle changes to the route

    setSearch() {
      if (!this.respondToRouteChanges){
        // console.log('ignoring since route changes ignored')
        return;
      }
      if (this.search !== this.querySearch)
        this.search = this.querySearch;
    },

  watch: {
     // watch for changes in the url
    'querySearch': 'setSearch',

note that respondToRouteChanges is just a boolean defined as data() in the component

  data() {
    return {
      respondToRouteChanges: true,
      ...

querySearch is just a computed value which returns the route

    querySearch() {
      return this.$route.query.search || '';
    },
like image 5
Tom Carchrae Avatar answered Oct 16 '22 12:10

Tom Carchrae