返回上一页面如果没有上一页面返回首页

2,877 阅读2分钟

有这样一个需求就是,返回按钮的功能:如果有上一个页面,点击返回按钮,返回到上一个页面;如果没有上一个页面,点击返回按钮,返回到首页。

项目背景是 vue3.2 的,直接说解决方案了:利用 window.history.state.back 是否有值来判断是否有上一页。

// 有上一页则返回
if (window.history.state.back) {
  router.go(-1)
} else {
// 没有上一页则返回到首页
  router.replace({ path: '/home' })
}

这是因为 Vue Routerhistory.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 之前,用于代替 createdbeforeCreated。由于 setup 函数执行的时候项目还没有进行初始化,所以不能访问 datamethods 中的数据。

当然,我们可以使用全局的变量 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 也是行不通的。

Vue3笔记(二)了解组合式API的应用与方法 
Document.referrer
Vue Router