对于路由使用的ref的疑问

<script setup>
import { ref, computed } from 'vue'
import Home from './Home.vue'
import About from './About.vue'
import NotFound from './NotFound.vue'
const routes = {
  '/': Home,
  '/about': About
}
const currentPath = ref(window.location.hash)
window.addEventListener('hashchange', () => {
  currentPath.value = window.location.hash
})
const currentView = computed(() => {
  return routes[currentPath.value.slice(1) || '/'] || NotFound
})
</script>
<template>
  <a href="#/">Home</a> |
  <a href="#/about">About</a> |
  <a href="#/non-existent-path">Broken Link</a>
  <component :is="currentView" />
</template>为什么还要重新赋值一遍currentPath.value = window.location.hash原本const currentPath = ref(window.location.hash)不就代表ref括号的参数默认是这个变量的value了吗

 

 

 

 

这个问题非常好,它触及了 Vue 响应式系统与原生浏览器API(如 window.location.hash)如何交互的核心,也是很多初学者容易困惑的地方。

简单来说,ref() 只在创建时读取一次 window.location.hash 的值,它并不会持续自动跟踪这个值的变化。

我们来详细分解一下这个过程。


 

1. ref() 的作用:“一次性快照”,而非“持续绑定”

当您执行这行代码时:

JavaScript
 
const currentPath = ref(window.location.hash)

背后发生的事情是:

  1. JavaScript 首先执行括号里的内容:window.location.hash。假设页面刚加载时,URL是 ...#/about,那么这个表达式会返回一个普通的字符串 "#about"

  2. 然后,Vue 的 ref() 函数接收到这个字符串 "#about",并用它来创建一个响应式对象

  3. 这个响应式对象被赋值给 currentPath 变量。此时,currentPath.value 的值就是字符串 "#about"

最关键的一点是:从这一刻起,currentPath.valuewindow.location.hash 之间就没有任何关系了。ref() 只是在初始化的那一瞬间,拍了一张 window.location.hash 的“快照”作为自己的初始值。

window.location.hash 是一个原生的浏览器属性,它本身并不是一个 Vue 的响应式源。当浏览器因为用户点击链接而改变了它的值时,Vue 的响应式系统是完全不知情的。

 

2. addEventListener 的作用:“手动连接的桥梁”

既然 Vue 无法自动知道 window.location.hash 变了,我们就需要一个“信使”来告诉它。这个“信使”就是 window.addEventListener

JavaScript
 
// 当浏览器的 hash 值发生变化时,请执行这个函数
window.addEventListener('hashchange', () => {
  // 这就是信使要传递的消息:
  // "嘿,Vue!请把 currentPath 的值更新为浏览器最新的 hash 值!"
  currentPath.value = window.location.hash
})
  • 'hashchange' 事件: 这是浏览器提供的标准事件。每当 URL 的 hash 部分(# 后面的内容)发生改变时,浏览器就会触发这个事件。

  • () => { ... }: 这是事件触发时要执行的回调函数。

  • currentPath.value = window.location.hash: 这就是我们手动重新赋值的关键步骤。我们在这里读取最新的 window.location.hash 值,并把它赋给 currentPath.value

因为 currentPath 是一个 ref,所以当它的 .value 被重新赋值时,Vue 的响应式系统就会被激活。Vue 会注意到 currentPath 变了,然后:

  1. 重新计算 currentView 这个计算属性。

  2. currentView 返回了新的组件(比如从 Home 变成了 About)。

  3. Vue 自动将模板中的 <component :is="currentView" /> 更新为新的组件。


 

一个生动的比喻

  • const currentPath = ref(window.location.hash):你抬头看了一眼公共广场上的大钟 (window.location.hash),然后把当前时间写在了你自己的个人白板 (currentPath) 上。

  • 之后,你的白板上的时间就不会再动了,即使广场上的大钟在不停地走。你的白板和大钟之间没有自动同步的魔法。

  • window.addEventListener('hashchange', ...):你雇了一个人(事件监听器),让他一直盯着广场上的大钟。

  • currentPath.value = window.location.hash:你告诉这个人,每当大钟的时间变了,就立刻跑过来,擦掉你白板上的旧时间,然后写上大钟的最新时间

正是这个“手动更新白板”的动作,才让你的 Vue 应用(办公室里的其他人)知道现在是几点了。

 

posted @ 2025-10-07 07:59  BKYNEKO  阅读(9)  评论(0)    收藏  举报