327

只是一个快速的问题。

您可以强制Vue.js重新加载/重新计算所有内容吗?如果是这样,怎么做?

4

20 回答 20

317

试试这个魔法:

vm.$forceUpdate();
//or in file components
this.$forceUpdate();

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

更新:当我刚开始使用 VueJS 时,我发现了这个解决方案。然而,进一步的探索证明这种方法是一种拐杖。据我回忆,有一段时间我摆脱了它,只是将所有无法自动刷新的属性(主要是嵌套属性)放入计算属性中。

更多信息:https ://vuejs.org/v2/guide/computed.html

于 2016-11-14T10:45:32.290 回答
121

这似乎是matthiasg这个问题上的一个非常干净的解决方案:

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

对于我的用例,我将一个 Vuex getter 作为道具提供给组件。Vuex 会以某种方式获取数据,但反应性并不能可靠地重新渲染组件。在我的例子中,将组件设置key为 prop 上的某个属性可以保证在 getter(和属性)最终解决时刷新。

于 2018-02-12T20:44:22.770 回答
83

请阅读此 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: 在某些情况下。

于 2019-01-25T14:42:28.360 回答
64

为什么?

...您需要强制更新吗?

也许你没有在最好的情况下探索 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 的这一部分,请查看Official Docs on Reactivity - Change Detection Caveats。这是必须阅读的!

于 2018-04-14T17:37:25.087 回答
59

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

于 2018-06-08T09:06:55.343 回答
25

使用vm.$set('varName', value). 在Change_Detection_Caveats中查找详细信息。

于 2016-01-21T13:01:54.737 回答
19

当然..您可以随时使用 key 属性强制重新渲染(重新创建)。

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

有关示例,请参见https://jsfiddle.net/mgoetzke/epqy1xgf/

这里也讨论过:https ://github.com/vuejs/Discussion/issues/356#issuecomment-336060875

于 2018-08-18T14:34:06.147 回答
14
<my-component :key="uniqueKey" />

与它一起使用this.$set(obj,'obj_key',value) 和更新uniqueKey每次更新的对象(obj)值的每次更新this.uniqueKey++

它以这种方式对我有用

于 2019-11-19T06:08:01.717 回答
12

所以有两种方法可以做到这一点,

  1. 您可以$forceUpdate()在方法处理程序中使用,即

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

<script>
export default {
   methods: {
     reRender(){
        this.$forceUpdate()
     }
   }
}
</script>
  1. 您可以为:key组件提供一个属性,并在想要重新渲染时增加

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

<script>
export default {
   data() {
     return {
        index: 1
     }
   },
   methods: {
     reRender(){
        this.index++
     }
   }
}
</script>
于 2020-02-14T13:58:32.593 回答
7

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

只需使用:key属性。

例如:

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

我在 BS Vue Table Slot 中使用那个。告诉我会为这个组件做点什么,所以让它独一无二。

于 2019-09-27T10:01:25.570 回答
6

使用 v-if 指令

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

所以简单地通过将truevalue的值从false更改为true会导致div之间的组件再次重​​新渲染

于 2018-03-08T20:56:15.480 回答
4

这对我有用。

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

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

于 2019-02-22T08:39:23.517 回答
2

我找到了一个方法。这有点hacky但有效。

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

您的视图模型对象在哪里vm,并且x是一个不存在的变量。

Vue.js 会在控制台日志中抱怨这一点,但它确实会触发所有数据的刷新。使用版本 1.0.26 测试。

于 2016-09-03T22:11:27.420 回答
2
<router-view :key="$route.params.slug" />

只需将密钥与您的任何参数一起使用它的自动重新加载子项..

于 2019-04-22T09:31:58.883 回答
2

为我工作

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

    watch: {
        '$route'() {
            this.userInfo = null
            this.offers = null
            this.loadUserInfo()
            this.getUserOffers()
        }
    }
于 2019-06-20T21:33:54.850 回答
2

2021 年 12 月更新:

您可以通过添加:key="$route.fullPath"来强制重新加载组件。

对于组件:

<Child :key="$route.fullPath" />

对于路由器视图标签:

<router-view :key="$route.fullPath" />

但是,:key="$route.fullPath"只能强制重新加载不同路由的组件,而不能强制重新加载同一路由的组件。为了能够强制重新加载同一路由的组件,我们需要将带有数组的 "value"添加到:key="$route.fullPath"更改 "value"。所以它变成:key="[$route.fullPath, value]"我们需要改变 "value"

*我们可以将Array分配给:key=

<template>
  <Child 
    :key="[$route.fullPath, value]" // Can assign "Array" to ":key="
    @childReload="reload" // Call @click="$emit('childReload')" in   
  />                      // Child Component to increment the value.
</template> 

    OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR

<template>
  <router-view 
    :key="[$route.fullPath, value]" // Can assign "Array" to ":key="
    @routerViewReload="reload" // Call @click="$emit('routerViewReload')"
  />                           // in Child Component to increment the value.
</template>
    
<script>
export default {
  name: "Parent", components: { Child, },
  data() {
    return {
      value: 0,
    };
  },
  methods: {
    reload() {
      this.value++;
    }
  }
}
</script>

然而,为了继续使用 "$route.fullPath" 和 "value" 有时会导致一些错误,所以只有当像Click这样的事件发生时,我们才使用"$route.fullPath""value"。除了像Click这样的事件发生时,我们总是只需要使用"$route.fullPath"

这是最终代码:

<template>
  <Child 
    :key="state ? $route.fullPath : [$route.fullPath, value]"
    @childReload="reload" // Call @click="$emit('childReload')" in
  />                      // Child Component to increment the value.
</template>
    
    OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR OR
    
<template>
  <router-view 
    :key="state ? $route.fullPath : [$route.fullPath, value]"
    @routerViewReload="reload" // Call @click="$emit('routerViewReload')" in
  />                           // Child Component to increment the value.
</template>
        
<script>
export default {
  name: "Parent", components: { Child, },
  data() {
    return {
      state: true,
      value: 0,
    };
  },
  methods: {
    reload() {
      this.state = false;
      this.value++;
      this.$nextTick(() => this.state = true);
    }
  }
}
</script>

不幸的是,没有简单的方法可以在 Vue 中正确地强制重新加载组件。这就是 Vue 目前的问题。

于 2021-09-20T23:44:45.657 回答
1

添加此代码:

this.$forceUpdate()
于 2020-04-20T05:32:15.513 回答
1

除了页面重新加载方法(闪烁)之外,它们都不适合我(: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>
于 2020-05-30T10:12:29.183 回答
1

添加:key到 vue-router 库的router-view组件原因的方法对我来说是错误的,所以我去 vue-router 的“组件内防护”来拦截更新并在同一条路径上更新路径时相应地刷新整个页面(如$router.go、$router.push、$router.replace 没有任何帮助)。唯一需要注意的是,我们要通过刷新页面来打破单页应用程序的行为。

  beforeRouteUpdate(to, from, next) {
    if (to.path !== from.path) {
      window.location = to.path;
    }
  },
于 2020-11-09T06:49:57.550 回答
0

对于仍在四处张望的人,现在有一个包。

https://github.com/gabrielmbmb/vuex-multi-tab-state

我所要做的就是安装它并将它添加到我在 main.ts 中的插件中(正如它在该页面上显示的那样),它完全符合我的要求。

于 2022-02-03T16:50:48.777 回答