Vue3+TypeScript实现首次加载引导视图:改用DOMContentLoaded事件的方案问询
Hey there! Let's work through this together since you're new to Vue 3 + TypeScript. First off, your current implementation works, but let's unpack why using DOMContentLoaded might not be the best fit here, plus give you a more Vue-idiomatic (and TypeScript-friendly) solution.
Why your DOMContentLoaded attempt didn't work
Vue's mounted hook already fires after your component's DOM has fully rendered—so it's the perfect safe spot to interact with elements in your template.
DOMContentLoaded is a browser-level event that triggers when the entire page's DOM is ready, which can happen before your Vue component finishes mounting (especially if your component is async-loaded or the page has other heavy resources). When that happens, your #splash element hasn't been rendered by Vue yet, so getElementById returns null, and your code fails.
In short: Your original use of mounted is actually more aligned with Vue's lifecycle than DOMContentLoaded would be. But if you still want to try the latter, we can make it work—though I'll show you a better approach first.
A better Vue 3 + TypeScript implementation (no direct DOM manipulation!)
As a Vue beginner, it's better to lean into Vue's reactive system instead of manually manipulating the DOM with getElementById or remove(). Here's a cleaner, type-safe version using template refs and reactive state:
Template code
<template> <!-- Use v-if to conditionally render the splash instead of removing it --> <div v-if="showSplash" ref="splashRef" class="splash"> <h1 class="fade-in">Hello</h1> <router-link to="/" @click="handleSplashClose">CLOSE</router-link> </div> <!-- Rest of your app content goes here --> </template>
Script (Composition API, TypeScript)
<script setup lang="ts"> import { ref, onMounted } from 'vue'; // Template ref for the splash element (TypeScript knows it's a div or null) const splashRef = ref<HTMLDivElement | null>(null); // Reactive variable to control if the splash is visible const showSplash = ref(false); // Check local storage to decide if we show the splash const checkSplashVisibility = () => { const loadCount = localStorage.getItem('pageLoadCount'); if (loadCount === '2') { showSplash.value = false; } else { showSplash.value = true; localStorage.setItem('pageLoadCount', '1'); } }; // Handle the close button click const handleSplashClose = () => { localStorage.setItem('pageLoadCount', '2'); showSplash.value = false; }; // Run our check when the component mounts onMounted(() => { checkSplashVisibility(); }); </script>
Why this is better:
- No manual DOM manipulation: Using
v-iflets Vue handle rendering/unrendering, which avoids bugs from messing with the DOM directly. - Type safety: TypeScript gives you autocomplete and error checking for the
splashRef(so you won't accidentally call a method that doesn't exist on a div). - Cleaner logic: All the splash-related code is grouped together, making it easier to maintain.
If you really want to use DOMContentLoaded
If you're set on using the browser event, you need to make sure the component's DOM exists before you try to access it. Here's how to adjust your code:
<script setup lang="ts"> import { onMounted } from 'vue'; const checkSplashStatus = () => { const loadCount = localStorage.getItem('pageLoadCount'); const splash = document.getElementById('splash'); // Guard clause in case the element doesn't exist yet if (!splash) return; if (loadCount === '2') { splash.remove(); } else { localStorage.setItem('pageLoadCount', '1'); } }; const handleSplashClose = () => { localStorage.setItem('pageLoadCount', '2'); const splash = document.getElementById('splash'); splash?.remove(); // Optional chaining to avoid errors if splash is already gone }; onMounted(() => { // Check if the DOM is already ready (since mounted fires after DOMContentLoaded usually) if (document.readyState === 'complete' || document.readyState === 'interactive') { checkSplashStatus(); } else { document.addEventListener('DOMContentLoaded', checkSplashStatus); } }); </script>
But again, this isn't better than using Vue's mounted hook. It adds unnecessary complexity because Vue already gives you a reliable way to interact with your component's DOM once it's ready.
内容的提问来源于stack exchange,提问作者desmondische

