您可以强制Vue.js重新加载/重新渲染吗?


231

只是一个简单的问题。

您可以强制Vue.js重新加载 / 重新计算的一切吗?如果是这样,怎么办?


可能会在这里获得更好的支持github.com/vuejs/Discussion/issues
Cory Danielson

太好了,不知道那个讨论地点。我会在那里尝试。
戴夫

您最终得到回应了吗?我也很想知道。
奥德曼,2015年

记不清了。但是,这是我通过一些线索提出的问题:github.com/vuejs/Discussion/issues/356
Dave

我在视图中具有v-for指令,并且在手动交换该阵列上的两个对象时具有用例。此后,Vue不会自动重新呈现模板。我使用了解决方法:只需对该数组执行任何操作(先推送空对象,然后进行拼接),这将触发重新渲染。但这是特例。
Fyodor Khruschov '16

Answers:


237

试试这个魔术:

vm.$forceUpdate();

无需创建任何悬挂变量:)

更新:当我仅开始使用VueJS时,我找到了此解决方案。但是,进一步的探索证明了这种方法的重要性。据我所记得,有一阵子我摆脱了它,只是将所有未能自动刷新的属性(主要是嵌套属性)放入计算的属性中。

此处提供更多信息:https : //vuejs.org/v2/guide/computed.html


4
当我将它与Vue中的表单向导组件一起使用时,这确实对我有所帮助。尽管数据变量完整无缺,但我的表单字段字段却处于丢失状态。现在,当我返回时,我使用它来刷新视图,我不得不将其放置在setTimeout函数中。
吉米·伊伦洛亚

26
请注意,在vue文件中,您需要“ this。$ forceUpdate();”。
Katinka Hesselink,

1
这对于长时间的axios调用后更新a非常有用。
AlfredBr '19

4
以某种绝对奇怪的方式,$forceUpdate()从来没有在2.5.17上为我工作过。
阿巴娜·克拉拉

2
@AbanaClara $ forceUpdate()从来不是一个公共方法,我发现它在挖掘Vue的源代码。而且由于它的使用从来都不是Vue's的正确方法,因此也许可以将其剥离。由于我不再使用前端,因此无法确定它是否仍然存在。
鲍里斯·莫索诺夫

82

这似乎是从漂亮干净的解决方案matthiasg关于这个问题

:key="someVariableUnderYourControl"当您要完全重建组件时,也可以使用和更改密钥

对于我的用例,我将Vuex吸气剂作为道具送入组件。Vuex会以某种方式获取数据,但是无法可靠地启动反应性来重新呈现组件。就我而言,将组件设置为keyprop上的某个属性可确保在最终解决吸气剂(和属性)后刷新。


1
这是一个巧妙的小技巧,它基本上会强制重新初始化组件(mounted将运行,等等)
btk 18'Oct

1
@btk我同意,这可能不是“正确”的方式做事情,但它是一个相当干净的黑客,它是什么。
布莱恩功夫

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

1
为什么需要重新加载?在某些情况下,浏览器缓存的资源文件(样式表/ js)需要在一定时间后重新加载。我有一个样式表,需要在7天后重新加载,并且如果用户保持打开页面访问选项卡,并且在7天后浏览该页面又回来了,则CSS已有7天以上的历史了。
Aurovrata

@AchielVolckaert您可能已经找到了答案,但是可以,Vue.set()也可以在组件内部使用。
acdcjunior

1
我同意@the_dude_abides和@ Aurovrata,这些是刷新的合法用途。我提出的问题是,人们并非很少出于错误的原因进行刷新。
acdcjunior

1
也许您只是想解决一个设计不佳的Web应用程序中的错误,该应用程序纯粹将vue用作呈现工具,例如,只要它进入服务器就重新加载整个应用程序,而忽略了vue的客户端应用程序功能。在现实世界中,您并非总是有时间修复所发现的所有可憎之处。
沃伦·露

30

请阅读此 http://michaelnthiessen.com/force-re-render/

可怕的方法:重新加载整个页面
可怕的方法:使用v-if hack
更好的方法:使用Vue的内置forceUpdate方法
最好的方法:在组件上进行键更改

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

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

我还使用watch:在某些情况下。


绝对,我同意你的观点!
钻石

我差点放弃了Vue。但是,由于此,我对Vue的信念得以恢复。
jokab

该链接实际上并没有显示如何以可怕的方式进行操作,不幸的是,这是我所需要的,因为我的应用程序是围绕着以可怕的方式导航而设计的。指向当前页面的简单URL似乎不起作用,至少在我正在处理的应用程序中无效,因此我实际上需要有关如何以可怕方式进行操作的说明。
沃伦·露


25

尝试使用this.$router.go(0);手动重新加载当前页面。


3
更简单:this。$ router.go()
马吕斯

实际上,@ MariusAndreiana-.go()函数需要1个非可选参数
a_lovelace



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

以及每次更新的对象(obj)值中的每个更新都使用this.$set(obj,'obj_key',value)uniqueKey更新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>

因此,仅通过将truevalue的值从false更改为true即可导致div之间的组件重新呈现


1
我认为这是重新加载组件的最干净的方法。完全在created()方法中,您可以添加一些初始化内容。
PiotrŻak18年

5

为了重新加载/重新渲染/刷新组件,请停止长编码。有一种Vue.JS方式可以做到这一点。

只需使用:key属性。

例如:

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

我在BS Vue表插槽中使用了那个。告诉我我将为此组件做些事情,因此使其独特。


3

这对我有用。

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

另一个组件触发refresh-stores-list事件将导致当前组件重新呈现


2

我找到了一个方法。这有点hacky,但可以。

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

由于在其他标签上进行了更改,因此我想重新呈现图像库的问题。所以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

抱歉,除了页面重新加载方法(闪烁)外,它们都不适合我(: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>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.