คุณสามารถบังคับให้ Vue.js โหลดซ้ำ / แสดงผลซ้ำได้หรือไม่


231

แค่คำถามด่วน

คุณสามารถบังคับVue.jsให้โหลดซ้ำ / คำนวณใหม่ทุกสิ่งได้หรือไม่ ถ้าเป็นเช่นนั้นได้อย่างไร


อาจได้รับการสนับสนุนที่ดีขึ้นที่นี่github.com/vuejs/Discussion/issues
Cory Danielson

เยี่ยมมากไม่รู้เกี่ยวกับที่สนทนา ฉันจะลองที่นั่น
เดฟ

คุณได้รับคำตอบหรือไม่? ฉันกระตือรือร้นที่จะรู้เช่นกัน
Oddman

จำไม่ได้ว่า แต่นี่คือปัญหาที่ฉันเปิดด้วยเบาะแสบางอย่าง: github.com/vuejs/Discussion/issues/356
เดฟ

ฉันมีคำสั่ง v-for ในมุมมองและมีกรณีการใช้งานเมื่อฉันสลับสองวัตถุในอาร์เรย์นั้นด้วยตนเอง Vue จะไม่ทำการเรนเดอร์เท็มเพลตอัตโนมัติ ฉันใช้วิธีแก้ปัญหา: เพียงดำเนินการใด ๆ กับอาเรย์นี้ (อย่าผลักวัตถุที่ว่างเปล่าแล้วประกบกัน) - นี่เป็นการทริกเกอร์การแสดงผล แต่นี่เป็นกรณีพิเศษ
ฟีโอดอร์ Khruschov

คำตอบ:


237

ลองใช้เวทย์มนตร์นี้:

vm.$forceUpdate();

ไม่จำเป็นต้องสร้าง vars ที่แขวนอยู่ :)

อัปเดต:ฉันพบโซลูชันนี้เมื่อฉันเริ่มทำงานกับ VueJS เท่านั้น อย่างไรก็ตามการสำรวจเพิ่มเติมพิสูจน์วิธีนี้เป็นไม้ยันรักแร้ เท่าที่ฉันจำได้ในขณะที่ฉันกำจัดมันเพียงแค่วางคุณสมบัติทั้งหมดที่ล้มเหลวในการรีเฟรชโดยอัตโนมัติ (ส่วนใหญ่ซ้อนกัน) ลงในคุณสมบัติที่คำนวณได้

ข้อมูลเพิ่มเติมที่นี่: https://vuejs.org/v2/guide/computed.html


4
สิ่งนี้ช่วยฉันได้จริงเมื่อฉันใช้กับคอมโพเนนต์ตัวช่วยสร้างฟอร์มใน Vue เขตข้อมูลในแบบฟอร์มของฉันสูญเสียสถานะแม้ว่าตัวแปรข้อมูลจะไม่เปลี่ยนแปลง ตอนนี้ฉันกำลังใช้สิ่งนี้เพื่อรีเฟรชมุมมองเมื่อฉันย้อนกลับไปฉันต้องวางมันในฟังก์ชั่น setTimeout
Jimmy Ilenloa

26
โปรดทราบว่าในไฟล์ vue คุณต้องการ 'this. $ forceUpdate ();'
Katinka Hesselink

1
วิธีนี้ใช้งานได้ดีในการอัปเดตการโทร axios ที่ยาว
AlfredBr

4
ในทางที่แปลกประหลาด$forceUpdate()ไม่เคยทำงานให้ฉันใน 2.5.17
Abana Clara

2
@AbanaClara $ forceUpdate () ไม่เคยเป็นวิธีสาธารณะฉันพบว่ามันขุดซอร์สโค้ดของ Vue และเนื่องจากการใช้งานไม่เคยเป็นวิธีที่ถูกต้องสำหรับ Vue'ing จึงอาจถูกถอดออกได้ ไม่สามารถพูดได้อย่างแน่นอนถ้ามันยังอยู่ที่นั่นเพราะฉันไม่ทำส่วนหน้าอีกต่อไป
Boris Mossounov

82

ดูเหมือนว่าวิธีการแก้ปัญหาที่สะอาดจากmatthiasgในประเด็นนี้ :

คุณยังสามารถใช้:key="someVariableUnderYourControl"และเปลี่ยนรหัสเมื่อคุณต้องการให้ส่วนประกอบสร้างใหม่ได้อย่างสมบูรณ์

สำหรับกรณีการใช้งานของฉันฉันได้ป้อน Vuex getter เป็นส่วนประกอบเป็นเสา ด้วยวิธีใดก็ตาม Vuex จะดึงข้อมูล แต่ปฏิกิริยาที่เกิดขึ้นไม่น่าเชื่อถือที่จะดึงองค์ประกอบออกมา ในกรณีของฉันการตั้งค่าองค์ประกอบkeyเป็นคุณลักษณะบางอย่างบนเสารับประกันการรีเฟรชเมื่อ getters (และคุณลักษณะ) ได้รับการแก้ไขในที่สุด


1
นี่คือเคล็ดลับเล็ก ๆ น้อย ๆ เรียบร้อยมันพื้นบังคับ re-instantiation ของส่วนประกอบ ( mountedจะทำงาน ฯลฯ )
BTK

1
@btk ฉันเห็นด้วยอาจไม่ใช่วิธีที่ "ถูกต้อง" ในการทำสิ่งต่าง ๆ แต่เป็นการแฮ็คที่สะอาดพอสมควรสำหรับสิ่งที่เป็นอยู่
Brian Kung

1
มีประโยชน์นี้ ฉันใช้เส้นทางแบบเต็มเส้นทางเป็นกุญแจสำคัญในการแสดงส่วนประกอบเดียวกันเมื่อเส้นทางเปลี่ยน : key = "$ route.fullPath"
Nirav Gandhi

44

ทำไม?

... คุณต้องการบังคับการอัปเดตหรือไม่

บางทีคุณอาจไม่ได้สำรวจ Vue อย่างดีที่สุด:

จะมี Vue โดยอัตโนมัติตอบสนองต่อการเปลี่ยนแปลงในมูลค่าวัตถุจะต้องมีการประกาศครั้งแรกใน dataหรือถ้าไม่ได้พวกเขาจะต้องมีการเพิ่มการใช้Vue.set()

ดูความคิดเห็นในตัวอย่างด้านล่าง หรือเปิดการสาธิตเดียวกันในJSFiddleที่นี่

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>

ที่จะโทส่วนหนึ่งของวูนี้ตรวจสอบเอกสารเป็นทางการในการเกิดปฏิกิริยา - เปลี่ยนการตรวจเตือน มันเป็นสิ่งที่ต้องอ่าน!


2
ยอมรับอย่างแน่นอนว่าคุณควรตั้งคำถามเกี่ยวกับข้อกำหนดการรีเฟรชนี้ แต่บางครั้งคุณเพียงต้องการให้ UI แสดงผลอีกครั้งเนื่องจากวิวพอร์ตมีการเปลี่ยนแปลงและคุณต้องแสดงเนื้อหาที่แตกต่างกัน (เป็นตัวอย่าง) ข้อมูลอาจไม่เปลี่ยนแปลงจริง
the_dude_abides

1
ทำไมคุณต้องโหลดซ้ำ ในบางกรณีไฟล์ทรัพยากร (stylesheets / js) แคชโดยเบราว์เซอร์จะต้องโหลดใหม่หลังจากระยะเวลาหนึ่ง ฉันมีสไตล์ชีทที่ต้องโหลดใหม่หลังจาก 7 วันและหากผู้ใช้เปิดแท็บไว้พร้อมกับการเข้าถึงหน้าเว็บและกลับมาหลังจาก 7 วันเพื่อสำรวจหน้านั้น css มีอายุมากกว่า 7 วัน
Aurovrata

@AchielVolckaert คุณอาจได้พบคำตอบแล้ว แต่ใช่Vue.set()ยังใช้งานได้ในส่วนประกอบ
acdcjunior

1
@the_dude_abides และ @ Aurovrata ฉันยอมรับการใช้งานเหล่านี้อย่างถูกกฎหมาย คำถามที่ฉันโพสต์คือคนไม่ค่อยทำสดชื่นด้วยเหตุผลที่ผิด
acdcjunior

1
บางทีคุณอาจกำลังพยายามแก้ไขบั๊กในเว็บแอพที่ออกแบบมาไม่ดีซึ่งใช้ vue หมดจดเป็นเครื่องมือเรนเดอร์และเช่นรีโหลดแอปพลิเคชั่นทั้งหมดเมื่อใดก็ตามที่ไปที่เซิร์ฟเวอร์โดยไม่สนใจความสามารถของฝั่งไคลเอ็นต์ ในโลกแห่งความเป็นจริงคุณจะไม่มีเวลาแก้ไขสิ่งที่น่ารังเกียจทุกครั้งที่คุณพบ
Warren Dew

30

โปรดอ่านhttp://michaelnthiessen.com/force-re-render/นี้

วิธีที่น่ากลัว: โหลดซ้ำทั้งหน้า
อีกวิธีที่น่ากลัว: ใช้ v-if hack
วิธีที่ดีกว่า: ใช้วิธีการ forceUpdate ในตัวของ Vue วิธี
ที่ดีที่สุด: การเปลี่ยนคีย์บนคอมโพเนนต์ของคุณ

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

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

ฉันยังใช้นาฬิกา: ในบางสถานการณ์


แน่นอนฉันเห็นด้วยกับคุณ!
เพชร

ฉันเกือบยอมแพ้กับ Vue แต่ด้วยเหตุนี้ความเชื่อมั่นใน Vue ของฉันจึงได้รับการฟื้นฟู
jokab

ลิงค์ไม่แสดงวิธีที่น่ากลัวจริง ๆ ซึ่งเป็นสิ่งที่ฉันต้องการเนื่องจากแอพของฉันออกแบบมาเพื่อนำทางไปในทางที่น่ากลัว ดูเหมือน URL ที่เรียบง่ายในหน้าปัจจุบันจะไม่ทำงานอย่างน้อยก็ไม่ได้อยู่ในแอพที่ฉันจัดการด้วยดังนั้นฉันจึงต้องการคำแนะนำเกี่ยวกับวิธีการใช้วิธีที่น่ากลัว
Warren Dew

@WarrenDew โปรดติดตาม: stackoverflow.com/questions/3715047/…
Yash

25

ลองใช้this.$router.go(0);เพื่อโหลดหน้าปัจจุบันใหม่ด้วยตนเอง


3
เรียบง่าย: นี่ $ router.go ()
Marius

ที่จริงแล้ว @MariusAndreiana - ฟังก์ชั่น. go () ต้องการพารามิเตอร์ที่ไม่จำเป็น 1 ตัว
a_lovelace


15

แน่นอนว่า.. คุณสามารถใช้แอททริบิวคีย์เพื่อบังคับให้แสดงซ้ำ (นันทนาการ) ได้ตลอดเวลา

<mycomponent :key="somevalueunderyourcontrol"></mycomponent>

ดูhttps://jsfiddle.net/mgoetzke/epqy1xgf/เพื่อเป็นตัวอย่าง

มันยังถูกกล่าวถึงที่นี่: https://github.com/vuejs/Discussion/issues/356#issuecomment-336060875


12
<my-component :key="uniqueKey" />

พร้อมกับมันใช้this.$set(obj,'obj_key',value) และอัปเดตuniqueKeyสำหรับทุกการปรับปรุงในค่า Object (obj) สำหรับทุกการปรับปรุงthis.uniqueKey++

มันทำงานให้ฉันด้วยวิธีนี้


6

มีสองวิธีที่คุณสามารถทำได้

1) คุณสามารถใช้$forceUpdate()ในตัวจัดการวิธีการของคุณเช่น

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

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

2) คุณสามารถมอบแอ:keyททริบิวต์ให้กับส่วนประกอบและส่วนเพิ่มของคุณเมื่อต้องการแสดงผลซ้ำ

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

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

5

ใช้คำสั่ง v-if

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

ดังนั้นเพียงแค่เปลี่ยนค่าของค่าที่แท้จริงจากเท็จเป็นจริงจะทำให้ส่วนประกอบระหว่าง div เปลี่ยนเป็นอีกครั้ง


1
ในความคิดของฉันนี้เป็นวิธีที่สะอาดที่สุดในการโหลดส่วนประกอบ Altough in created () method คุณสามารถเพิ่มบางอย่างของการเริ่มต้นได้
Piotr Żak

5

ในการรีโหลด / แสดงผลซ้ำ / รีเฟรชคอมโพเนนต์ให้หยุดการโค้ดแบบยาว มีวิธี Vue.JS ในการทำเช่นนั้น

เพียงใช้:keyแอตทริบิวต์

ตัวอย่างเช่น:

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

ฉันใช้อันนั้นใน BS Vue Table Slot บอกว่าฉันจะทำบางสิ่งบางอย่างสำหรับองค์ประกอบนี้เพื่อให้เป็นเอกลักษณ์


3

สิ่งนี้ได้ผลสำหรับฉัน

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

ส่วนประกอบอื่น ๆ ใช้ไฟเหตุการณ์ refresh-stores-list จะทำให้คอมโพเนนต์ปัจจุบันแสดงผลซ้ำ


2

ฉันพบวิธี มันค่อนข้างแฮ็ก แต่ใช้ได้

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

vmวัตถุโมเดลของคุณอยู่ที่ไหนและxเป็นตัวแปรที่ไม่มีอยู่จริง

Vue.js จะบ่นเกี่ยวกับเรื่องนี้ในบันทึกของคอนโซล แต่มันจะทริกเกอร์การรีเฟรชสำหรับข้อมูลทั้งหมด ทดสอบกับรุ่น 1.0.26


2

ทำงานให้ฉัน

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

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


0

: key = "$ route.params.param1" เพียงใช้รหัสกับ params ของคุณในการโหลดเด็กอัตโนมัติ ..


4
พยายามให้ข้อมูลโดยละเอียดเกี่ยวกับโซลูชันของคุณ เพิ่มรหัสของคุณเน้นคำหลัก
Agilanbu

0

ฉันมีปัญหานี้กับแกลเลอรี่รูปภาพที่ฉันต้องการแสดงซ้ำเนื่องจากมีการเปลี่ยนแปลงในแท็บอื่น ดังนั้น tab1 = imageGallery, tab2 = FavoriteImages

tab @ change = "updateGallery ()" -> สิ่งนี้บังคับให้ v-for directive ของฉันประมวลผลฟังก์ชั่น filteredImages ทุกครั้งที่ฉันสลับแท็บ

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

0

ขออภัยด้วยวิธีการโหลดหน้าซ้ำอีกครั้ง (กะพริบ) ไม่มีวิธีใดที่ใช้งานได้สำหรับฉัน (: คีย์ไม่ทำงาน)

และฉันพบวิธีนี้จากฟอรัม vue.js เก่าซึ่งใช้ได้กับฉัน:

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>
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.