Cara mengatur parameter kueri URL di Vue dengan Vue-Router


114

Saya mencoba mengatur parameter kueri dengan Vue-router saat mengubah bidang input, saya tidak ingin menavigasi ke beberapa halaman lain tetapi hanya ingin mengubah parameter kueri url di halaman yang sama, saya melakukan seperti ini:

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

Tetapi ini juga menyegarkan halaman dan menyetel posisi y ke 0, yaitu menggulir ke atas halaman. Apakah ini cara yang benar untuk menyetel parameter kueri URL atau adakah cara yang lebih baik untuk melakukannya.


Diedit:

Ini kode router saya:

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

Jawaban:


132

Berikut contohnya di dokumen:

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

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

Seperti yang disebutkan dalam dokumen tersebut, router.replaceberfungsi sepertirouter.push

Jadi, Anda tampaknya sudah benar di kode sampel yang dipermasalahkan. Tapi saya pikir Anda mungkin perlu memasukkan parameter nameatau pathjuga, sehingga router memiliki beberapa rute untuk dinavigasi. Tanpa nameatau path, itu tidak terlihat sangat berarti.

Inilah pemahaman saya saat ini:

  • query bersifat opsional untuk router - beberapa info tambahan bagi komponen untuk membuat tampilan
  • nameatau pathwajib - ini memutuskan komponen apa yang akan ditampilkan di <router-view>.

Itu mungkin hal yang hilang dalam kode sampel Anda.

EDIT: Detail tambahan setelah komentar

Sudahkah Anda mencoba menggunakan rute bernama dalam kasus ini? Anda memiliki rute dinamis, dan lebih mudah untuk menyediakan parameter dan kueri secara terpisah:

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

dan kemudian dalam metode Anda:

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

Secara teknis tidak ada perbedaan antara di atas dan this.$router.replace({path: "/user/123", query:{q1: "q1"}}), tetapi lebih mudah untuk menyediakan parameter dinamis pada rute bernama daripada membuat string rute. Tetapi dalam kedua kasus, parameter kueri harus diperhitungkan. Dalam kedua kasus tersebut, saya tidak dapat menemukan sesuatu yang salah dengan cara penanganan parameter kueri.

Setelah Anda berada di dalam rute, Anda dapat mengambil parameter dinamis sebagai this.$route.params.iddan parameter kueri Anda sebagai this.$route.query.q1.


Saya mencoba memberikan jalur juga, tetapi ini tidak berhenti bergulir ke bagian atas halaman, saya telah mengedit pertanyaan dengan opsi router juga, mungkin ada beberapa perubahan yang diperlukan di sana.
Saurabh

Apakah parameter kueri Anda dimaksudkan untuk menggulir ke tempat yang tepat di dokumen? Suka pertanyaan Anda yang lain tentang tag jangkar ?
Mani

Tidak, saya hanya ingin menambahkan parameter kueri di URL, saya tidak ingin menggulir apa pun di sini.
Saurabh

Saya baru saja menguji opsi di pengaturan lokal saya, parameter kueri berfungsi normal. Saya dapat menavigasi ke rute baru dan mengakses parameter kueri seperti yang ditunjukkan dalam jawaban saya yang diperbarui. Jadi, masalahnya - Anda tidak ingin menggulir? Atau masalahnya apakah seluruh aplikasi menyegarkan lagi?
Mani

jadi saya berada di halaman yang sama, ketika saya memilih beberapa input, saya ingin menambahkannya di URL, tetapi ketika saya melakukannya, scroll terjadi. Gulir adalah masalah bagi saya. Saya tidak mencoba untuk menavigasi ke halaman lain, saya hanya ingin berada di halaman yang sama dan menambahkan / memodifikasi parameter kueri url tanpa alasan.
Saurabh

15

Tanpa memuat ulang halaman atau menyegarkan dom, history.pushStatedapat melakukan pekerjaan itu.
Tambahkan metode ini di komponen Anda atau di tempat lain untuk melakukannya:

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

Jadi di mana pun di komponen Anda, panggil addParamsToLocation({foo: 'bar'})untuk mendorong lokasi saat ini dengan parameter kueri di tumpukan window.history.

Untuk menambahkan parameter kueri ke lokasi saat ini tanpa mendorong entri riwayat baru , gunakan history.replaceStatesebagai gantinya.

Diuji dengan Vue 2.6.10 dan Nuxt 2.8.1.

Hati-hati dengan metode ini!
Vue Router tidak tahu bahwa url telah berubah, jadi tidak mencerminkan url setelah pushState.



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

1
Saya paling menyukai jawaban ini. Sayangnya ini menyebabkanError: Avoided redundant navigation to current location
Max Coplan

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

2
Tapi sekarang setelah saya memikirkannya, Anda bisa melakukannyathis.$router.push({ query: {...this.$route.query,new: 'param'},) })
Max Coplan

3

Jika Anda mencoba menyimpan beberapa parameter, saat mengubah yang lain, pastikan untuk menyalin status kueri vue router dan tidak menggunakannya kembali.

Ini berfungsi, karena Anda membuat salinan yang tidak direferensikan:

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

sementara di bawah ini akan menyebabkan Vue Router mengira Anda menggunakan kembali kueri yang sama dan menyebabkan NavigationDuplicatedkesalahan:

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

Tentu saja, Anda dapat menguraikan objek kueri, seperti berikut, tetapi Anda harus mengetahui semua parameter kueri ke halaman Anda, jika tidak, Anda berisiko kehilangannya di navigasi yang dihasilkan.

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

Perhatikan, meskipun contoh di atas adalah untuk push(), ini juga berfungsi replace().

Diuji dengan vue-router 3.1.6.


3

Untuk menambahkan beberapa parameter kueri, inilah yang berhasil untuk saya (dari sini https://forum.vuejs.org/t/vue-router-programmatically-append-to-querystring/3655/5 ).

jawaban di atas sudah dekat ... meskipun dengan Object.assign itu akan mengubah ini. $ route.query yang bukan itu ingin Anda lakukan ... pastikan argumen pertama adalah {} saat melakukan Object.assign

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

2

Untuk mengatur / menghapus beberapa parameter kueri sekaligus, saya telah berakhir dengan metode di bawah ini sebagai bagian dari mixin global saya ( thismenunjuk ke komponen 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

Saya biasanya menggunakan objek sejarah untuk ini. Itu juga tidak memuat ulang halaman.

Contoh:

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

0

Inilah solusi sederhana saya untuk memperbarui parameter kueri di URL tanpa menyegarkan halaman. Pastikan itu berfungsi untuk kasus penggunaan Anda.

const query = { ...this.$route.query, someParam: 'some-value' };
this.$router.replace({ query });
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.