你能把Vue.js强制到reload/re-render吗?
Can you force Vue.js to reload/re-render?
只是一个简短的问题。
你能强制Vue.js
重新加载/重新计算一切吗?如果是,怎么做?
使用vm.$set('varName', value)
.
在 Change_Detection_Caveats.(已过时 link).
中查找详细信息
我找到了一个方法。这有点 hacky 但有效。
vm.$set("x",0);
vm.$delete("x");
其中 vm
是您的视图模型对象,x
是一个不存在的变量。
Vue.js 会在控制台日志中对此进行抱怨,但它确实会触发所有数据的刷新。测试版本 1.0.26.
试试这个魔法:
vm.$forceUpdate();
//or in file components
this.$forceUpdate();
无需创建任何悬挂变量 :)
更新: 我刚开始使用 VueJS 时就找到了这个解决方案。然而,进一步的探索证明这种方法是一个拐杖。据我所知,有一段时间我摆脱了它,只是将所有未能自动刷新的属性(主要是嵌套的)放入计算属性中。
这似乎是 matthiasg on this issue 的一个非常干净的解决方案:
you can also use :key="someVariableUnderYourControl"
and change the key when you want to component to be completely rebuilt
对于我的用例,我将 Vuex getter 作为道具输入到组件中。 Vuex 会以某种方式获取数据,但反应性不会可靠地启动以重新呈现组件。在我的例子中,将组件 key
设置为 prop 上的某个属性可以保证在 getters(和属性)最终解析时刷新。
使用 v-if 指令
<div v-if="trulyvalue">
<component-here />
</div>
因此只需将 trulyvalue 的值从 false 更改为 true 就会导致 div 之间的组件再次重新呈现
为什么?
...您需要强制更新吗?
也许您没有充分探索 Vue:
To have Vue automatically react to value changes, the objects must be initially declared in data
. Or, if not, they must be added using Vue.set()
.
查看下面演示中的评论。或者打开same demo in a JSFiddle here.
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。必读!
尝试使用this.$router.go(0);
手动重新加载当前页面。
当然..您可以随时使用 key 属性强制重新渲染(重新创建)。
<mycomponent :key="somevalueunderyourcontrol"></mycomponent>
请参阅 https://jsfiddle.net/mgoetzke/epqy1xgf/ 示例
这里也讨论过:https://github.com/vuejs/Discussion/issues/356#issuecomment-336060875
请阅读本文
http://michaelnthiessen.com/force-re-render/
The horrible way: reloading the entire page
The terrible way:
using the v-if hack
The better way: using Vue’s built-in
forceUpdate method
The best way: key-changing on your
component
<template>
<component-to-re-render :key="componentKey" />
</template>
<script>
export default {
data() {
return {
componentKey: 0,
};
},
methods: {
forceRerender() {
this.componentKey += 1;
}
}
}
</script>
我也用 watch: 在某些情况下。
这对我有用。
created() {
EventBus.$on('refresh-stores-list', () => {
this.$forceUpdate();
});
},
其他组件触发 refresh-stores-list 事件会导致当前组件重新渲染
<router-view :key="$route.params.slug" />
只需将密钥与您的任何参数一起使用即可自动重新加载子项..
为我工作
data () {
return {
userInfo: null,
offers: null
}
},
watch: {
'$route'() {
this.userInfo = null
this.offers = null
this.loadUserInfo()
this.getUserOffers()
}
}
为了reload/re-render/refresh分量,停止长编码。有一种 Vue.JS 方法可以做到这一点。
只需使用 :key
属性。
例如:
<my-component :key="unique" />
我正在 BS Vue Table Slot 中使用那个。告诉我要为这个组件做点什么,让它独一无二。
<my-component :key="uniqueKey" />
与它一起使用 this.$set(obj,'obj_key',value)
并为对象 (obj) 值中的每个更新更新 uniqueKey
每次更新 this.uniqueKey++
这种方式对我有用
所以有两种方法可以做到这一点,
- 您可以在方法处理程序中使用
$forceUpdate()
即
<your-component @click="reRender()"></your-component>
<script>
export default {
methods: {
reRender(){
this.$forceUpdate()
}
}
}
</script>
- 你可以给你的组件一个
:key
属性并在想要重新渲染时递增
<your-component :key="index" @click="reRender()"></your-component>
<script>
export default {
data() {
return {
index: 1
}
},
methods: {
reRender(){
this.index++
}
}
}
</script>
添加此代码:
this.$forceUpdate()
除了页面重新加载方法(闪烁),none 对我有效(:密钥无效)。
我从旧的 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>
将 :key
添加到 vue-router 库的 router-view
组件的方法对我来说很麻烦,所以我去 vue-router 的 'in-component guard' 进行拦截当同一路线上的路径更新时相应地更新和刷新整个页面(因为 $router.go、$router.push、$router.replace 没有任何帮助)。唯一需要注意的是,我们要通过刷新页面来暂时打破 singe-page 应用程序的行为。
beforeRouteUpdate(to, from, next) {
if (to.path !== from.path) {
window.location = to.path;
}
},
2021 年 12 月更新:
您可以通过添加 :key="$route.fullPath".
来 force-reload 组件
对于Child组件:
<Child :key="$route.fullPath" />
对于router-view标签:
<router-view :key="$route.fullPath" />
但是,:key="$route.fullPath"只能force-reload 不同路线的组件 但不是 同一路线 的组成部分。为了能够 force-reload 相同路线 的组件,我们需要添加 "value" 和数组 到 :key="$route.fullPath" 和更改“值”。所以它变成了 :key="[$route.fullPath, value]" 我们需要 change "value".
*我们可以将数组赋值给: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 中正确 force-reload 组件。这就是目前 Vue 的问题。
对于仍在四处寻找的人,现在有一个包。
https://github.com/gabrielmbmb/vuex-multi-tab-state
我所要做的就是安装它并将其添加到我在 main.ts 中的插件中(如该页面所示),它完全符合我的要求。
只是一个简短的问题。
你能强制Vue.js
重新加载/重新计算一切吗?如果是,怎么做?
使用vm.$set('varName', value)
.
在 Change_Detection_Caveats.(已过时 link).
我找到了一个方法。这有点 hacky 但有效。
vm.$set("x",0);
vm.$delete("x");
其中 vm
是您的视图模型对象,x
是一个不存在的变量。
Vue.js 会在控制台日志中对此进行抱怨,但它确实会触发所有数据的刷新。测试版本 1.0.26.
试试这个魔法:
vm.$forceUpdate();
//or in file components
this.$forceUpdate();
无需创建任何悬挂变量 :)
更新: 我刚开始使用 VueJS 时就找到了这个解决方案。然而,进一步的探索证明这种方法是一个拐杖。据我所知,有一段时间我摆脱了它,只是将所有未能自动刷新的属性(主要是嵌套的)放入计算属性中。
这似乎是 matthiasg on this issue 的一个非常干净的解决方案:
you can also use
:key="someVariableUnderYourControl"
and change the key when you want to component to be completely rebuilt
对于我的用例,我将 Vuex getter 作为道具输入到组件中。 Vuex 会以某种方式获取数据,但反应性不会可靠地启动以重新呈现组件。在我的例子中,将组件 key
设置为 prop 上的某个属性可以保证在 getters(和属性)最终解析时刷新。
使用 v-if 指令
<div v-if="trulyvalue">
<component-here />
</div>
因此只需将 trulyvalue 的值从 false 更改为 true 就会导致 div 之间的组件再次重新呈现
为什么?
...您需要强制更新吗?
也许您没有充分探索 Vue:
To have Vue automatically react to value changes, the objects must be initially declared in
data
. Or, if not, they must be added usingVue.set()
.
查看下面演示中的评论。或者打开same demo in a JSFiddle here.
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。必读!
尝试使用this.$router.go(0);
手动重新加载当前页面。
当然..您可以随时使用 key 属性强制重新渲染(重新创建)。
<mycomponent :key="somevalueunderyourcontrol"></mycomponent>
请参阅 https://jsfiddle.net/mgoetzke/epqy1xgf/ 示例
这里也讨论过:https://github.com/vuejs/Discussion/issues/356#issuecomment-336060875
请阅读本文 http://michaelnthiessen.com/force-re-render/
The horrible way: reloading the entire page
The terrible way: using the v-if hack
The better way: using Vue’s built-in forceUpdate method
The best way: key-changing on your component
<template>
<component-to-re-render :key="componentKey" />
</template>
<script>
export default {
data() {
return {
componentKey: 0,
};
},
methods: {
forceRerender() {
this.componentKey += 1;
}
}
}
</script>
我也用 watch: 在某些情况下。
这对我有用。
created() {
EventBus.$on('refresh-stores-list', () => {
this.$forceUpdate();
});
},
其他组件触发 refresh-stores-list 事件会导致当前组件重新渲染
<router-view :key="$route.params.slug" />
只需将密钥与您的任何参数一起使用即可自动重新加载子项..
为我工作
data () {
return {
userInfo: null,
offers: null
}
},
watch: {
'$route'() {
this.userInfo = null
this.offers = null
this.loadUserInfo()
this.getUserOffers()
}
}
为了reload/re-render/refresh分量,停止长编码。有一种 Vue.JS 方法可以做到这一点。
只需使用 :key
属性。
例如:
<my-component :key="unique" />
我正在 BS Vue Table Slot 中使用那个。告诉我要为这个组件做点什么,让它独一无二。
<my-component :key="uniqueKey" />
与它一起使用 this.$set(obj,'obj_key',value)
并为对象 (obj) 值中的每个更新更新 uniqueKey
每次更新 this.uniqueKey++
这种方式对我有用
所以有两种方法可以做到这一点,
- 您可以在方法处理程序中使用
$forceUpdate()
即
<your-component @click="reRender()"></your-component>
<script>
export default {
methods: {
reRender(){
this.$forceUpdate()
}
}
}
</script>
- 你可以给你的组件一个
:key
属性并在想要重新渲染时递增
<your-component :key="index" @click="reRender()"></your-component>
<script>
export default {
data() {
return {
index: 1
}
},
methods: {
reRender(){
this.index++
}
}
}
</script>
添加此代码:
this.$forceUpdate()
除了页面重新加载方法(闪烁),none 对我有效(:密钥无效)。
我从旧的 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>
将 :key
添加到 vue-router 库的 router-view
组件的方法对我来说很麻烦,所以我去 vue-router 的 'in-component guard' 进行拦截当同一路线上的路径更新时相应地更新和刷新整个页面(因为 $router.go、$router.push、$router.replace 没有任何帮助)。唯一需要注意的是,我们要通过刷新页面来暂时打破 singe-page 应用程序的行为。
beforeRouteUpdate(to, from, next) {
if (to.path !== from.path) {
window.location = to.path;
}
},
2021 年 12 月更新:
您可以通过添加 :key="$route.fullPath".
来 force-reload 组件对于Child组件:
<Child :key="$route.fullPath" />
对于router-view标签:
<router-view :key="$route.fullPath" />
但是,:key="$route.fullPath"只能force-reload 不同路线的组件 但不是 同一路线 的组成部分。为了能够 force-reload 相同路线 的组件,我们需要添加 "value" 和数组 到 :key="$route.fullPath" 和更改“值”。所以它变成了 :key="[$route.fullPath, value]" 我们需要 change "value".
*我们可以将数组赋值给: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 中正确 force-reload 组件。这就是目前 Vue 的问题。
对于仍在四处寻找的人,现在有一个包。
https://github.com/gabrielmbmb/vuex-multi-tab-state
我所要做的就是安装它并将其添加到我在 main.ts 中的插件中(如该页面所示),它完全符合我的要求。