有这样一个需求就是,返回按钮的功能:如果有上一个页面,点击返回按钮,返回到上一个页面;如果没有上一个页面,点击返回按钮,返回到首页。
项目背景是 vue3.2 的,直接说解决方案了:利用 window.history.state.back 是否有值来判断是否有上一页。
// 有上一页则返回
if (window.history.state.back) {
router.go(-1)
} else {
// 没有上一页则返回到首页
router.replace({ path: '/home' })
}
这是因为 Vue Router 在 history.state 中保存了导航信息如滚动条位置、上一页等。 router.vuejs.org/guide/migra…
We use the history state to save information about the navigation like the scroll position, previous location, etc.
在得到最优解之前进行了其他方法的尝试,虽然都没有成功,但是记录一下。这中间涉及到挺多细节,巩固一下知识。
其他尝试
window.history.length
行不通,为什么呢?因为window.history.length 复制到搜索栏打开是 2,而不是 0;通过链接跳转到浏览器打开是 1,而不是 0。这就混乱了,无法用 window.history.length 的值来判断是否有上一个页面。
beforeRouteEnter
很抱歉,beforeRouteEnter 是 vue2 中才有的 API,当然在 vue3 中也可以通过导入 defineComponent 来使用 beforeRouteEnter。
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
beforeRouteEnter: (to, from, next) => {
next()
}
})
</script>
<script lang="ts" setup>
...
</script>
问题是:vue3 中 setup 位于 beforeCreated 之前,用于代替 created 和 beforeCreated。由于 setup 函数执行的时候项目还没有进行初始化,所以不能访问 data 或 methods 中的数据。
当然,我们可以使用全局的变量 globalPrePath 记录上一个页面的路径。在处理返回逻辑时使用全局变量 globalPrePath。
<script lang="ts">
import { defineComponent, ref, } from 'vue'
let globalPrePath = ''
export default defineComponent({
beforeRouteEnter: (to, from, next) => {
globalPrePath = from.path
next()
},
})
</script>
<script setup lang="ts">
const handleBack = ()=>{
if(globalPrePath){
router.go(-1)
} else {
// 没有上一页则返回到首页
router.replace({ path: '/home' })
}
}
</script>
Vue2.x配置(data、methos、computed...)中可以访问到 setup 中的属性、方法defineComponent 中可以,setup 语法糖中的不行。
<script lang="ts">
import { defineComponent, ref, } from 'vue'
export default defineComponent({
methods: {
test(){
console.log(this.global) // 100
}
},
setup(){
const global = ref(100)
return{
global
}
}
})
</script>
setup 语法糖中的变量访问不到。
<script lang="ts">
import { defineComponent, ref, } from 'vue'
export default defineComponent({
methods: {
test(){
console.log(this.global) // undefined
}
},
})
</script>
<script setup lang="ts">
const global = ref(100)
</script>
document.referrer
Document.referrer 返回的是一个 URI,当前页面就是从这个 URI 所代表的页面跳转或打开的。
这个属性只能判断页面从哪里打开的,对于现在的单页 Web 应用(SPA)来说,几个路由页面跳转,document.referrer 是不变的。
onBeforeRouteUpdate
对于组件内路由组合 API onBeforeRouteUpdate 来说,只有组件第一次加载页面并不会触发,只有组件加载完成之后,路由参数(params 或者 query)变化才会触发。
<script lang="ts" setup>
const router = useRouter()
const changePage = ()=>{
router.push({name: 'GovWarn', query: {t: new Date()}})
}
</script>
显然这个 API 也是行不通的。