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

NativeScript-Vue集成Firebase时$navigateTo报Failed to resolve Frame错误

NativeScript-Vue + Firebase 导航报错:无法找到Frame组件

问题场景

我开发了一个基于Firebase的NativeScript-Vue应用,代码如下,但运行时提示无法找到指定的Frame,尽管已经在App.vue中定义了id为main-frame的Frame组件。

应用代码

src/components/App.vue

<script setup lang="ts">
import { firebase } from '@nativescript/firebase-core';
import '@nativescript/firebase-auth';
import { $navigateTo, ActionBar, onMounted } from 'nativescript-vue';
import Login from './pages/Login.vue';
import Home from './pages/Home.vue';

onMounted(() => {
  firebase().auth().addAuthStateChangeListener(async user => {
    if (!user) {
      console.log("No user is signed in, navigating to Login");
      $navigateTo(Login, { frame: 'main-frame', clearHistory: true });
    } else {
      console.log("User is signed in, navigating to Home");
      $navigateTo(Home, { frame: 'main-frame', clearHistory: true });
    }
  })
})
</script>

<template>
  <Frame id="main-frame">
    <ActionBar title="My App" class="action-bar" />
  </Frame>
</template>

src/components/pages/Home.vue

<script setup lang="ts">
import { firebase } from '@nativescript/firebase-core';
import '@nativescript/firebase-auth';

const logout = async () => {
  try {
    await firebase().auth().signOut();
    console.log("User signed out successfully");
  } catch (error) {
    console.error("Error signing out:", error);
  }
}
</script>

<template>
  <Page>
    <StackLayout>
      <Label text="Welcome to the Home Page!" class="h1 text-center" />
      <Button @tap="logout" text="Logout" />
    </StackLayout>
  </Page>
</template>

src/components/pages/Login.vue

<script setup lang="ts">
  import { ref, computed, onMounted, onUnmounted } from 'nativescript-vue';
  import { firebase } from '@nativescript/firebase-core';
  import '@nativescript/firebase-auth';
  import { GoogleAuthProvider } from '@nativescript/firebase-auth';
  import { GoogleSignin } from '@nativescript/google-signin';

  const handleLogin = async () => {
    try {
      const googleUser = await GoogleSignin.signIn();
      const credential = GoogleAuthProvider.credential(googleUser.idToken, googleUser.accessToken);
      await firebase().auth().signInWithCredential(credential);
    } catch (error) {
      console.error('Login failed', error);
    }
  }
</script>

<template>
  <Page actionBarHidden="true">
    <StackLayout class="p-10" verticalAlignment="center" horizontalAlignment="center">
      <Label text="Welcome! Please log in." class="h1 text-center mb-10" />
      <Button @tap="handleLogin" text="Login with Google" class="btn btn-primary" />
    </StackLayout>
  </Page>
</template>

src/app.ts

import { createApp } from 'nativescript-vue';
import App from './components/App.vue';

createApp(App).start();

错误信息

[$navigateTo] Failed to navigate:
  Error: Failed to resolve frame. Make sure your frame exists.
    at $navigateTo (file: src/webpack:/moonhope-finance-ns/node_modules/nativescript-vue/dist/plugins/navigation.js:32:0)
    at file: src/webpack:/moonhope-finance-ns/src/components/App.vue:12:18
    at com.google.firebase.auth.FirebaseAuth.AuthStateListener.onAuthStateChanged (file: src/webpack:/moonhope-finance-ns/node_modules/@nativescript/firebase-auth/index.android.js:827:0)

解决方案

核心原因

  • Vue的onMounted钩子触发时,NativeScript的Frame组件可能还未完成Native层面的初始化,导致通过id查找Frame实例失败。
  • Firebase的auth状态监听可能在Frame完全就绪前就触发了导航操作。

修复方案

方案1:通过Vue Ref直接绑定Frame实例(推荐)

直接通过Vue的ref获取Frame组件实例,避免通过id查找的延迟问题:

<!-- 修改后的src/components/App.vue -->
<script setup lang="ts">
import { firebase } from '@nativescript/firebase-core';
import '@nativescript/firebase-auth';
import { $navigateTo, onMounted, ref } from 'nativescript-vue';
import Login from './pages/Login.vue';
import Home from './pages/Home.vue';

// 创建ref绑定Frame组件
const mainFrame = ref(null);

onMounted(() => {
  firebase().auth().addAuthStateChangeListener(async user => {
    if (!user) {
      console.log("No user is signed in, navigating to Login");
      // 使用ref指向的Frame实例
      $navigateTo(Login, { frame: mainFrame.value, clearHistory: true });
    } else {
      console.log("User is signed in, navigating to Home");
      $navigateTo(Home, { frame: mainFrame.value, clearHistory: true });
    }
  })
})
</script>

<template>
  <!-- 添加ref属性绑定到mainFrame -->
  <Frame ref="mainFrame" id="main-frame">
    <ActionBar title="My App" class="action-bar" />
  </Frame>
</template>

方案2:监听Frame的Loaded事件

等Frame完全加载完成后再注册auth状态监听,确保导航时Frame已就绪:

<!-- 修改后的src/components/App.vue -->
<script setup lang="ts">
import { firebase } from '@nativescript/firebase-core';
import '@nativescript/firebase-auth';
import { $navigateTo, ref } from 'nativescript-vue';
import Login from './pages/Login.vue';
import Home from './pages/Home.vue';

const mainFrame = ref(null);
let authStateListener = null;

// Frame加载完成后注册auth监听
const onFrameLoaded = () => {
  authStateListener = firebase().auth().addAuthStateChangeListener(async user => {
    if (!user) {
      console.log("No user is signed in, navigating to Login");
      $navigateTo(Login, { frame: mainFrame.value, clearHistory: true });
    } else {
      console.log("User is signed in, navigating to Home");
      $navigateTo(Home, { frame: mainFrame.value, clearHistory: true });
    }
  });
};

// 组件卸载时移除监听,防止内存泄漏
const onFrameUnloaded = () => {
  if (authStateListener) {
    authStateListener();
  }
};
</script>

<template>
  <Frame 
    ref="mainFrame" 
    id="main-frame"
    @loaded="onFrameLoaded"
    @unloaded="onFrameUnloaded"
  >
    <ActionBar title="My App" class="action-bar" />
  </Frame>
</template>

方案3:延迟执行导航逻辑

通过setTimeout给Frame预留初始化时间,适合快速测试:

<!-- 修改后的src/components/App.vue -->
<script setup lang="ts">
import { firebase } from '@nativescript/firebase-core';
import '@nativescript/firebase-auth';
import { $navigateTo, onMounted } from 'nativescript-vue';
import Login from './pages/Login.vue';
import Home from './pages/Home.vue';

onMounted(() => {
  // 延迟500ms执行,确保Frame初始化完成
  setTimeout(() => {
    firebase().auth().addAuthStateChangeListener(async user => {
      if (!user) {
        console.log("No user is signed in, navigating to Login");
        $navigateTo(Login, { frame: 'main-frame', clearHistory: true });
      } else {
        console.log("User is signed in, navigating to Home");
        $navigateTo(Home, { frame: 'main-frame', clearHistory: true });
      }
    });
  }, 500);
})
</script>

<template>
  <Frame id="main-frame">
    <ActionBar title="My App" class="action-bar" />
  </Frame>
</template>

内容的提问来源于stack exchange,提问作者starleaf1

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 07:44:55