Splash sobre a primeira página
Mantenha o splash de abertura acima do <RouterView> para que a primeira página nativa possa montar por baixo dele. Remover a camada revela essa mesma página, sem adicionar uma entrada de splash ao histórico de navegação.
Se o splash for uma rota, chamar replace() cria o destino quando o splash está saindo. No Android, esse trabalho pode disputar a thread de UI com a animação de saída. Uma camada sobreposta permite terminar a criação da página antes de iniciar a animação de saída; ela não transfere a inicialização para outra thread.
Mantenha o RouterView montado
Depois da instalação normal do router, salve este exemplo como App.vue e o próximo componente como Splash.vue no mesmo diretório:
<script setup lang="ts">
import { ref } from 'nativescript-vue'
import { RouterView } from 'vue-router-ns'
import Splash from './Splash.vue'
const showSplash = ref(true)
</script>
<template>
<GridLayout>
<GridLayout :isUserInteractionEnabled="!showSplash" :accessibilityHidden="showSplash">
<RouterView />
</GridLayout>
<Splash v-if="showSplash" @done="showSplash = false" />
</GridLayout>
</template>Os dois filhos ocupam a mesma célula do GridLayout. O splash vem por último, acima do router. O layout que envolve a página impede interação por toque e navegação pelo leitor de tela no conteúdo coberto até a remoção do splash.
Só a camada sobreposta tem v-if. Não coloque <RouterView> atrás de v-if="!showSplash": isso adiaria a criação da página até o splash desaparecer. Também não espere router.isReady() antes de createApp(App).use(router).start(): o router precisa que sua view monte primeiro.
Revele a página
Este componente espera a navegação inicial, faz o fade da camada e emite done. Ele permanece visível com uma mensagem de erro se a inicialização lançar uma exceção ou o guard inicial deixar o app sem destino:
<script setup lang="ts">
import type { EventData, View } from '@nativescript/core'
import { onBeforeUnmount, ref } from 'nativescript-vue'
import { useRouter } from 'vue-router-ns'
const props = withDefaults(defineProps<{ fade?: boolean }>(), { fade: true })
const emit = defineEmits<{ done: [] }>()
const router = useRouter()
const failed = ref(false)
let started = false
let active = true
onBeforeUnmount(() => {
active = false
})
async function reveal({ object }: EventData) {
if (started) return
started = true
try {
await router.isReady()
if (!active) return
// A guard can cancel initial navigation without throwing an error.
if (!router.currentRoute.value.matched.length) {
failed.value = true
return
}
} catch (error) {
if (active) failed.value = true
console.error('Initial navigation failed', error)
return
}
try {
if (props.fade) await (object as View).animate({ opacity: 0, duration: 250 })
} catch {
// A cancelled animation must not leave a ready app behind the splash.
}
if (active) emit('done')
}
</script>
<template>
<GridLayout backgroundColor="#0f172a" iosOverflowSafeArea="true" @loaded="reveal">
<StackLayout verticalAlignment="middle" padding="32">
<Label text="My app" color="white" fontSize="32" textAlignment="center" />
<Label
v-if="failed"
text="Unable to open the first page. Please restart the app."
color="white"
textAlignment="center"
textWrap="true"
/>
</StackLayout>
</GridLayout>
</template>O fade é uma animação do aplicativo. Passe :fade="false" quando a preferência de movimento reduzido do app estiver ativa; a política de movimento do router controla transições de rotas, não essa animação personalizada.
isReady() espera a navegação inicial, não todas as abas ocultas nem as requisições de rede da própria página. Inclua qualquer inicialização obrigatória do app na condição de prontidão. Para onboarding, emita done quando a pessoa concluir as etapas; mantenha <RouterView> montado durante todo o processo.
Combine com a tela de abertura do iOS
Defina iosOverflowSafeArea="true" no layout raiz da camada para que o fundo se estenda além da área segura. Use o mesmo fundo, imagem, tamanho e posicionamento de App_Resources/iOS/LaunchScreen.storyboard para evitar um salto visual quando o iOS entregar o controle ao app. Confira o alinhamento nos tamanhos de iPhone e iPad suportados.
Essa camada aparece depois que o NativeScript inicia. Ela complementa a tela de abertura do sistema operacional; não substitui a tela exibida antes de o JavaScript executar. iosOverflowSafeArea é específico do iOS.
Os guards continuam rodando por baixo
A navegação inicial, os redirects e os guards executam normalmente enquanto o splash está visível. Ele oculta a página visualmente; não adia a autenticação nem ignora os guards. Redirecione uma visita inicial sem autenticação para uma página de login utilizável. O splash não é uma barreira de controle de acesso.
Não é preciso mudar a API do router, criar outra rota nem chamar push() ou replace() para remover a camada. Voltar percorre o histórico real do app e não traz o splash de volta.