Comment définir les paramètres de requête URL dans Vue avec Vue-Router

114

J'essaie de définir des paramètres de requête avec Vue-router lors de la modification des champs d'entrée, je ne veux pas accéder à une autre page mais je veux simplement modifier les paramètres de requête d'url sur la même page, je fais comme ceci:

this.$router.replace({ query: { q1: "q1" } })

Mais cela actualise également la page et définit la position y sur 0, c'est-à-dire qu'elle fait défiler vers le haut de la page. Est-ce la bonne façon de définir les paramètres de requête d'URL ou existe-t-il une meilleure façon de le faire?


Édité:

Voici mon code de routeur:

export default new Router({
  mode: 'history',
  scrollBehavior: (to, from, savedPosition)  => {
    if (to.hash) {
      return {selector: to.hash}
    } else {
      return {x: 0, y: 0}
    }
  },
  routes: [
    ....... 
    { path: '/user/:id', component: UserView },
  ]
})
Saurabh
la source

Réponses:

133

Voici l'exemple dans la documentation:

// with query, resulting in /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})

Réf: https://router.vuejs.org/en/essentials/navigation.html

Comme mentionné dans ces documents, router.replacefonctionne commerouter.push

Donc, vous semblez avoir raison dans votre exemple de code en question. Mais je pense que vous devrez peut-être inclure l'un nameou l' autre pathparamètre également, de sorte que le routeur ait un itinéraire vers lequel naviguer. Sans un nameou path, cela n'a pas l'air très significatif.

C'est ma compréhension actuelle maintenant:

  • query est facultatif pour le routeur - quelques informations supplémentaires pour que le composant construise la vue
  • nameou pathest obligatoire - il décide du composant à afficher dans votre <router-view>.

Cela pourrait être l'élément manquant dans votre exemple de code.

EDIT: Détails supplémentaires après commentaires

Avez-vous essayé d'utiliser des routes nommées dans ce cas? Vous avez des routes dynamiques et il est plus facile de fournir des paramètres et des requêtes séparément:

routes: [
    { name: 'user-view', path: '/user/:id', component: UserView },
    // other routes
]

puis dans vos méthodes:

this.$router.replace({ name: "user-view", params: {id:"123"}, query: {q1: "q1"} })

Techniquement, il n'y a pas de différence entre ce qui précède et this.$router.replace({path: "/user/123", query:{q1: "q1"}}), mais il est plus facile de fournir des paramètres dynamiques sur des routes nommées que de composer la chaîne de route. Mais dans les deux cas, les paramètres de requête doivent être pris en compte. Dans les deux cas, je n'ai rien trouvé de mal dans la façon dont les paramètres de requête sont traités.

Une fois que vous êtes à l'intérieur de la route, vous pouvez récupérer vos paramètres dynamiques en tant que this.$route.params.idet vos paramètres de requête en tant que this.$route.query.q1.

Mani
la source
J'ai également essayé de donner le chemin, mais cela n'a pas arrêté de défiler vers le haut de la page, j'ai également modifié la question avec les options du routeur, peut-être qu'il y a un changement nécessaire.
Saurabh
Votre paramètre de requête est-il destiné à faire défiler jusqu'au bon endroit dans le document? Vous aimez votre autre question sur les balises d'ancrage ?
Mani
Non, je veux juste ajouter le paramètre de requête dans l'URL, je ne veux pas de défilement ici.
Saurabh
Je viens de tester les options dans ma configuration locale, les paramètres de requête fonctionnent normalement. Je peux naviguer vers une nouvelle route et accéder aux paramètres de requête comme indiqué dans ma réponse mise à jour. Donc, le problème est - vous ne voulez pas qu'il défile? Ou le problème est-il que toute l'application se rafraîchit à nouveau?
Mani
donc je suis sur la même page, quand je sélectionne une entrée, je veux les ajouter dans l'URL, mais quand je le fais, le défilement se produit. Le défilement est le problème pour moi. Je n'essaye pas de naviguer vers une autre page, je veux juste être sur la même page et ajouter / modifier les paramètres de requête d'url sans problème.
Saurabh
16

Sans recharger la page ou actualiser le dom, history.pushStatepeut faire le travail.
Ajoutez cette méthode dans votre composant ou ailleurs pour ce faire:

addParamsToLocation(params) {
  history.pushState(
    {},
    null,
    this.$route.path +
      '?' +
      Object.keys(params)
        .map(key => {
          return (
            encodeURIComponent(key) + '=' + encodeURIComponent(params[key])
          )
        })
        .join('&')
  )
}

Donc, n'importe où dans votre composant, appelez addParamsToLocation({foo: 'bar'})pour pousser l'emplacement actuel avec les paramètres de requête dans la pile window.history.

Pour ajouter des paramètres de requête à l'emplacement actuel sans pousser une nouvelle entrée d' historique , utilisez à la history.replaceStateplace.

Testé avec Vue 2.6.10 et Nuxt 2.8.1.

Soyez prudent avec cette méthode!
Vue Router ne sait pas que l'URL a changé, elle ne reflète donc pas l'URL après pushState.

ManUtopiK
la source
5
this.$router.push({ query: Object.assign(this.$route.query, { new: 'param' }) })
Boston Kenne
la source
1
J'ai aimé cette réponse le plus. Malheureusement, cela provoqueError: Avoided redundant navigation to current location
Max Coplan
Correction:this.$router.push({ query: Object.assign({...this.$route.query}, { new: 'param' }) })
Max Coplan
2
Mais maintenant que j'y pense, vous pouvez le fairethis.$router.push({ query: {...this.$route.query,new: 'param'},) })
Max Coplan
3

Si vous essayez de conserver certains paramètres, tout en modifiant d'autres, assurez-vous de copier l'état de la requête du routeur de vue et de ne pas la réutiliser.

Cela fonctionne, puisque vous faites une copie non référencée:

  const query = Object.assign({}, this.$route.query);
  query.page = page;
  query.limit = rowsPerPage;
  await this.$router.push({ query });

tandis que ci-dessous conduira Vue Router à penser que vous réutilisez la même requête et conduira à l' NavigationDuplicatederreur:

  const query = this.$route.query;
  query.page = page;
  query.limit = rowsPerPage;
  await this.$router.push({ query });

Bien sûr, vous pouvez décomposer l'objet de requête, comme suit, mais vous devez connaître tous les paramètres de requête de votre page, sinon vous risquez de les perdre dans la navigation résultante.

  const { page, limit, ...otherParams } = this.$route.query;
  await this.$router.push(Object.assign({
    page: page,
    limit: rowsPerPage
  }, otherParams));
);

Notez que bien que l'exemple ci-dessus soit pour push(), cela fonctionne replace()aussi avec .

Testé avec vue-router 3.1.6.

André M
la source
3

Pour ajouter plusieurs paramètres de requête, c'est ce qui a fonctionné pour moi (à partir d'ici https://forum.vuejs.org/t/vue-router-programmatically-append-to-querystring/3655/5 ).

une réponse ci-dessus était proche ... bien qu'avec Object.assign, cela muterait. $ route.query ce qui n'est pas ce que vous voulez faire ... assurez-vous que le premier argument est {} lorsque vous faites Object.assign

this.$router.push({ query: Object.assign({}, this.$route.query, { newKey: 'newValue' }) });
Boris
la source
2

Pour définir / supprimer plusieurs paramètres de requête à la fois, je me suis retrouvé avec les méthodes ci-dessous dans le cadre de mes mixins globaux ( thispoint vers le composant vue):

    setQuery(query){
        let obj = Object.assign({}, this.$route.query);

        Object.keys(query).forEach(key => {
            let value = query[key];
            if(value){
                obj[key] = value
            } else {
                delete obj[key]
            }
        })
        this.$router.replace({
            ...this.$router.currentRoute,
            query: obj
        })
    },

    removeQuery(queryNameArray){
        let obj = {}
        queryNameArray.forEach(key => {
            obj[key] = null
        })
        this.setQuery(obj)
    },
virus
la source
1

J'utilise normalement l'objet historique pour cela. Il ne recharge pas non plus la page.

Exemple:

history.pushState({}, '', 
                `/pagepath/path?query=${this.myQueryParam}`);
Mostafa
la source
0

Voici ma solution simple pour mettre à jour les paramètres de requête dans l'URL sans actualiser la page. Assurez-vous que cela fonctionne pour votre cas d'utilisation.

const query = { ...this.$route.query, someParam: 'some-value' };
this.$router.replace({ query });
parker_codes
la source