Vue.jsを強制的にリロード/再レンダリングできますか?


231

簡単な質問です。

すべてを強制的Vue.jsリロード / 再計算できますか?もしそうなら、どうですか?


ここでは、より良いサポートを得る可能性がありますgithub.com/vuejs/Discussion/issues
コーリー・ダニエルソン

すばらしい、その討論の場所について知りませんでした。あちらで試してみます。
Dave、

返事がもらえましたか?私も知りたいと思っています。
Oddman、2015

正確には覚えていません。しかし、ここに私がいくつかの手掛かりで開いた問題があります:github.com/vuejs/Discussion/issues/356
Dave

ビューにv-forディレクティブがあり、その配列で2つのオブジェクトを手動でスワップする場合の使用例があります。この後、Vueはテンプレートを自動的に再レン​​ダリングしません。私は回避策を使用しました:この配列を使用してアクションを実行するだけです(空のオブジェクトをプッシュしてからスプライスを実行します)-これにより再レンダリングがトリガーされます。しかし、これは特別なケースです。
Fyodor Khruschov

回答:


237

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

vm.$forceUpdate();

ぶら下がり変数を作成する必要はありません:)

更新:私がVueJSでの作業を始めたとき、私はこの解決策を見つけました。しかし、さらなる調査により、このアプローチは松葉杖として証明されました。私が覚えている限りでは、しばらくすると、自動更新に失敗したすべてのプロパティ(ほとんどはネストされたプロパティ)を計算されたプロパティに単純に入れてしまいました。

詳細はこちら:https : //vuejs.org/v2/guide/computed.html


4
これは、Vueのフォームウィザードコンポーネントで使用するときに非常に役立ちました。データ変数はそのままだったのに、フォームフィールドfieldsが失われた状態でした。これで、戻るときにビューを更新するためにこれを使用しています。これをsetTimeout関数に配置する必要がありました。
ジミーイレンロア2017

26
Vueファイルでは 'this。$ forceUpdate();'が必要です。
Katinka Hesselink

1
これは、長いaxios呼び出しの後の更新に最適です。
-AlfredBr

4
まったく奇妙な方法で$forceUpdate()、2.5.17でこれまでまったく機能しませんでした。
アバナクララ

2
@AbanaClara $ forceUpdate()は決してパブリックメソッドではなかったので、Vueのソースコードを掘っていたことがわかりました。そして、その使用法はVueの正しい方法ではなかったので、おそらく取り除かれる可能性があります。フロントエンドはもうやらないので、まだそこにあるかどうかははっきりとは言えません。
Boris Mossounov

82

これは、この問題に関するmatthiasgのかなりクリーンなソリューションのようです。

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

私のユースケースでは、Vuexゲッターをコンポーネントとして小道具として供給していました。どういうわけか、Vuexはデータをフェッチしますが、コンポーネントを再レンダリングするために反応性が確実に作動しません。私の場合、コンポーネントkeyをプロップの属性に設定すると、ゲッター(および属性)が最終的に解決されたときに更新が保証されました。


1
これはきちんとした小さなトリックであり、基本的にコンポーネントの再インスタンス化を強制します(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>

Vueのこの部分をマスターするには、反応性の変更に関する公式ドキュメント-変更検出に関する警告を確認してください。必読です!


2
この更新要件に疑問を投げかける必要があることは間違いなく同意しますが、ビューポートが変更され、さまざまなアセットを表示する必要があるため(例として)、UIを再レンダリングする必要がある場合もあります。データは実際には変更されていない可能性があります。
the_dude_abides 2018

1
なぜリロードする必要があるのですか?場合によっては、ブラウザによってキャッシュされたリソースファイル(スタイルシート/ js)は、一定期間後に再ロードする必要があります。7日後に再読み込みが必要なスタイルシートがあり、ユーザーがページにアクセスしてタブを開いたままにし、7日後に戻ってそのページに移動した場合、CSSは7日以上前のものでした。
Aurovrata 2018年

@AchielVolckaertあなたはおそらくすでに答えを見つけましたが、はい、Vue.set()コンポーネント内でも機能します。
acdcjunior

1
@the_dude_abidesと@ Aurovrata、それらはリフレッシュの合法的な使用であると私は同意します。私が提起した質問は、人々が間違った理由でリフレッシュを行うことはめったにないということです。
acdcjunior

1
おそらく、Vueを純粋にレンダリングツールとして使用する、設計が不十分なWebアプリのバグを修正しようとしているだけかもしれません。たとえば、vueのクライアント側アプリケーション機能を無視して、サーバーにアクセスするたびにアプリケーション全体を再ロードします。現実の世界では、あなたが見つけたすべての嫌悪感を修正する時間があるとは限りません。
Warren Dew

30

これを読んで ください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>

私は時計も使用しています。状況によっては。


絶対に同意します!
ダイアモンド

私はほとんどVueをあきらめました。しかし、これのおかげで、Vueに対する私の信仰は回復されました。
jokab

リンクは実際にそれを行う方法を恐ろしい方法で示していません。私のアプリは恐ろしい方法をナビゲートするように設計されているので、残念ながらこれは私が必要とするものです。現在のページへの単純なURLは機能していないようです。少なくとも、私が扱っているアプリでは機能しません。そのため、恐ろしい方法を実行する方法についての説明が実際に必要です。
Warren Dew

@WarrenDew従ってください:stackoverflow.com/questions/3715047/...
ヤシュ

25

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


3
よりシンプル:this。$ router.go()
Marius

実際には@MariusAndreiana-.go()関数には1つの非オプションパラメータが必要です
a_lovelace



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

それとともに、すべての更新のオブジェクト(obj)値のすべての更新の使用this.$set(obj,'obj_key',value)uniqueKey更新this.uniqueKey++

それはこのように私のために働きました


6

これを行うには2つの方法があります。

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>

つまり、truevalueの値をfalseからtrueに変更するだけで、div間のコンポーネントが再度レンダリングされます。


1
私の意見では、これはコンポーネントをリロードする最もクリーンな方法です。created()メソッドの代わりに、初期化の要素を追加できます。
PiotrŻak2018年

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でkeyを使用し、その子を自動的に再読み込みします。


4
ソリューションに関する詳細な情報を提供してください。コードを追加し、キーワードをハイライトします
Agilanbu

0

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

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

申し訳ありませんが、ページのリロードメソッド(ちらつき)を除いて、どれも機能しません(:keyが機能しませんでした)。

そして私は私のために働く古い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.