用生命谱写代码的赞歌

0%

Vue 微信网页刷新问题

js 刷新页面的方式

  1. location.reload(): 类似于 f5 刷新页面
  2. window.location.replace('http://www.zhidianzhuli.com'): 用一个新页面替换当前页面达到刷新目的
  3. <meta http-equiv="refresh" content="5">: 使用 meta 标签 5 秒后自动刷新

vue 单页面应用在微信浏览器内刷新

location.reload() 在某些条件下不起作用,例如直接从微信服务号抽屉菜单进入页面后,无法通过 location.reload() 刷新

window.location.replace() 在微信浏览器中使用当前网页的 url 无法刷新

原因

vue 的前端路由是由 vue-router 管理并采用 hash 模式,url 类似于 http://www.zhidianzhuli.com/#/cid?id=468直接修改 id 或者 在 id 之后添加其他查询信息对 vue-router 有效,因为 hash 模式下,vue-rouer 只关心 # 后的信息变化。但是浏览器认为 hash 的变化不是 url 变化,所以 window.location.replace() 刷新方式无效

解决方式

在 Ajax 请求成功之后直接修改 window.location.search,做到真正改变查询参数,即 window.location.search = '?v=' + Date.now()。修改后的 url 变成了 http://www.zhidianzhuli.com/?v=1553772570335#/cid?id=468,浏览器页自动进行了刷新

通过 vue-router 刷新当前 route

利用 v-if 控制 router-view,在路由容器组件,如 App.vue 中实现一个刷新方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<template>
<div id="app" class="pageBg">
<keep-alive>
<router-view v-if="$route.meta.keepAlive && isRouterAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive && isRouterAlive"></router-view>
</div>
</template>

<script>
export default {
name: 'App',
data() {
return {
isRouterAlive: true
}
},
methods: {
// 页面重新加载
reload() {
this.isRouterAlive = false
this.$nextTick(() => (this.isRouterAlive = true))
}
}
}
</script>

然后,在其它任何想刷新自己的路由页面中执行 this.$root.reload() 或者 this.$parent.reload()

如果 $root 节点不是路由容器组件,可以使用 provide / inject 来传递 reload

父组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<template>
<div id="app" class="pageBg">
<router-view v-if="isRouterAlive"></router-view>
</div>
</template>

<script>
export default {
name: 'App',
provide() {
return {
reload: this.reload
}
},
data() {
return {
isRouterAlive: true
}
},
methods: {
// 页面重新加载
reload() {
this.isRouterAlive = false
this.$nextTick(() => (this.isRouterAlive = true))
}
}
}
</script>

子组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import { setItem } from 'extra/js/api'
export default {
inject: ['reload'],
name: 'voucher',
data() {
return {}
},
methods: {
setMark(obj) {
setItem({
type: obj.type,
...
blacklist: obj.blacklist
}).then(res => {
if (res.data.code === '1001') {
Toast({
message: '标记成功',
position: 'bottom',
duration: 2000
})
setTimeout(() => {
this.reload()
}, 600)
} else if () {
...
} else {
...
}
})
}
}
}