Cómo configurar parámetros de consulta de URL en Vue con Vue-Router

114

Estoy tratando de establecer parámetros de consulta con Vue-enrutador al cambiar los campos de entrada, no quiero navegar a otra página, pero solo quiero modificar los parámetros de consulta de URL en la misma página, estoy haciendo lo siguiente:

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

Pero esto también actualiza la página y establece la posición y en 0, es decir, se desplaza hasta la parte superior de la página. ¿Es esta la forma correcta de configurar los parámetros de consulta de URL o hay una mejor manera de hacerlo?


Editado:

Aquí está mi código de enrutador:

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
fuente

Respuestas:

132

Aquí está el ejemplo en documentos:

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

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

Como se menciona en esos documentos, router.replacefunciona comorouter.push

Entonces, parece que lo tiene bien en su código de muestra en cuestión. Pero creo que es posible que deba incluir el parámetro nameo pathtambién, para que el enrutador tenga alguna ruta para navegar. Sin una nameo path, no parece muy significativo.

Este es mi entendimiento actual ahora:

  • query es opcional para el enrutador: alguna información adicional para el componente para construir la vista
  • nameo pathes obligatorio: decide qué componente mostrar en su <router-view>.

Eso podría ser lo que falta en su código de muestra.

EDITAR: Detalles adicionales después de los comentarios

¿Ha intentado utilizar rutas con nombre en este caso? Tiene rutas dinámicas y es más fácil proporcionar parámetros y consultas por separado:

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

y luego en tus métodos:

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

Técnicamente, no hay diferencia entre los anteriores y this.$router.replace({path: "/user/123", query:{q1: "q1"}}), pero es más fácil proporcionar parámetros dinámicos en rutas con nombre que componer la cadena de ruta. Pero en cualquier caso, se deben tener en cuenta los parámetros de consulta. En cualquier caso, no pude encontrar nada malo en la forma en que se manejan los parámetros de consulta.

Una vez que esté dentro de la ruta, puede recuperar sus parámetros dinámicos como this.$route.params.idy sus parámetros de consulta como this.$route.query.q1.

Mani
fuente
Intenté dar la ruta también, pero esto no dejó de desplazarme hasta la parte superior de la página, también he editado la pregunta con las opciones del enrutador, es posible que se necesite algún cambio allí.
Saurabh
¿Su parámetro de consulta está destinado a desplazarse al lugar correcto en el documento? ¿Te gusta tu otra pregunta sobre las etiquetas de anclaje ?
Mani
No, solo quiero agregar el parámetro de consulta en la URL, no quiero ningún desplazamiento aquí.
Saurabh
Acabo de probar las opciones en mi configuración local, los parámetros de consulta funcionan normalmente. Puedo navegar a una nueva ruta y acceder a los parámetros de consulta como se muestra en mi respuesta actualizada. Entonces, el problema es: ¿no quieres que se desplace? ¿O el problema es que toda la aplicación se actualiza nuevamente?
Mani
entonces estoy en la misma página, cuando selecciono alguna entrada, quiero agregarla en la URL, pero cuando lo hago, ocurre el desplazamiento. El desplazamiento es el problema para mí. No estoy tratando de navegar a otra página, solo quiero estar en la misma página y agregar / modificar parámetros de consulta de URL sin problemas.
Saurabh
15

Sin recargar la página o actualizar el dom, history.pushStatepuede hacer el trabajo.
Agregue este método en su componente o en otro lugar para hacer eso:

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

Entonces, en cualquier parte de su componente, llame addParamsToLocation({foo: 'bar'})para enviar la ubicación actual con parámetros de consulta en la pila window.history.

Para agregar parámetros de consulta a la ubicación actual sin presionar una nueva entrada de historial , use history.replaceStateen su lugar.

Probado con Vue 2.6.10 y Nuxt 2.8.1.

¡Cuidado con este método!
Vue Router no sabe que la URL ha cambiado, por lo que no refleja la URL después de pushState.

ManUtopiK
fuente
5
this.$router.push({ query: Object.assign(this.$route.query, { new: 'param' }) })
Boston Kenne
fuente
1
Me gustó más esta respuesta. Desafortunadamente, esto causaError: Avoided redundant navigation to current location
Max Coplan
Arreglo:this.$router.push({ query: Object.assign({...this.$route.query}, { new: 'param' }) })
Max Coplan
2
Pero ahora que lo pienso, puedes hacerlothis.$router.push({ query: {...this.$route.query,new: 'param'},) })
Max Coplan
3

Si está tratando de mantener algunos parámetros, mientras cambia otros, asegúrese de copiar el estado de la consulta del enrutador vue y no reutilizarlo.

Esto funciona, ya que está haciendo una copia sin referencia:

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

mientras que a continuación, hará que Vue Router piense que está reutilizando la misma consulta y producirá el NavigationDuplicatederror:

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

Por supuesto, puede descomponer el objeto de consulta, como se indica a continuación, pero deberá conocer todos los parámetros de consulta de su página; de lo contrario, corre el riesgo de perderlos en la navegación resultante.

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

Tenga en cuenta que, aunque el ejemplo anterior es para push(), esto también funciona con replace().

Probado con vue-router 3.1.6.

Andre M
fuente
3

Para agregar múltiples parámetros de consulta, esto es lo que funcionó para mí (desde aquí https://forum.vuejs.org/t/vue-router-programmatic-append-to-querystring/3655/5 ).

una respuesta anterior fue cercana ... aunque con Object.assign mutará this. $ route.query que no es lo que quieres hacer ... asegúrate de que el primer argumento sea {} al hacer Object.assign

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

Para establecer / eliminar múltiples parámetros de consulta a la vez, terminé con los métodos a continuación como parte de mis mixins globales ( thisapunta 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)
    },
virus
fuente
1

Normalmente uso el objeto de historial para esto. Tampoco recarga la página.

Ejemplo:

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

Esta es mi solución simple para actualizar los parámetros de consulta en la URL sin actualizar la página. Asegúrese de que funcione para su caso de uso.

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