web-dev-qa-db-ja.com

Vue.jsにロード/再レンダリングを強制することはできますか

ちょっとした質問です。

あなたはVue.jsに全てをリロード/再計算させることができますか?もしそうなら、どうですか?

134
Dave

この魔法の呪文を試してください。

vm.$forceUpdate();

ぶら下がっているvarsを作成する必要はありません:)

更新: 私はVueJSを使い始めたときにこの解決策を見つけました。しかしさらなる探査は松葉杖としてのこのアプローチを証明した。私が思い出す限りでは、しばらくすると私は自動的に更新されなかったすべてのプロパティ(ほとんどネストされたもの)を計算プロパティに入れることをやめました。

ここでより多くの情報: https://vuejs.org/v2/guide/computed.html

156
Boris Mossounov

これは matthiasg on からの非常にきれいな解決策のようです - この問題

コンポーネントを完全に再構築する場合は、:key="someVariableUnderYourControl"を使用してキーを変更することもできます。

私のユースケースでは、私はVuexゲッターをプロップとしてコンポーネントに供給していました。どういうわけかVuexはデータを取得しますが、反応性がコンポーネントを再表示するために確実に起動することはありません。私の場合は、プロペラのコンポーネントkeyを何らかの属性に設定することで、ゲッター(およびその属性)が最終的に解決されたときのリフレッシュが保証されます。

46
Brian Kung

どうして?

... need強制的に更新しますか?

おそらくあなたはVueを最大限に探索し​​ていないでしょう:

Vue automatically値の変更に反応するには、オブジェクトは最初にdataで宣言されている必要があります。 Vue.set()を使用して追加する必要があります。

以下のデモのコメントをご覧ください。または JSFiddlehere の同じデモを開きます。

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>

Vueのこの部分をマスターするには、 Of Docs on Reactivity-Change Detection Caveats を確認してください。必読です!

26
acdcjunior

vm.$set('varName', value)を使用してください。 Change_Detection_Caveats に詳細を探します。

21
denis.peplin

もちろん、key属性を使用すればいつでも再レンダリング(再作成)を強制できます。

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

例については https://jsfiddle.net/mgoetzke/epqy1xgf/ を参照してください。

それはまたここで議論されました: https://github.com/vuejs/Discussion/issues/356#issuecomment-336060875

12
mgoetzke

現在のページを手動でリロードするためにthis.$router.go(0);を使用してみてください。

11
Poy Chang

これをお読みください http://michaelnthiessen.com/force-re-render/ /

恐ろしい方法:ページ全体をリロードする
すごい方法:v-ifハックを使う
より良い方法: Vueの組み込みのforceUpdateメソッドを使用する
最善の方法: コンポーネントのキーを変更する

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

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

場合によっては、watch:も使用します。

7
Yash

v-ifディレクティブを使う

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

そのため、trulyvalueの値をfalseからtrueに変更するだけで、div間のコンポーネントが再び表示されます。

4
GEOFFREY MWANGI

私は方法を発見しました。ちょっとハッキーだけどうまくいく。

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

vmはビューモデルオブジェクト、xは存在しない変数です。

Vue.jsはコンソールログでこれについて文句を言いますが、それはすべてのデータのためのリフレッシュを引き起こします。バージョン1.0.26でテスト済み。

2
Laszlo the Wiz

これは私のために働きました。

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

もう一方のコンポーネントがrefresh-stores-listイベントを発生させると、現在のコンポーネントがレンダリングされます。

2
sean717

別のタブで行われた変更のために再レンダリングしたい画像ギャラリーでこの問題が発生しました。したがって、tab1 = imageGallery、tab2 = favoriteImages

tab @ change = "updateGallery()"->これにより、v-forディレクティブは、タブを切り替えるたびに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
Jason

:key = "$ route.params.param1"はあなたの任意のパラメータと一緒にkeyを使うだけです。

0
Rai Ahmad Fraz

私のために働いた

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

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