Como definir parâmetros de consulta de URL no Vue com Vue-Router


114

Estou tentando definir parâmetros de consulta com Vue-router ao alterar os campos de entrada, não quero navegar para outra página, mas apenas modificar os parâmetros de consulta de url na mesma página, estou fazendo assim:

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

Mas isso também atualiza a página e define a posição y para 0, ou seja, rola para o topo da página. Esta é a maneira correta de definir os parâmetros de consulta de URL ou existe uma maneira melhor de fazer isso.


Editado:

Aqui está o código do meu roteador:

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

Respostas:


132

Aqui está o exemplo em docs:

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

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

Conforme mencionado nesses documentos, router.replacefunciona comorouter.push

Então, você parece ter acertado em seu código de amostra em questão. Mas acho que você pode precisar incluir o parâmetro nameou pathtambém, para que o roteador tenha alguma rota para navegar. Sem um nameou path, não parece muito significativo.

Este é meu entendimento atual agora:

  • query é opcional para o roteador - algumas informações adicionais para o componente construir a visão
  • nameou pathé obrigatório - ele decide qual componente mostrar em seu <router-view>.

Isso pode ser o que está faltando em seu código de amostra.

EDIT: detalhes adicionais após comentários

Você já tentou usar rotas nomeadas neste caso? Você tem rotas dinâmicas e é mais fácil fornecer parâmetros e consultas separadamente:

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

e então em seus métodos:

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

Tecnicamente, não há diferença entre o acima e this.$router.replace({path: "/user/123", query:{q1: "q1"}}), mas é mais fácil fornecer parâmetros dinâmicos em rotas nomeadas do que compor a string de rota. Mas em ambos os casos, os parâmetros de consulta devem ser levados em consideração. Em qualquer dos casos, não consegui encontrar nada de errado com a forma como os parâmetros de consulta são tratados.

Depois de estar dentro da rota, você pode buscar seus parâmetros dinâmicos como this.$route.params.ide seus parâmetros de consulta como this.$route.query.q1.


Tentei indicar o caminho também, mas não parava de rolar para o topo da página, editei a pergunta com as opções do roteador também, pode ser que haja alguma alteração necessária aí.
— Saurabh

O seu parâmetro de consulta pretende rolar para o lugar certo no documento? Gostou da sua outra pergunta sobre tags âncora ?
— Mani

Não, eu só quero adicionar o parâmetro de consulta na URL, não quero nenhum scroll aqui.
— Saurabh

Acabei de testar as opções na minha configuração local, os parâmetros de consulta funcionam normalmente. Consigo navegar para uma nova rota e acessar os parâmetros de consulta, conforme mostrado na minha resposta atualizada. Então, o problema é - você não quer que ele role? Ou o problema é que todo o aplicativo está sendo atualizado novamente?
— Mani

então estou na mesma página, quando seleciono alguma entrada, quero adicioná-la na URL, mas quando faço isso, acontece a rolagem. Rolar é o problema para mim. Não estou tentando navegar para outra página, apenas quero estar na mesma página e adicionar / modificar parâmetros de consulta de url sem problemas.
— Saurabh

15

Sem recarregar a página ou atualizar o dom, history.pushStatepode fazer o trabalho.
Adicione este método em seu componente ou em outro lugar para fazer isso:

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

Portanto, em qualquer lugar em seu componente, chame addParamsToLocation({foo: 'bar'})para enviar o local atual com parâmetros de consulta na pilha window.history.

Para adicionar parâmetros de consulta à localização atual sem empurrar uma nova entrada de histórico , use history.replaceState.

Testado com Vue 2.6.10 e Nuxt 2.8.1.

Cuidado com este método!
O Vue Router não sabe que o url mudou, então ele não reflete o url após pushState.



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

1
Gostei mais dessa resposta. Infelizmente, isso causaError: Avoided redundant navigation to current location
— Max Coplan

Correção:this.$router.push({ query: Object.assign({...this.$route.query}, { new: 'param' }) })
— Max Coplan

2
Mas agora que pensei sobre isso, você pode simplesmente fazerthis.$router.push({ query: {...this.$route.query,new: 'param'},) })
— Max Coplan

3

Se você estiver tentando manter alguns parâmetros, enquanto altera outros, certifique-se de copiar o estado da consulta do roteador vue e não reutilizá-la.

Isso funciona, pois você está fazendo uma cópia sem referência:

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

enquanto abaixo irá fazer com que o Vue Router pense que você está reutilizando a mesma consulta e levará ao NavigationDuplicatederro:

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

Claro, você pode decompor o objeto de consulta, como a seguir, mas você precisa estar ciente de todos os parâmetros de consulta de sua página, caso contrário, você corre o risco de perdê-los na navegação resultante.

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

Observe que, embora o exemplo acima seja para push(), ele também funciona com replace().

Testado com vue-router 3.1.6.


3

Para adicionar vários parâmetros de consulta, isso é o que funcionou para mim (aqui https://forum.vuejs.org/t/vue-router-programmatically-append-to-querystring/3655/5 ).

uma resposta acima estava perto ... embora com Object.assign ele irá transformar este. $ route.query que não é o que você deseja fazer ... certifique-se de que o primeiro argumento é {} ao fazer Object.assign

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

2

Para definir / remover vários parâmetros de consulta de uma vez, acabei com os métodos abaixo como parte dos meus mixins globais ( thisaponta para o 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

Eu normalmente uso o objeto de histórico para isso. Também não recarrega a página.

Exemplo:

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

0

Esta é minha solução simples para atualizar os parâmetros de consulta na URL sem atualizar a página. Certifique-se de que funciona para o seu caso de uso.

const query = { ...this.$route.query, someParam: 'some-value' };
this.$router.replace({ query });
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.