You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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-if lets 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 12:42:31