Jak ustawić parametry zapytań URL w Vue z Vue-Router

114

Próbuję ustawić parametry zapytania za pomocą Vue-router podczas zmiany pól wejściowych, nie chcę przechodzić do innej strony, ale chcę tylko zmodyfikować parametry zapytania URL na tej samej stronie, robię to w ten sposób:

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

Ale to również odświeża stronę i ustawia pozycję y na 0, tj. Przewija do góry strony. Czy jest to właściwy sposób ustawiania parametrów zapytania URL, czy też istnieje lepszy sposób, aby to zrobić.


Edytowano:

Oto mój kod routera:

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
źródło

Odpowiedzi:

133

Oto przykład w dokumentach:

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

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

Jak wspomniano w tych dokumentach, router.replacedziała jakrouter.push

Wygląda więc na to, że masz to dobrze w swoim przykładowym kodzie. Myślę jednak, że może być konieczne uwzględnienie jednego z parametrów namelub path, aby router miał jakąś trasę, do której należy nawigować. Bez namelub pathnie wygląda to zbytnio.

Oto moje obecne rozumienie teraz:

  • query jest opcjonalne dla routera - dodatkowe informacje dla komponentu, aby utworzyć widok
  • namelub pathjest obowiązkowe - decyduje, który komponent ma się pojawić w Twoim <router-view>.

To może być brakująca rzecz w twoim przykładowym kodzie.

EDYCJA: Dodatkowe szczegóły po komentarzach

Czy próbowałeś używać nazwanych tras w tym przypadku? Masz trasy dynamiczne i łatwiej jest osobno podać parametry i zapytania:

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

a następnie w swoich metodach:

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

Technicznie nie ma różnicy między powyższymi a this.$router.replace({path: "/user/123", query:{q1: "q1"}}), ale łatwiej jest podać parametry dynamiczne dla nazwanych tras niż tworzenie ciągu trasy. Ale w obu przypadkach należy wziąć pod uwagę parametry zapytania. W obu przypadkach nie mogłem znaleźć nic złego w sposobie obsługi parametrów zapytania.

Po znalezieniu się w trasie możesz pobrać parametry dynamiczne jako, this.$route.params.ida parametry zapytania jako this.$route.query.q1.

Mani
źródło
Próbowałem również podać ścieżkę, ale to nie zatrzymało przewijania na górę strony, edytowałem również pytanie z opcjami routera, może tam potrzebna jest jakaś zmiana.
Saurabh
Czy parametr zapytania ma przewijać się w odpowiednie miejsce w dokumencie? Podobnie jak inne pytanie dotyczące tagów kotwicy ?
Mani
Nie, chcę tylko dodać parametr zapytania w adresie URL, nie chcę tutaj żadnego przewijania.
Saurabh
Właśnie przetestowałem opcje w mojej konfiguracji lokalnej, parametry zapytania działają normalnie. Jestem w stanie nawigować do nowej trasy i uzyskać dostęp do parametrów zapytania, jak pokazano w mojej zaktualizowanej odpowiedzi. Problem w tym, że nie chcesz, żeby się przewijał? A może problem polega na tym, że cała aplikacja ponownie się odświeża?
Mani
więc jestem na tej samej stronie, kiedy wybieram dane wejściowe, chcę je dodać w adresie URL, ale kiedy to robię, następuje przewijanie. Dla mnie problemem jest przewijanie. Nie próbuję przechodzić do innej strony, po prostu chcę być na tej samej stronie i pozornie dodawać / modyfikować parametry zapytania URL.
Saurabh
16

Bez ponownego ładowania strony lub odświeżania domeny history.pushStatemoże wykonać zadanie.
Dodaj tę metodę w swoim komponencie lub w innym miejscu, aby to zrobić:

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

Tak więc w dowolnym miejscu komponentu wywołaj, addParamsToLocation({foo: 'bar'})aby przesłać bieżącą lokalizację z parametrami zapytania ze stosu window.history.

Aby dodać parametry zapytania do bieżącej lokalizacji bez wypychania nowego wpisu historii , użyj history.replaceStatezamiast tego.

Testowane z Vue 2.6.10 i Nuxt 2.8.1.

Uważaj na tę metodę!
Vue Router nie wie, że url się zmienił, więc nie odzwierciedla adresu URL po pushState.

ManUtopiK
źródło
5
this.$router.push({ query: Object.assign(this.$route.query, { new: 'param' }) })
Boston Kenne
źródło
1
Najbardziej podobała mi się ta odpowiedź. Niestety to powodujeError: Avoided redundant navigation to current location
Max Coplan
Poprawka:this.$router.push({ query: Object.assign({...this.$route.query}, { new: 'param' }) })
Max Coplan
2
Ale teraz, kiedy o tym myślę, możesz po prostu zrobićthis.$router.push({ query: {...this.$route.query,new: 'param'},) })
Max Coplan
3

Jeśli próbujesz zachować niektóre parametry, zmieniając inne, pamiętaj, aby skopiować stan zapytania routera vue i nie używać go ponownie.

To działa, ponieważ tworzysz kopię bez odwołań:

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

podczas gdy poniżej spowoduje, że Vue Router pomyśli, że ponownie używasz tego samego zapytania, i doprowadzi do NavigationDuplicatedbłędu:

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

Oczywiście możesz zdekomponować obiekt zapytania, na przykład poniżej, ale musisz znać wszystkie parametry zapytania na swojej stronie, w przeciwnym razie ryzykujesz utratę ich w wynikowej nawigacji.

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

Uwaga, chociaż powyższy przykład dotyczy push(), to działa replace()również z .

Testowane z vue-router 3.1.6.

Andre M
źródło
3

W przypadku dodawania wielu parametrów zapytania, właśnie to zadziałało (stąd https://forum.vuejs.org/t/vue-router-programmatically-append-to-querystring/3655/5 ).

odpowiedź powyżej była bliska… chociaż z Object. assign to zmutuje to. $ route.query, co nie jest tym, co chcesz zrobić… upewnij się, że pierwszy argument to {} podczas wykonywania Object. assign

this.$router.push({ query: Object.assign({}, this.$route.query, { newKey: 'newValue' }) });
Boris
źródło
2

Aby ustawić / usunąć wiele parametrów zapytania naraz, skończyłem z poniższymi metodami jako częścią moich globalnych mixinów ( thiswskazuje na komponent 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)
    },
wirus
źródło
1

Zwykle używam do tego obiektu historii. Nie ładuje również ponownie strony.

Przykład:

history.pushState({}, '', 
                `/pagepath/path?query=${this.myQueryParam}`);
mostafa
źródło
0

Oto moje proste rozwiązanie, aby zaktualizować parametry zapytania w adresie URL bez odświeżania strony. Upewnij się, że działa w Twoim przypadku użycia.

const query = { ...this.$route.query, someParam: 'some-value' };
this.$router.replace({ query });
parker_codes
źródło