场景:页面顶部操作栏是公共组件(每个页面都会有的),需求是点击顶部操作栏中的切换地区按钮,除了顶部的其他页面数据要跟着变化
Vue项目中刷新当前页面常用的方法
- JS 原生刷新页面方法:
window.location.reload()
- 利用路由刷新的方法:
this.$route.go(0)
- 利用 vue 提供的 provide 和 inject 自定义刷新
前两种刷新页面的方法,虽然代码简单,但比较粗暴,属于强制刷新整个页面,会出现短时间的白屏空隙,用户体验不好
下面只总结第三种刷新页面的方法,可以很好地解决刷新但不出现白屏的问题。
利用 provide
和 inject
实现页面刷新
- 首先在祖先组件中比如 App.vue 的 <router-link /> 标签中添加判断条件 v-if
<router-link v-if='isRouterAlive'/>
- 其次在 data 里面添加
isRouetrAlive
,这个属性名可以自定义,默认设置为true
,如果为false
整个页面就不会显示了。
data () {
return {
isRouterAlive: true
}
}
-
然后在 methods 里面添加一个刷新方法
methods: {
reload () {
this.isRouterAlive = false
this.$nextTick(() => {
this.isRouterAlive = true
})
}
}
-
最后需要把这个函数 provide 出去
provide () {
return {
reload: this.reload
}
}
祖先组件App.vue 组件上的设置已经完成,在需要刷新的页面上注入这个函数然后调用就可。
-
首先注入这个函数,注意
inject
要放到data
之前,否则会报错,报错原因有待研究。。
inject: ['reload']
- 然后再需要刷新的地方调用即可
refresh () {
this.reload()
}
备注:这种方法不论子组件有多深,只要调用了inject那么就可以注入provide中的数据。
完整代码如下:
App.vue
<template>
<div id="app">
<div class="wrap">
<router-view v-if="isRouterAlive"></router-view>
</div>
</div>
</template>
<script>
export default {
name: 'App',
provide () {
return {
reload: this.reload
}
},
data () {
return {
isRouterAlive: true
}
},
methods: {
reload () {
this.isRouterAlive = false
this.$nextTick(function() {
this.isRouterAlive = true
})
}
}
}
</script>
调用刷新方法的地方:
<template>
<button @click="refresh"></button>
</template>
<script>
export default{
name: 'refresh',
inject: ['reload'],
methods: {
refresh () {
this.reload()
}
}
}
</script>
补充:可能出现问题的地方
- 控制台报错 Maximum call stack size exceeded 原因:
inject:['reload']
放在了data
下面导致。 - 控制台报错 this.reload is not a funciton... 原因:
App.vue
组件中已经有了methods
,但我没仔细看于是多写了一个methods
,reload()
方法被覆盖