Vue / Intermediate: feature state and effect ownership / Lesson 8
Vue Router and route-owned state
Model navigation as a history and parameter contract while keeping route changes distinct from server authorization.
On this page
Lesson goals
- Define routes, named navigation, and history assumptions.
- React to reused route components without losing ownership.
Choose history behavior explicitly
The example uses memory history for a controlled fixture. A real SSR integration needs a fresh request-owned router rather than this fixture singleton. Memory history does not automatically read the browser URL and needs explicit navigation to establish its initial location. A browser application commonly uses web history, which requires hosting fallback behavior for direct nested URLs; that deployment requirement is separate from component code. Hash history has different URL and server tradeoffs. The route components below are app-defined SFCs, not supplied by the router. Keep missing-record and error rendering inside a clear feature boundary rather than assuming every matched path has valid data.
import { createRouter, createMemoryHistory } from "vue-router"
import NoteList from "./NoteList.vue"
import NoteDetail from "./NoteDetail.vue"
export const router = createRouter({
history: createMemoryHistory(),
routes: [
{ path: "/notes", name: "notes", component: NoteList },
{ path: "/notes/:id", name: "note", component: NoteDetail }
]
})
The app must install this router, supply both SFCs, and push an initial location in its controlled setup. This is a configuration fragment, not a running browser application. No navigation, server, or route request is performed here.
Observe the parameter that defines the task
Navigating from one id to another can reuse the same route component instance. A mounted hook alone therefore may not reload the intended record. In Composition API, useRoute exposes the reactive route; watch the specific parameter or use a relevant route-update guard rather than watching the entire object indiscriminately. Validate the parameter and handle missing data. Keep request invalidation aligned with id changes so a slow old result cannot overwrite the new destination. Query and hash changes may have different semantics and should not trigger unrelated work merely because the route object changed.
Keep navigation policy and access control distinct
Guards can coordinate client navigation, unsaved-change prompts, and redirects, but a user can call an API without passing through the interface. Server authorization must protect the actual resource. Direct-entry handling also needs correct loading, error, and not-found states. Update document titles and manage meaningful focus after route transitions so a client-side navigation remains understandable with a keyboard or screen reader. Do not assume a URL change alone announces a new task. Test intended history behavior with a controlled router and representative direct links, then verify hosting behavior separately under the project’s deployment process.
Common errors and fixes
Changing the id displays the old record
- Why it happens
- The component is reused and loading ran only on mount.
- How to fix it
- Observe the relevant parameter and invalidate obsolete requests.
- Prevent it next time
- Test navigation between ids on the same route record.
Nested links fail on a direct page load
- Why it happens
- Web-history hosting fallback is missing or incorrect.
- How to fix it
- Review the authorized hosting configuration and not-found behavior.
- Prevent it next time
- Document history-mode deployment assumptions.
A route guard is treated as data authorization
- Why it happens
- Client navigation is confused with the protected server operation.
- How to fix it
- Enforce permission at the API or data-service boundary.
- Prevent it next time
- Test direct resource access independently.
Check your understanding
1. Why might onMounted not run again for /notes/n1 to /notes/n2?
Show worked solution
The same route component instance can be reused. Watch the id source or use a suitable route-update integration, and verify loading and cancellation for the new task. Forcing a remount is a separate design choice with state-lifetime consequences.
2. A client guard blocks an editor page. Does it secure the edit API?
Show worked solution
No. The API must authenticate and authorize each protected action regardless of client routing. The guard can improve navigation experience but is not the server trust boundary.
Key takeaways
- Route parameters define task identity and can change without remounting.
- History mode has explicit hosting assumptions.
- Guards and server permission are different controls.