Bạn có thể buộc Vue.js tải lại / kết xuất lại không?


231

Chỉ là một câu hỏi nhanh.

Bạn có thể buộc Vue.jsphải tải lại / tính toán lại tất cả mọi thứ? Nếu vậy thì thế nào?


Có thể nhận được hỗ trợ tốt hơn tại đây github.com/vuejs/Discussion/issues
Cory Danielson

Tuyệt, không biết về nơi thảo luận đó. Tôi sẽ thử ở đó.
Dave

Bạn đã kết thúc nhận được một phản ứng? Tôi cũng muốn biết là tốt.
Oddman

Đừng nhớ chính xác. Nhưng đây là vấn đề tôi đã mở ra với một số manh mối: github.com/vuejs/Discussion/issues/356
Dave

Tôi có lệnh v-for trong khung nhìn và có trường hợp sử dụng khi tôi tự trao đổi hai đối tượng trên mảng đó. Vue không tự động đăng ký lại mẫu sau này. Tôi đã sử dụng cách giải quyết: chỉ cần thực hiện bất kỳ hành động nào với mảng này (thực hiện đẩy đối tượng trống và sau đó ghép nối) - điều này kích hoạt sự đăng ký lại. Nhưng đây là trường hợp đặc biệt.
Fyodor Khruschov

Câu trả lời:


237

Hãy thử phép thuật này:

vm.$forceUpdate();

Không cần tạo bất kỳ bình treo nào :)

Cập nhật: Tôi tìm thấy giải pháp này khi tôi chỉ bắt đầu làm việc với VueJS. Tuy nhiên thăm dò thêm đã chứng minh cách tiếp cận này như một cái nạng. Theo như tôi nhớ, trong một thời gian, tôi đã loại bỏ nó chỉ đơn giản là đặt tất cả các thuộc tính không tự động làm mới (chủ yếu là các thuộc tính lồng nhau) vào các thuộc tính được tính toán.

Thêm thông tin tại đây: https://vuejs.org/v2/guide/computing.html


4
điều này thực sự giúp tôi khi tôi đang sử dụng nó với một thành phần thuật sĩ biểu mẫu trong Vue. Các trường biểu mẫu của tôi bị mất trạng thái mặc dù các biến dữ liệu vẫn còn nguyên vẹn. Bây giờ tôi đang sử dụng điều này để làm mới các khung nhìn khi tôi quay trở lại, tôi phải đặt nó trong chức năng setTimeout.
Jimmy Ilenloa

26
Lưu ý rằng trong các tệp vue bạn cần 'this. $ ForceUpdate ();'
Katinka Hesselink

1
Điều này hoạt động tuyệt vời để cập nhật sau một cuộc gọi axios dài.
AlfredBr

4
Theo một cách hoàn toàn kỳ lạ, $forceUpdate()không bao giờ EVER làm việc cho tôi vào ngày 2.5.17.
Abana Clara

2
@AbanaClara $ forceUpdate () không bao giờ là phương thức công khai, tôi thấy nó đào mã nguồn của Vue. Và vì việc sử dụng nó không bao giờ là cách đúng đắn của Vue'ing, có lẽ nó có thể bị loại bỏ. Không thể nói chắc chắn nếu nó vẫn còn ở đó, vì tôi không làm front-end nữa.
Boris Mossounov

82

Đây có vẻ là một giải pháp khá sạch từ matthiasg về vấn đề này :

bạn cũng có thể sử dụng :key="someVariableUnderYourControl"và thay đổi khóa khi bạn muốn xây dựng lại thành phần

Đối với trường hợp sử dụng của tôi, tôi đã cho Vuex getter vào một thành phần như một chỗ dựa. Bằng cách nào đó Vuex sẽ lấy dữ liệu nhưng độ phản ứng sẽ không đáng tin cậy để khởi động lại thành phần. Trong trường hợp của tôi, việc đặt thành phần thành keymột số thuộc tính trên prop đảm bảo làm mới khi cuối cùng các getters (và thuộc tính) được giải quyết.


1
Đây là một mẹo nhỏ gọn gàng, về cơ bản, nó buộc phải khởi tạo lại thành phần ( mountedsẽ được chạy, v.v.)
btk

1
@btk Tôi đồng ý, có lẽ đó không phải là cách "đúng" để làm mọi thứ, nhưng nó là một bản hack khá sạch sẽ, vì nó là như vậy.
Brian Kung

1
Điều này hữu ích. Tôi sử dụng đường dẫn đầy đủ tuyến đường làm chìa khóa để đăng ký lại thành phần tương tự khi tuyến đường thay đổi. : key = "$ route.fullPath"
Nirav Gandhi

44

Tại sao?

... bạn có cần cập nhật không?

Có lẽ bạn không khám phá Vue một cách tốt nhất:

Để Vue tự động phản ứng với các thay đổi giá trị, các đối tượng phải được khai báo ban đầudata . Hoặc, nếu không, chúng phải được thêm bằng cách sử dụngVue.set() .

Xem bình luận trong bản demo dưới đây. Hoặc mở bản demo tương tự trong một JSFiddle tại đây .

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>

Để thành thạo phần này của Vue, hãy kiểm tra Tài liệu chính thức về Khả năng phản ứng - Thay đổi phát hiện . Cái này là phải đọc!


2
Chắc chắn đồng ý rằng bạn nên đặt câu hỏi về yêu cầu làm mới này, nhưng đôi khi bạn chỉ cần giao diện người dùng để kết xuất lại vì chế độ xem đã thay đổi và bạn cần hiển thị các tài sản khác nhau (như một ví dụ). Dữ liệu có thể không thực sự thay đổi.
the_dude_abides

1
Tại sao bạn cần tải lại? Trong một số trường hợp, các tệp tài nguyên (bảng định kiểu / js) được trình duyệt lưu vào bộ đệm cần phải được tải lại sau một khoảng thời gian nhất định. Tôi đã có một bản định kiểu cần được tải lại sau 7 ngày và nếu người dùng giữ một tab mở với quyền truy cập trang và quay lại sau 7 ngày để điều hướng trang đó, css đã hơn 7 ngày.
Aurovrata

@AchielVolckaert có lẽ bạn đã tìm thấy câu trả lời, nhưng vâng, Vue.set()cũng hoạt động bên trong các thành phần.
acdcjunior

1
@the_dude_abides và @ Aurovrata, đó là những cách sử dụng hợp pháp để làm mới, tôi đồng ý. Câu hỏi tôi đặt ra là mọi người không hiếm khi làm mới vì những lý do sai.
acdcjunior

1
Có lẽ bạn chỉ đang cố gắng sửa một lỗi trong ứng dụng web được thiết kế kém, sử dụng vue hoàn toàn như một công cụ kết xuất và ví dụ tải lại toàn bộ ứng dụng bất cứ khi nào nó đến máy chủ, bỏ qua khả năng ứng dụng phía máy khách của vue. Trong thế giới thực, bạn không phải lúc nào cũng có thời gian để sửa mọi thứ gớm ghiếc bạn tìm thấy.
Warren Dew

30

Vui lòng đọc http://michaelnthiessen.com/force-re-render/

Cách khủng khiếp: tải lại toàn bộ trang
Cách khủng khiếp: sử dụng hack v-if
Cách tốt hơn: sử dụng phương thức ForceUpdate tích hợp của Vue
Cách tốt nhất: thay đổi khóa trên thành phần của bạn

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

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

Tôi cũng sử dụng đồng hồ: trong một số tình huống.


Hoàn toàn, tôi đồng ý với bạn!
Kim cương

Tôi gần như đã từ bỏ Vue. Nhưng nhờ điều này, niềm tin của tôi vào Vue đã được khôi phục.
jokab

Liên kết không thực sự chỉ ra cách thực hiện theo cách khủng khiếp, đó là điều không may tôi cần vì ứng dụng của tôi được thiết kế xoay quanh việc điều hướng theo cách khủng khiếp. Một URL đơn giản đến trang hiện tại dường như không hoạt động, ít nhất là không có trong ứng dụng tôi đang xử lý, vì vậy tôi thực sự cần hướng dẫn về cách thực hiện theo cách khủng khiếp.
Warren Dew

@WarrenDew Vui lòng theo dõi: stackoverflow.com/questions/3715047/ trên
Yash

25

Cố gắng sử dụng this.$router.go(0);để tải lại thủ công trang hiện tại.


3
Đơn giản hơn: cái này. $ Router.go ()
Marius

Trên thực tế @MariusAndreiana - hàm .go () yêu cầu 1 tham số không tùy chọn
a_lovelace



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

cùng với nó sử dụng this.$set(obj,'obj_key',value) và cập nhật uniqueKeycho mọi cập nhật trong giá trị đối tượng (obj) cho mỗi cập nhậtthis.uniqueKey++

nó làm việc cho tôi theo cách này


6

Vì vậy, có hai cách bạn có thể làm điều này,

1). Bạn có thể sử dụng $forceUpdate()bên trong phương thức xử lý của bạn tức là

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

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

2). Bạn có thể cung cấp một :keythuộc tính cho thành phần của bạn và tăng khi muốn đăng ký lại

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

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

5

sử dụng chỉ thị v-if

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

Vì vậy, chỉ cần thay đổi giá trị của truevalue từ false thành true sẽ khiến thành phần giữa div được đăng ký lại


1
Theo tôi đây là cách sạch nhất để tải lại thành phần. Rõ ràng trong phương thức created () Bạn có thể thêm một số công cụ khởi tạo.
Piotr Żak

5

Để tải lại / kết xuất lại / làm mới thành phần, hãy dừng mã hóa dài. Có một cách Vue.JS làm điều đó.

Chỉ dùng :key thuộc tính.

Ví dụ:

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

Tôi đang sử dụng cái đó trong BS Vue Table Slot. Nói rằng tôi sẽ làm một cái gì đó cho thành phần này để làm cho nó độc đáo.


3

Điều này đã làm việc cho tôi.

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

Thành phần khác kích hoạt sự kiện danh sách cửa hàng làm mới sẽ khiến thành phần hiện tại quay trở lại


2

Tôi tìm thấy một cách. Đó là một chút hack nhưng hoạt động.

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

Đâu vmlà đối tượng mô hình xem của bạn vàx là một biến không tồn tại.

Vue.js sẽ phàn nàn về điều này trong nhật ký giao diện điều khiển nhưng nó kích hoạt làm mới cho tất cả dữ liệu. Đã thử nghiệm với phiên bản 1.0.26.


2

Đã làm cho tôi

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

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

2

chỉ cần thêm mã này:

this.$forceUpdate()

Chúc may mắn


0

: key = "$ route.params.param1" chỉ cần sử dụng khóa với bất kỳ thông số nào của bạn, nó tự động tải lại cho trẻ em ..


4
cố gắng cung cấp một thông tin chi tiết về giải pháp của bạn. thêm mã của bạn, đánh dấu các từ khóa
Agilanbu

0

Tôi gặp vấn đề này với một bộ sưu tập hình ảnh mà tôi muốn đăng ký lại do những thay đổi được thực hiện trên một tab khác. Vì vậy, tab1 = imageGallery, tab2 = FavoritesImages

tab @ change = "updateGallery ()" -> điều này buộc chỉ thị v-for của tôi xử lý chức năng FilteredImages mỗi khi tôi chuyển 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>

0

Xin lỗi các bạn, ngoại trừ phương pháp tải lại trang (nhấp nháy), không ai trong số họ làm việc cho tôi (: key không hoạt động).

và tôi đã tìm thấy phương pháp này từ diễn đàn vue.js cũ hoạt động với tôi:

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>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.