So legen Sie URL-Abfrageparameter in Vue mit Vue-Router fest

113

Ich versuche, Abfrageparameter mit dem Vue-Router festzulegen, wenn Eingabefelder geändert werden. Ich möchte nicht zu einer anderen Seite navigieren, sondern nur URL-Abfrageparameter auf derselben Seite ändern. Ich mache das wie folgt:

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

Dies aktualisiert aber auch die Seite und setzt die y-Position auf 0, dh es wird zum oberen Rand der Seite gescrollt. Ist dies der richtige Weg, um die URL-Abfrageparameter festzulegen, oder gibt es einen besseren Weg, dies zu tun?


Bearbeitet:

Hier ist mein Router-Code:

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
quelle

Antworten:

130

Hier ist das Beispiel in Dokumenten:

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

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

Wie in diesen Dokumenten erwähnt, router.replacefunktioniert wierouter.push

Sie scheinen es also richtig in Ihrem fraglichen Beispielcode zu haben. Ich denke jedoch, dass Sie möglicherweise auch einen nameoder einen pathParameter einschließen müssen , damit der Router über eine Route verfügt, zu der er navigieren kann. Ohne ein nameoder pathsieht es nicht sehr aussagekräftig aus.

Dies ist mein derzeitiges Verständnis:

  • query ist für den Router optional - einige zusätzliche Informationen für die Komponente zum Erstellen der Ansicht
  • nameoder pathist obligatorisch - es entscheidet, welche Komponente in Ihrem angezeigt werden soll <router-view>.

Dies könnte das fehlende Element in Ihrem Beispielcode sein.

EDIT: Zusätzliche Details nach Kommentaren

Haben Sie in diesem Fall versucht, benannte Routen zu verwenden? Sie haben dynamische Routen und es ist einfacher, Parameter und Abfragen separat bereitzustellen:

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

und dann in Ihren Methoden:

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

Technisch gibt es keinen Unterschied zwischen den oben genannten und this.$router.replace({path: "/user/123", query:{q1: "q1"}}), aber es ist einfacher, dynamische Parameter auf benannten Routen anzugeben, als die Routenzeichenfolge zu erstellen. In beiden Fällen sollten jedoch Abfrageparameter berücksichtigt werden. In beiden Fällen konnte ich keine Fehler bei der Behandlung von Abfrageparametern feststellen.

Nachdem Sie sich innerhalb der Route befinden, können Sie Ihre dynamischen Parameter als this.$route.params.idund Ihre Abfrageparameter als abrufen this.$route.query.q1.

Mani
quelle
Ich habe auch versucht, den Pfad anzugeben, aber dies hat nicht aufgehört, zum Anfang der Seite zu scrollen. Ich habe die Frage auch mit Router-Optionen bearbeitet. Möglicherweise sind dort einige Änderungen erforderlich.
Saurabh
Soll Ihr Abfrageparameter an die richtige Stelle im Dokument scrollen? Wie Ihre andere Frage zu Ankertags ?
Mani
Nein, ich möchte nur den Abfrageparameter in die URL einfügen. Ich möchte hier keinen Bildlauf durchführen.
Saurabh
Ich habe gerade die Optionen in meinem lokalen Setup getestet. Die Abfrageparameter funktionieren normal. Ich kann zu einer neuen Route navigieren und auf Abfrageparameter zugreifen, wie in meiner aktualisierten Antwort gezeigt. Das Problem ist also - Sie möchten nicht, dass es scrollt? Oder ist das Problem, dass die gesamte App erneut aktualisiert wird?
Mani
Wenn ich also eine Eingabe auswähle, möchte ich sie auf derselben Seite zur URL hinzufügen. Wenn ich dies jedoch tue, wird ein Bildlauf durchgeführt. Scroll ist das Problem für mich. Ich versuche nicht, zu einer anderen Seite zu navigieren, sondern möchte nur auf derselben Seite sein und URL-Abfrageparameter scheinbar nahtlos hinzufügen / ändern.
Saurabh
14

Ohne die Seite neu zu laden oder den Dom zu aktualisieren, history.pushStatekann der Job erledigt werden.
Fügen Sie diese Methode in Ihre Komponente oder anderswo ein, um dies zu tun:

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

Rufen Sie also irgendwo in Ihrer Komponente auf, addParamsToLocation({foo: 'bar'})um den aktuellen Speicherort mit Abfrageparametern im Fenster window.history zu verschieben.

Verwenden Sie stattdessen , um dem aktuellen Speicherort Abfrageparameter hinzuzufügen, ohne einen neuen Verlaufseintraghistory.replaceState zu verschieben.

Getestet mit Vue 2.6.10 und Nuxt 2.8.1.

Seien Sie vorsichtig mit dieser Methode!
Vue Router weiß nicht, dass sich die URL geändert hat, sodass sie die URL nach pushState nicht wiedergibt.

ManUtopiK
quelle
4
this.$router.push({ query: Object.assign(this.$route.query, { new: 'param' }) })
Boston Kenne
quelle
1
Diese Antwort hat mir am besten gefallen. Leider verursacht diesError: Avoided redundant navigation to current location
Max Coplan
Fix:this.$router.push({ query: Object.assign({...this.$route.query}, { new: 'param' }) })
Max Coplan
2
Aber jetzt, wo ich darüber nachdenke, können Sie es einfach tunthis.$router.push({ query: {...this.$route.query,new: 'param'},) })
Max Coplan
3

Wenn Sie versuchen, einige Parameter beizubehalten, während Sie andere ändern, müssen Sie den Status der Vue-Router-Abfrage kopieren und nicht wiederverwenden.

Dies funktioniert, da Sie eine nicht referenzierte Kopie erstellen:

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

Der folgende Abschnitt führt dazu, dass Vue Router denkt, dass Sie dieselbe Abfrage wiederverwenden, und führt zu dem NavigationDuplicatedFehler:

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

Natürlich können Sie das Abfrageobjekt wie folgt zerlegen, aber Sie müssen alle Abfrageparameter Ihrer Seite kennen, da Sie sonst riskieren, sie in der resultierenden Navigation zu verlieren.

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

Beachten Sie, dass das obige Beispiel zwar für gilt push(), dies jedoch auch funktioniert replace().

Getestet mit vue-router 3.1.6.

Andre M.
quelle
3

Für das Hinzufügen mehrerer Abfrageparameter hat dies bei mir funktioniert (von hier aus https://forum.vuejs.org/t/vue-router-programmatisch-append-to-querystring/3655/5 ).

Eine Antwort oben war knapp ... obwohl sie mit Object.assign dies mutiert. $ route.query, was nicht das ist, was Sie tun möchten ... stellen Sie sicher, dass das erste Argument {} ist, wenn Sie Object.assign ausführen

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

Um mehrere Abfrageparameter gleichzeitig festzulegen / zu entfernen, habe ich im Rahmen meiner globalen Mixins ( thisPunkte zur Vue-Komponente) die folgenden Methoden verwendet :

    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
quelle
1

Normalerweise verwende ich dafür das Verlaufsobjekt. Die Seite wird auch nicht neu geladen.

Beispiel:

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

Hier ist meine einfache Lösung, um die Abfrageparameter in der URL zu aktualisieren, ohne die Seite zu aktualisieren. Stellen Sie sicher, dass es für Ihren Anwendungsfall funktioniert.

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