vuejs / vue-router

🚦 The official router for Vue 2
http://v3.router.vuejs.org/
MIT License
18.99k stars 5.06k forks source link

Detect when the user changes the URL on the address bar by manually typing it #3873

Closed jfmdev closed 10 months ago

jfmdev commented 10 months ago

Is there an easy way to detect when the user changes the URL on address bar by manually typing something (and then pressing Enter)?

I'm aware that you can add a watcher to $route, and be notified every time the URL changes, but this method doesn't allows you to differentiate when the URL was changed because your code called this.$router.replace() or because the user edited the address bar.


Additional context: I have an screen that opens with URL /#/products, and that contains a text input to search for products. By default the input is empty and the screen display all products.
If the user writes "food" on the input, the application will execute an AJAX request (to fetch products that contain the word "food") and the URL will be updated to #/products?search=food.
If then the user reloads the page, then the application (on the mounted hook) will read $route.query.search to populate the search input (with "food" on this case) and to only display the products that matches the search criteria.
The requirement I have is that if the user edits the address bar (e.g. changing #/products?search=food to #/products?search=electronics) the application should detect the change and execute an AJAX request to update the list of products.

Currently I'm using a flag, to indicate when the URL was changed my code, but I would like to know if the library has some built-in method that does the same:

watch: {
  $route() {
    // Check if the change was done externally.
    if (!this.internalRouteUpdate) {
      // Re-fetch list of products.
      const search = this.$route.query?.search || "";
      this.fetchProducts(search);
    } else {
      // Reset flag.
      this.internalRouteUpdate = false;
    }
  }
},

methods: {
  fetchProducts(search) {
    // ...execute AJAX request ...//

    // Replace URL and update flag.
    this.$router.replace(newLocation, () => {
      this.internalRouteUpdate = true;
    });
  },

On this particular case, instead of using the internalRouteUpdate flag, I could just simply do if(this.$route.query?.search !== currentSearch) this.fetchProducts(...);, however that comparison will become complex once I start adding more filtering options to the screen.

posva commented 10 months ago

Hi, thanks for your interest but Github issues are for bug reports and feature requests only. You can ask questions on the forum, the Discord server or StackOverflow.