Come impostare i parametri di query dell'URL in Vue con Vue-Router


114

Sto cercando di impostare i parametri di query con Vue-router quando modifico i campi di input, non voglio navigare in un'altra pagina ma voglio solo modificare i parametri di query dell'URL sulla stessa pagina, sto facendo così:

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

Ma questo aggiorna anche la pagina e imposta la posizione y su 0, cioè scorre fino all'inizio della pagina. È questo il modo corretto per impostare i parametri della query dell'URL o esiste un modo migliore per farlo.


Modificato:

Ecco il codice del mio router:

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 },
  ]
})

Risposte:


132

Ecco l'esempio nei documenti:

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

Rif: https://router.vuejs.org/en/essentials/navigation.html

Come accennato in quei documenti, router.replacefunziona comerouter.push

Quindi, sembra che tu abbia ragione nel tuo codice di esempio in questione. Ma penso che potrebbe essere necessario includere anche il parametro nameo path, in modo che il router abbia un percorso verso cui navigare. Senza un nameo path, non sembra molto significativo.

Questa è la mia comprensione attuale ora:

  • query è opzionale per il router: alcune informazioni aggiuntive per il componente per costruire la vista
  • nameo pathè obbligatorio: decide quale componente mostrare nel tuo file <router-view>.

Questa potrebbe essere la cosa mancante nel tuo codice di esempio.

EDIT: ulteriori dettagli dopo i commenti

Hai provato a utilizzare percorsi denominati in questo caso? Hai percorsi dinamici ed è più facile fornire parametri e query separatamente:

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

e poi nei tuoi metodi:

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

Tecnicamente non c'è differenza tra quanto sopra e this.$router.replace({path: "/user/123", query:{q1: "q1"}}), ma è più facile fornire parametri dinamici sulle rotte nominate che comporre la stringa della rotta. Ma in entrambi i casi, è necessario tenere in considerazione i parametri della query. In entrambi i casi, non sono riuscito a trovare nulla di sbagliato nel modo in cui vengono gestiti i parametri delle query.

Dopo essere entrato nel percorso, puoi recuperare i tuoi parametri dinamici come this.$route.params.ide i parametri della query come this.$route.query.q1.


Ho provato a dare anche il percorso, ma questo non ha smesso di scorrere fino all'inizio della pagina, ho modificato la domanda anche con le opzioni del router, potrebbe essere necessario qualche cambiamento lì.
Saurabh

Il parametro della query è destinato a scorrere fino al punto giusto nel documento? Come l'altra tua domanda sui tag di ancoraggio ?
Mani

No, voglio solo aggiungere il parametro della query nell'URL, non voglio alcuno scorrimento qui.
Saurabh

Ho appena testato le opzioni nella mia configurazione locale, i parametri della query funzionano normalmente. Sono in grado di navigare su una nuova rotta e accedere ai parametri della query come mostrato nella mia risposta aggiornata. Quindi, il problema è: non vuoi che scorra? O il problema è che l'intera app si aggiorna di nuovo?
Mani

quindi sono sulla stessa pagina, quando seleziono degli input, voglio aggiungerli nell'URL, ma quando lo faccio, lo scorrimento avviene. Lo scorrimento è il problema per me. Non sto cercando di passare a un'altra pagina, voglio solo essere sulla stessa pagina e aggiungere / modificare i parametri della query dell'URL in modo apparentemente invisibile.
Saurabh

15

Senza ricaricare la pagina o aggiornare il dom, history.pushStatepuò fare il lavoro.
Aggiungi questo metodo nel tuo componente o altrove per farlo:

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

Quindi, ovunque nel tuo componente, chiama addParamsToLocation({foo: 'bar'})per eseguire il push della posizione corrente con i parametri della query nello stack window.history.

Per aggiungere i parametri della query alla posizione corrente senza premere una nuova voce della cronologia , utilizzare history.replaceStateinvece.

Testato con Vue 2.6.10 e Nuxt 2.8.1.

Stai attento con questo metodo!
Vue Router non sa che l'URL è cambiato, quindi non riflette l'URL dopo pushState.



5
this.$router.push({ query: Object.assign(this.$route.query, { new: 'param' }) })

1
Questa risposta mi è piaciuta di più. Sfortunatamente questo causaError: Avoided redundant navigation to current location
Max Coplan

Correzione:this.$router.push({ query: Object.assign({...this.$route.query}, { new: 'param' }) })
Max Coplan

2
Ma ora che ci penso, puoi farlothis.$router.push({ query: {...this.$route.query,new: 'param'},) })
Max Coplan,

3

Se stai cercando di mantenere alcuni parametri, mentre ne modifichi altri, assicurati di copiare lo stato della query del router vue e non riutilizzarlo.

Funziona, dal momento che stai facendo una copia senza riferimenti:

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

mentre sotto porterà Vue Router a pensare che stai riutilizzando la stessa query e porterà NavigationDuplicatedall'errore:

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

Certo, potresti scomporre l'oggetto query, come segue, ma dovrai essere a conoscenza di tutti i parametri di query della tua pagina, altrimenti rischi di perderli nella navigazione risultante.

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

Nota, sebbene l'esempio sopra sia per push(), funziona replace()anche con .

Testato con vue-router 3.1.6.


3

Per l'aggiunta di più parametri di query, questo è ciò che ha funzionato per me (da qui https://forum.vuejs.org/t/vue-router-programmatical-append-to-querystring/3655/5 ).

una risposta sopra era vicina ... anche se con Object.assign cambierà questo. $ route.query che non è quello che vuoi fare ... assicurati che il primo argomento sia {} quando esegui Object.assign

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

2

Per impostare / rimuovere più parametri di query contemporaneamente, ho finito con i metodi seguenti come parte dei miei mixin globali ( thispunta al componente 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)
    },

1

Normalmente uso l'oggetto della cronologia per questo. Inoltre non ricarica la pagina.

Esempio:

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

0

Ecco la mia semplice soluzione per aggiornare i parametri della query nell'URL senza aggiornare la pagina. Assicurati che funzioni per il tuo caso d'uso.

const query = { ...this.$route.query, someParam: 'some-value' };
this.$router.replace({ query });
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.