Bisakah Anda memaksa Vue.js untuk memuat ulang / membuat ulang?

231

Hanya pertanyaan singkat.

Bisakah Anda memaksa Vue.jsuntuk memuat ulang / menghitung ulang semuanya? Jika ya, bagaimana caranya?

Dave
sumber
Mungkin mendapatkan dukungan yang lebih baik di sini github.com/vuejs/Discussion/issues
Cory Danielson
Hebat, tidak tahu tentang tempat diskusi itu. Saya akan mencoba di sana.
Dave
Apakah Anda akhirnya mendapat respons? Saya juga ingin tahu.
Oddman
Tidak ingat persis. Tapi inilah masalah yang saya buka dengan beberapa petunjuk: github.com/vuejs/Discussion/issues/356
Dave
Saya memiliki direktif v-for dalam tampilan dan menggunakan case ketika saya menukar dua objek secara manual pada array itu. Vue tidak secara otomatis me-rerender template setelah ini. Saya menggunakan solusi: lakukan saja tindakan apa pun dengan array ini (lakukan push objek kosong lalu splice) - ini memicu rerender. Tetapi ini adalah kasus khusus.
Fyodor Khruschov

Jawaban:

237

Coba mantra ajaib ini:

vm.$forceUpdate();

Tidak perlu membuat vars gantung :)

Pembaruan: Saya menemukan solusi ini ketika saya baru mulai bekerja dengan VueJS. Namun eksplorasi lebih lanjut membuktikan pendekatan ini sebagai penopang. Sejauh yang saya ingat, dalam beberapa saat saya menyingkirkannya hanya menempatkan semua properti yang gagal menyegarkan secara otomatis (kebanyakan yang bersarang) ke dalam properti yang dihitung.

Info lebih lanjut di sini: https://vuejs.org/v2/guide/computed.html

Boris Mossounov
sumber
4
ini sangat membantu saya ketika saya menggunakannya dengan komponen form wizard di Vue. Bidang formulir saya kehilangan status meskipun variabel data masih utuh. Sekarang saya menggunakan ini untuk menyegarkan tampilan ketika saya kembali, saya harus meletakkannya di fungsi setTimeout.
Jimmy Ilenloa
26
Perhatikan bahwa dalam file vue Anda memerlukan 'ini. $ ForceUpdate ();'
Katinka Hesselink
1
Ini berfungsi baik untuk memperbarui setelah panggilan aksioma yang panjang.
AlfredBr
4
Dalam beberapa cara yang sangat aneh, $forceUpdate()tidak pernah bekerja untuk saya di 2.5.17.
Abana Clara
2
@AbanaClara $ forceUpdate () tidak pernah menjadi metode publik, saya menemukannya menggali kode sumber Vue. Dan karena penggunaannya tidak pernah merupakan cara yang tepat untuk Vue'ing, mungkin itu bisa dihapus. Tidak bisa mengatakan dengan pasti apakah itu masih ada, karena saya tidak melakukan front-end lagi.
Boris Mossounov
82

Ini sepertinya solusi yang cukup bersih dari matthiasg untuk masalah ini :

Anda juga dapat menggunakan :key="someVariableUnderYourControl"dan mengubah kunci ketika Anda ingin komponen dibangun kembali sepenuhnya

Untuk kasus penggunaan saya, saya memberi makan pengambil Vuex ke komponen sebagai alat peraga. Entah bagaimana Vuex akan mengambil data tetapi reaktivitas tidak andal menendang untuk merender komponen. Dalam kasus saya, mengatur komponen keyke beberapa atribut pada prop dijamin refresh ketika getter (dan atribut) akhirnya diselesaikan.

Brian Kung
sumber
1
Ini adalah trik kecil yang rapi, pada dasarnya memaksa instantiasi ulang komponen ( mountedakan dijalankan, dll)
btk
1
@ btk Saya setuju, ini mungkin bukan cara yang "benar 'untuk melakukan sesuatu, tetapi ini adalah peretasan yang cukup bersih, untuk apa itu
Brian Kung
1
ini bermanfaat. Saya menggunakan path lengkap rute sebagai kunci untuk merender komponen yang sama ketika rute berubah. : key = "$ route.fullPath"
Nirav Gandhi
44

Mengapa?

... apakah Anda perlu memaksakan pembaruan?

Mungkin Anda tidak menjelajahi Vue yang terbaik:

Agar Vue bereaksi secara otomatis terhadap perubahan nilai, objek pada awalnyadata harus dinyatakan dalam . Atau, jika tidak, mereka harus ditambahkan menggunakanVue.set() .

Lihat komentar di demo di bawah ini. Atau buka demo yang sama di JSFiddle di sini .

new Vue({
  el: '#app',
  data: {
    person: {
      name: 'Edson'
    }
  },
  methods: {
    changeName() {
      // because name is declared in data, whenever it
      // changes, Vue automatically updates
      this.person.name = 'Arantes';
    },
    changeNickname() {
      // because nickname is NOT declared in data, when it
      // changes, Vue will NOT automatically update
      this.person.nickname = 'Pele';
      // although if anything else updates, this change will be seen
    },
    changeNicknameProperly() {
      // when some property is NOT INITIALLY declared in data, the correct way
      // to add it is using Vue.set or this.$set
      Vue.set(this.person, 'address', '123th avenue.');
      
      // subsequent changes can be done directly now and it will auto update
      this.person.address = '345th avenue.';
    }
  }
})
/* CSS just for the demo, it is not necessary at all! */
span:nth-of-type(1),button:nth-of-type(1) { color: blue; }
span:nth-of-type(2),button:nth-of-type(2) { color: red; }
span:nth-of-type(3),button:nth-of-type(3) { color: green; }
span { font-family: monospace }
<script src="https://unpkg.com/vue"></script>

<div id="app">
  <span>person.name: {{ person.name }}</span><br>
  <span>person.nickname: {{ person.nickname }}</span><br>
  <span>person.address: {{ person.address }}</span><br>
  <br>
  <button @click="changeName">this.person.name = 'Arantes'; (will auto update because `name` was in `data`)</button><br>
  <button @click="changeNickname">this.person.nickname = 'Pele'; (will NOT auto update because `nickname` was not in `data`)</button><br>
  <button @click="changeNicknameProperly">Vue.set(this.person, 'address', '99th st.'); (WILL auto update even though `address` was not in `data`)</button>
  <br>
  <br>
  For more info, read the comments in the code. Or check the docs on <b>Reactivity</b> (link below).
</div>

Untuk menguasai bagian Vue ini, periksa Dokumen Resmi tentang Reaktivitas - Ubah Peringatan Deteksi . Ini harus dibaca!

acdcjunior
sumber
2
Sangat setuju bahwa Anda harus mempertanyakan persyaratan penyegaran ini, tetapi kadang-kadang Anda hanya perlu UI untuk merender ulang karena viewport telah berubah dan Anda perlu menampilkan aset yang berbeda (sebagai satu contoh). Data mungkin tidak benar-benar berubah.
the_dude_abides
1
Mengapa Anda perlu memuat ulang? Dalam beberapa kasus, file sumber daya (stylesheet / js) yang di-cache oleh browser perlu dimuat ulang setelah periode waktu tertentu. Saya memiliki stylesheet yang perlu dimuat ulang setelah 7 hari dan jika pengguna tetap membuka tab dengan akses halaman dan kembali setelah 7 hari untuk menavigasi halaman itu, css lebih dari 7 hari.
Aurovrata
@AchielVolckaert Anda mungkin sudah menemukan jawabannya, tapi ya, Vue.set()juga berfungsi di dalam komponen.
acdcjunior
1
@the_dude_abides dan @ Aurovrata, itu adalah penggunaan yang sah untuk menyegarkan, saya setuju. Pertanyaan yang saya ajukan adalah bahwa orang jarang melakukan penyegaran dengan alasan yang salah.
acdcjunior
1
Mungkin Anda hanya mencoba untuk memperbaiki bug di aplikasi web yang dirancang dengan buruk yang menggunakan vue murni sebagai alat rendering, dan misalnya memuat ulang seluruh aplikasi setiap kali ia pergi ke server, mengabaikan kemampuan aplikasi sisi klien dari vue. Di dunia nyata, Anda tidak selalu punya waktu untuk memperbaiki setiap kekejian yang Anda temukan.
Warren Dew
30

Silakan baca ini http://michaelnthiessen.com/force-re-render/

Cara mengerikan: memuat ulang seluruh halaman
Cara mengerikan: menggunakan peretasan v-if
Cara yang lebih baik: menggunakan metode forceUpdate yang terintegrasi dengan Vue Cara
terbaik: mengubah kunci pada komponen Anda

<template>
   <component-to-re-render :key="componentKey" />
</template>

<script>
 export default {
  data() {
    return {
      componentKey: 0,
    };
  },
  methods: {
    forceRerender() {
      this.componentKey += 1;  
    }
  }
 }
</script>

Saya juga menggunakan arloji: dalam beberapa situasi.

Yash
sumber
Tentu, saya setuju dengan Anda!
Berlian
Aku hampir menyerah pada Vue. Namun berkat ini, keyakinan saya pada Vue telah dipulihkan.
jokab
Tautan itu sebenarnya tidak menunjukkan cara melakukannya dengan cara yang mengerikan, yang sayangnya saya butuhkan karena aplikasi saya dirancang untuk menavigasi dengan cara yang mengerikan. URL sederhana ke halaman saat ini tampaknya tidak berfungsi, setidaknya tidak di aplikasi yang saya tangani, jadi saya benar-benar memerlukan instruksi tentang cara melakukannya dengan cara yang mengerikan.
Warren Dew
@ WarrenDew Harap ikuti: stackoverflow.com/questions/3715047/…
Yash
25

Coba gunakan this.$router.go(0);untuk memuat ulang secara manual halaman saat ini.

Poy Chang
sumber
3
Simpler: this. $ Router.go ()
Marius
Sebenarnya @MariusAndreiana - fungsi .go () membutuhkan 1 parameter non-opsional
a_lovelace
23

Gunakan vm.$set('varName', value). Cari detail di Change_Detection_Caveats .

denis.peplin
sumber
12
<my-component :key="uniqueKey" />

bersamaan dengan itu gunakan this.$set(obj,'obj_key',value) dan perbarui uniqueKeyuntuk setiap pembaruan dalam objek (obj) nilai untuk setiap pembaruanthis.uniqueKey++

ini bekerja untuk saya dengan cara ini

Pushkar Shirodkar
sumber
6

Jadi ada dua cara Anda bisa melakukan ini,

1). Anda dapat menggunakan $forceUpdate()di dalam handler metode Anda yaitu

<your-component @click="reRender()"></your-component>

<script>
export default {
   methods: {
     reRender(){
        this.$forceUpdate()
     }
   }
}
</script>

2). Anda dapat memberikan :keyatribut ke komponen Anda dan meningkatkan ketika ingin rerender

<your-component :key="index" @click="reRender()"></your-component>

<script>
export default {
   data() {
     return {
        index: 1
     }
   },
   methods: {
     reRender(){
        this.index++
     }
   }
}
</script>
Shahrukh Anwar
sumber
5

menggunakan v-if direktif

<div v-if="trulyvalue">
    <component-here />
 </div>

Jadi hanya dengan mengubah nilai truevalue dari false ke true akan menyebabkan komponen antara div kembali rerender

Geoff
sumber
1
Menurut pendapat saya ini adalah cara terbersih untuk memuat ulang komponen. Meskipun dalam metode create () Anda dapat menambahkan beberapa hal inisialisasi.
Piotr Żak
5

Untuk memuat ulang / merender ulang / menyegarkan komponen, hentikan pengkodean yang panjang. Ada cara Vue.JS untuk melakukan itu.

Cukup gunakan :keyatribut.

Sebagai contoh:

<my-component :key="unique" />

Saya menggunakan yang di BS Vue Table Slot. Memberitahu bahwa saya akan melakukan sesuatu untuk komponen ini jadi buatlah menjadi unik.

Felix Labayen
sumber
3

Ini berhasil bagi saya.

created() {
            EventBus.$on('refresh-stores-list', () => {
                this.$forceUpdate();
            });
        },

Komponen lain yang mengaktifkan event refresh-store-list akan menyebabkan komponen saat ini rerender

sean717
sumber
2

Saya menemukan jalan. Agak berantakan tapi berhasil.

vm.$set("x",0);
vm.$delete("x");

Di mana objek vmview-model Anda, dan xmerupakan variabel yang tidak ada.

Vue.js akan mengeluh tentang hal ini di log konsol tetapi memicu pembaruan untuk semua data. Diuji dengan versi 1.0.26.

Laszlo sang Wiz
sumber
2

Bekerja untukku

    data () {
        return {
            userInfo: null,
            offers: null
        }
    },

    watch: {
        '$route'() {
            this.userInfo = null
            this.offers = null
            this.loadUserInfo()
            this.getUserOffers()
        }
    }
tuwilof
sumber
2

tambahkan saja kode ini:

this.$forceUpdate()

Semoga berhasil

RahmanRezaee
sumber
0

: key = "$ route.params.param1" cukup gunakan kunci dengan params Anda yang mana pun anak-anak memuat ulang secara otomatis ..

Rai Ahmad Fraz
sumber
4
cobalah untuk memberikan informasi terperinci tentang solusi Anda. tambahkan kode Anda, sorot kata kunci
Agilanbu
0

Saya punya masalah dengan galeri gambar yang ingin saya rerender karena perubahan yang dilakukan pada tab yang berbeda. Jadi tab1 = imageGallery, tab2 = favoriteImages

tab @ change = "updateGallery ()" -> ini memaksa direktif v-for saya untuk memproses fungsi filteredImages setiap kali saya mengganti tab.

<script>
export default {
  data() {
    return {
      currentTab: 0,
      tab: null,
      colorFilter: "",
      colors: ["None", "Beige", "Black"], 
      items: ["Image Gallery", "Favorite Images"]
    };
  },
  methods: {
    filteredImages: function() {
      return this.$store.getters.getImageDatabase.filter(img => {
        if (img.color.match(this.colorFilter)) return true;
      });
    },
    updateGallery: async function() {
      // instance is responsive to changes
      // change is made and forces filteredImages to do its thing
      // async await forces the browser to slow down and allows changes to take effect
      await this.$nextTick(function() {
        this.colorFilter = "Black";
      });

      await this.$nextTick(function() {
        // Doesnt hurt to zero out filters on change
        this.colorFilter = "";
      });
    }
  }
};
</script>
Jason
sumber
0

maaf kawan, kecuali metode pemuatan ulang halaman (berkedip), tidak ada yang berfungsi untuk saya (: kunci tidak berfungsi).

dan saya menemukan metode ini dari forum vue.js lama yang berfungsi untuk saya:

https://github.com/vuejs/Discussion/issues/356

<template>
    <div v-if="show">
       <button @click="rerender">re-render</button>
    </div>
</template>
<script>
    export default {
        data(){
            return {show:true}
        },
        methods:{
            rerender(){
                this.show = false
                this.$nextTick(() => {
                    this.show = true
                    console.log('re-render start')
                    this.$nextTick(() => {
                        console.log('re-render end')
                    })
                })
            }
        }
    }
</script>
sailfish009
sumber