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

Quasar框架中MainLayout.vue登录按钮动态更新问题求助

问题

使用Quasar Framework开发时,完成登录操作后,MainLayout.vue布局组件中的登录/退出q-btn按钮无法实时切换状态,仅在页面刷新后才会更新。目前已通过boot文件使用provide/inject传递登录状态,但未实现实时更新效果,求解决方法。


相关代码

MainLayout.vue

<template>
  <q-layout view="lHh Lpr lFf">
    <q-header elevated>
      <q-toolbar>
         <q-toolbar-title>
          <q-btn flat @click="$router.push('/')">
            Homepage
          </q-btn>
        </q-toolbar-title>
        <q-space />
        <q-btn v-if="!userLoggedIn" icon="login" @click="router.push('/login')" />
        <q-btn v-if="userLoggedIn" icon="logout" @click="logout" />
      </q-toolbar>
    </q-header>
    <q-page-container>
      <router-view />
    </q-page-container>
  </q-layout>
</template>

<script setup>
import { inject, ref } from "vue";

const userId = inject("userId", false);
const userLoggedIn = ref(userId);
</script>

Login.vue(登录核心代码)

import { inject, ref } from "vue";

const updateUserId = inject("updateLoginStatus");

const email = ref();
const password = ref();

const signInExistingUser = () => {
  signInWithEmailAndPassword(auth, email.value, password.value)
    .then(() => {
      updateUserId(auth.currentUser.uid);
      router.push("/");
    })
    .catch((error) => {
      $q.notify({
         // 错误处理逻辑
      });
    });
};

boot.js

export default boot(async ({ app, router }) => {
  const user = await getCurrentUser();
  let userLoggedIn = ref(false);
  const uid = ref(false);
  if (user) {
    userLoggedIn.value = true;
    uid.value = user.uid;
  }

  const updateLoginStatus = (updatedUserId) => {
    uid.value = updatedUserId;
    userLoggedIn.value = !userLoggedIn.value;
    console.log(userLoggedIn.value);
    return userLoggedIn.value;
  };

  app.provide("updateLoginStatus", updateLoginStatus);
  app.provide("userId", uid.value);
});

解决方案

问题根源

  1. boot.js中provide("userId", uid.value)传递的是ref的原始值,而非响应式ref对象,导致MainLayout无法感知状态变化。
  2. MainLayout中userLoggedIn是基于静态值创建的独立ref,不会跟随原始状态更新。

修改步骤

1. 调整boot.js,传递响应式ref对象

直接将userLoggedIn和uid这两个响应式ref提供给子组件,同时修正登录状态更新逻辑:

export default boot(async ({ app, router }) => {
  const user = await getCurrentUser();
  const userLoggedIn = ref(false);
  const uid = ref(false);
  if (user) {
    userLoggedIn.value = true;
    uid.value = user.uid;
  }

  const updateLoginStatus = (updatedUserId) => {
    uid.value = updatedUserId;
    userLoggedIn.value = true; // 登录成功直接设为true,无需取反
    console.log(userLoggedIn.value);
  };

  // 提供响应式ref对象,而非原始值
  app.provide("userLoggedIn", userLoggedIn);
  app.provide("uid", uid);
  app.provide("updateLoginStatus", updateLoginStatus);
});

2. 优化MainLayout.vue,直接使用响应式状态

无需自行创建userLoggedIn,直接注入boot提供的响应式ref,状态变化时自动更新视图:

<template>
  <q-layout view="lHh Lpr lFf">
    <q-header elevated>
      <q-toolbar>
         <q-toolbar-title>
          <q-btn flat @click="$router.push('/')">
            Homepage
          </q-btn>
        </q-toolbar-title>
        <q-space />
        <q-btn v-if="!userLoggedIn.value" icon="login" @click="router.push('/login')" />
        <q-btn v-if="userLoggedIn.value" icon="logout" @click="logout" />
      </q-toolbar>
    </q-header>
    <q-page-container>
      <router-view />
    </q-page-container>
  </q-layout>
</template>

<script setup>
import { inject } from "vue";
import { useRouter } from "vue-router";
import { signOut, auth } from "firebase/auth"; // 根据实际身份验证工具调整

const router = useRouter();
const userLoggedIn = inject("userLoggedIn");
const uid = inject("uid");

const logout = () => {
  signOut(auth)
    .then(() => {
      userLoggedIn.value = false;
      uid.value = false;
      router.push('/login');
    })
    .catch(error => {
      $q.notify({
        // 错误处理逻辑
      });
    });
};
</script>

3. Login.vue保持现有逻辑

调用updateLoginStatus会直接修改响应式ref的值,MainLayout中的视图会自动触发更新:

import { inject, ref } from "vue";
import { useRouter } from "vue-router";
import { signInWithEmailAndPassword, auth } from "firebase/auth"; // 按需导入

const router = useRouter();
const updateUserId = inject("updateLoginStatus");

const email = ref();
const password = ref();

const signInExistingUser = () => {
  signInWithEmailAndPassword(auth, email.value, password.value)
    .then(() => {
      updateUserId(auth.currentUser.uid);
      router.push("/");
    })
    .catch((error) => {
      $q.notify({
         // 错误处理逻辑
      });
    });
};

核心说明

  • 必须传递响应式ref对象而非原始值,才能实现跨组件的状态实时同步。
  • 登录/退出操作直接修改ref的value属性,MainLayout中的v-if会自动感知状态变化,切换按钮显示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 13:40:34