Perbarui url secara diam-diam tanpa memicu rute di vue-router

Saya perlu memperbarui hash url, tanpa benar-benar memicu vue-router untuk menuju ke rute itu. Sesuatu seperti:

router.replace('my/new/path', {silent:true})

Ini akan memperbarui url menjadi .../#/my/new/path, tetapi router itu sendiri tidak akan merutekan ke jalur itu.

Apakah ada cara elegan untuk mencapai hal ini?


person Rinux    schedule 14.07.2018    source sumber
comment
apa yang terjadi jika Anda menggunakan kode ini?   -  person Niklesh Raut    schedule 14.07.2018
comment
Mungkinkah ini masalah xy..?   -  person Rainb    schedule 14.07.2018
comment
@ C2486 kode ini hanyalah contoh solusi elegan. Sayangnya argumen kedua dalam fungsi ganti seharusnya berupa panggilan balik onComplete.   -  person Rinux    schedule 14.07.2018
comment
@Rainb, mungkin saja. Saya perlu memuat halaman tertentu dari aplikasi lama kita yang dimasukkan ke dalam iframe dalam aplikasi baru kita. Saat bernavigasi dalam iframe ini, hash url di jendela atas harus diperbarui, supaya riwayatnya berfungsi dengan baik. Karena navigasi sudah dilakukan dalam iframe, rute itu sendiri tidak boleh diperbarui. Setelah pengguna benar-benar bernavigasi dengan bilah alamat atau menggunakan mundur/maju, komponen dengan iframe harus diperbarui dengan url yang benar. Saya tahu, ada beberapa tanda bahaya di sana, tetapi saya perlu menggunakan iframe agar dapat melakukan sandbox pada aplikasi lama.   -  person Rinux    schedule 14.07.2018


Jawaban (4)


Router Vue aktif atau nonaktif, jadi Anda tidak bisa "membuatnya tidak mendeteksi url tertentu". Meskipun demikian, Vue menggunakan kembali komponen jika tidak perlu menghancurkannya dan memungkinkan Anda menggunakan url alias. Hal ini memungkinkan Anda untuk memiliki url dari aplikasi iframe Anda sebagai alias di rute Anda, dan menjaga komponen yang sama tetap hidup selama waktu tersebut, mencegah iframe Anda dimuat ulang.

// router.js
import Comp1 from "./components/Comp1";
import Comp2 from "./components/Comp2";

export default [
  {
    path: "/route1",
    component: Comp1,
    alias: ["/route2", "/route3", "/route4"]
  },
  {
    path: "/otherroute",
    component: Comp2
  }
];
// main.js
import Vue from "vue";
import App from "./App";
import VueRouter from "vue-router";
import routes from "./router";

Vue.config.productionTip = false;
Vue.use(VueRouter);

const router = new VueRouter({
  routes
});

/* eslint-disable no-new */
new Vue({
  el: "#app",
  router,
  components: { App },
  template: "<App/>"
});

Dalam contoh ini, route1, route2, route3 dan route4 semuanya akan diperlakukan seolah-olah route1 harus dimuat, menyebabkan komponen Comp1 Anda tetap hidup.

Edit  Templat Vue

person Sumurai8    schedule 14.07.2018
comment
Saya tidak mengerti bagaimana ini menjawab pertanyaan itu. Tidak ada kode untuk memperbarui url jendela induk jika url di dalam iframe berubah. Tidak ada kode untuk update router iframe jika url induk windows berubah. - person jansolo; 10.12.2020
comment
@jansolo Perilaku yang diinginkan OP adalah: (1) url induk berubah, (2) router vue tidak boleh memperbarui tampilan. Solusinya di sini adalah dengan menggunakan alias sehingga router Vue memperlakukan beberapa url sebagai rute yang sama. Pertanyaan ini bukan tentang cara memperbarui iframe anak dengan informasi tersebut, melainkan bagaimana menghindari memuat ulang iframe tersebut dengan setiap perubahan rute. - person Sumurai8; 11.12.2020

Tanpa memuat ulang laman atau menyegarkan dom, history.pushState dapat melakukan tugasnya.
Tambahkan metode ini di komponen Anda atau di tempat lain untuk melakukannya:

addHashToLocation(params) {
  history.pushState(
    {},
    null,
    this.$route.path + '#' + encodeURIComponent(params)
  )
}

Jadi di mana pun di komponen Anda, panggil addHashToLocation('/my/new/path') untuk mendorong lokasi saat ini dengan parameter kueri di tumpukan window.history.

Untuk menambahkan parameter kueri ke lokasi saat ini tanpa memasukkan entri riwayat baru, gunakan history.replaceState sebagai gantinya.

Harus bekerja dengan Vue 2.6.10 dan Nuxt 2.8.1.

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

person ManUtopiK    schedule 20.06.2019
comment
Untuk menggunakan pendekatan ini dengan URL dinamis, Anda dapat menggunakan metode resolve(): const { href } = this.$router.resolve(route); window.history.pushState({}, null, href); - person Gustavo Gondim; 13.10.2020

jika yang ingin Anda lakukan adalah memperbarui url untuk menampilkan status halaman (mungkin seperti ?search=something) maka Anda dapat melakukan trik seperti ini. ide utamanya adalah menggunakan tombol this.respondToRouteChanges untuk mengabaikan perubahan saat url diperbarui oleh kode Anda.

saat memperbarui rute (mis. dalam metode vue di komponen Anda)

          this.respondToRouteChanges = false;
          this.$router.replace({query: { search: this.search })
              .finally(() => {
                this.respondToRouteChanges = true;
              });

dan dalam kode komponen yang biasanya melihat/menangani perubahan pada rute

    setSearch() {
      if (!this.respondToRouteChanges){
        // console.log('ignoring since route changes ignored')
        return;
      }
      if (this.search !== this.querySearch)
        this.search = this.querySearch;
    },

  watch: {
     // watch for changes in the url
    'querySearch': 'setSearch',

perhatikan bahwa respondToRouteChanges hanyalah boolean yang didefinisikan sebagai data() dalam komponen

  data() {
    return {
      respondToRouteChanges: true,
      ...

querySearch hanyalah nilai terhitung yang mengembalikan rute

    querySearch() {
      return this.$route.query.search || '';
    },
person Tom Carchrae    schedule 04.03.2021

Saya menemukan cara Silently update url, tetapi rute tetap terpicu (tapi ini mungkin bukan masalah - tergantung situasi).

Dalam kasus saya, pengguna dapat membuat profil, misalnya melalui URL http://localhost:8080/#/user/create/, memberikan beberapa info profil dan setelah "Simpan" diklik, pengguna diarahkan ke profil yang dibuatnya dengan URL misalnya http://localhost:8080/#/FaFYhTW9gShk/, di mana pengguna dapat terus mengedit formulir profil .

Bagaimana aku melakukan itu?

  1. Halaman user/create/ (ProfileCreate) dan halaman FaFYhTW9gShk/ (ProfileDetails) menggunakan komponen ProfileUser yang sama.
// router.js
const routes = [
    {
        path: '/user/create',
        component: Profile,
        children: [
            {
                path: '',
                name: 'ProfileCreate',
                component: ProfileUser
            }
        ]
    }
    { path: '/:profileUrl',
        component: Profile,
        children: [
            {
                path: '',
                name: 'ProfileDetails',
                component: ProfileUser
            }
        ]
    }
]

  1. Di router.beforeEach saya memeriksa apakah saya perlu memuat data dari bagian belakang, atau saya hanya perlu mengubah URL?
// router.js
router.beforeEach((to, from, next) => {
    if (!('isProfileLoaded' in to.params)) {
        // load profile from backend and update Vuex
    }

  next()
})
  1. Ketika tombol "Simpan" diklik, di action saya mengirim data ke backend + menelepon router.push
// action.js
import router from '@/router'

// Here I send data to backend
// Some code

// Update-URL-Trick
router.push({
    name: 'ProfileDetails',
    params: { profileUrl: profileUrl isProfileLoaded: true }
})

Sejauh isProfileLoaded disediakan, Vue menggunakan kembali data profil dari Vuex + router silently memperbarui URL menggunakan kembali komponen ProfileUser yang sama.

person TitanFighter    schedule 09.12.2019