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

Ionic Vue3 Firebase更新邮箱报错:无法赋值只读属性'email'

问题描述

首次使用Vue3、Ionic和Firebase开发应用,已完成认证功能,现在尝试实现更新邮箱功能时遇到错误:Cannot assign to 'email' because it is a read-only property.。通过console.log检查数据显示正常,但不清楚报错原因。

以下是相关代码:

组件代码

<form class="login-form" autocomplete="off">
          <ion-item lines="full">
            <ion-label position="floating">New Email</ion-label>
            <ion-input v-model="updatedEmail" type="email"></ion-input>
          </ion-item>
          <ion-button expand="block" @click="doUpdateEmail">Update email</ion-button>
        </form>

组件脚本

<script>
import router from "@/router";
import { useAuthStore } from "@/store";

import {
  IonGrid,
  IonRow,
  IonCol,
  IonLabel,
  IonInput,
  IonItem,
  IonContent,
  IonHeader,
  IonTitle,
  IonToolbar,
  IonButton,
  IonPage, toastController
} from '@ionic/vue';
import { defineComponent, ref } from "vue";

export default defineComponent({
  components: {
    IonHeader,
    IonToolbar,
    IonTitle,
    IonContent,
    IonPage,
    IonGrid,
    IonRow,
    IonCol,
    IonLabel,
    IonInput,
    IonItem,
    IonButton
  },

  setup() {
    const { logoutUser, updateEmail, user, profile } = useAuthStore();
    const updatedEmail = ref('')
    const currentEmail = user.email


    const doLogout = async () => {
      await logoutUser();
      await router.replace("/login");
    };

    const doUpdateEmail = async () => {
      await updateEmail(user.email, updatedEmail.value).then(() => {
        // toast
        console.log('succes')
      })
          .catch(() => {
            // toast
            console.log('failed')
          });
    };

    return {
      updatedEmail,
      doLogout,
      doUpdateEmail,
      user,
      profile
    };
  },
});
</script>

Pinia Store代码

import { User as fbUser } from "firebase/auth";
import { defineStore } from "pinia";
import {
  fbAuthStateListener,
  fbCreateAccount,
  fbGetUserProfile,
  fbSignIn,
  fbSignOut,
} from "./firebase";

export interface User {
  user: any;
  profile: any;
  userError: any;
}

interface State {
  user: fbUser | null;
  profile: any;
  error: null;
}


export const useAuthStore = defineStore("authStore", {
  // convert to a function
  state: (): State => ({
    user: null,
    profile: null,
    error: null,
  }),
  getters: {
    isLoggedIn: (state) => state.user !== null,
    userError: (state) => state.error,
  },
  actions: {
    initializeAuthListener() {
      return new Promise((resolve) => {
        fbAuthStateListener(async (user: any) => {
          this.user = user ? user : null;

          if (user) {
            const profile = (await fbGetUserProfile()) as any;
            this.profile = profile;
          }
          resolve(true);
        });
      });
    },

    async logInUser(email: string, password: string) {
      try {
        const response = await fbSignIn(email, password);
        this.user = response.user ? response.user : null;
        this.error = null;
        return true;
      } catch (e: any) {
        this.user = null;
        this.error = e;
        return false;
      }
    },
    async logoutUser() {
      try {
        await fbSignOut();
        this.user = null;
        this.profile = null;
        this.error = null;
        return true;
      } catch (e: any) {
        this.error = e;
        return false;
      }
    },

    async updateEmail(email:string, updatedEmail: string) {
      try {
        if(this.user) {
         return email = updatedEmail
        }


      } catch (e: any) {
        this.error = e;
        return false;
      }
    },
     async createAccount(email: string, password: string) {
        try {
          const {user, profile} = await fbCreateAccount(email, password);
          this.user = user ? user : null;
          this.profile = profile ? profile : null;
          this.error = null;
          return true;
        } catch (e: any) {
          this.user = null;
          this.error = e;
          return false;
        }
      },
  },
});

问题分析与解决

报错原因

  1. Firebase User对象的email属性只读:Firebase Auth返回的User实例中,email是只读属性,不能直接赋值修改,必须通过Firebase官方提供的updateEmail()方法完成更新。
  2. Pinia的updateEmail方法逻辑无效:当前store中的updateEmail方法只是给参数email赋值,完全没有调用Firebase的更新接口,根本没实现实际的邮箱更新逻辑。

修复步骤

1. 在Firebase工具函数中添加更新邮箱方法

在你的firebase.ts(或对应工具文件)中新增调用Firebase Auth更新邮箱的函数:

import { getAuth, updateEmail } from "firebase/auth";

export const fbUpdateEmail = async (newEmail: string) => {
  const auth = getAuth();
  const user = auth.currentUser;
  if (!user) throw new Error("用户未登录");
  
  await updateEmail(user, newEmail);
};

2. 修改Pinia Store中的updateEmail方法

更新store里的updateEmail方法,调用新增的Firebase工具函数,并同步本地store的用户状态:

// 先导入新增的fbUpdateEmail方法
import {
  fbAuthStateListener,
  fbCreateAccount,
  fbGetUserProfile,
  fbSignIn,
  fbSignOut,
  fbUpdateEmail // 新增导入
} from "./firebase";

// 修改updateEmail方法
async updateEmail(newEmail: string) {
  try {
    if (!this.user) throw new Error("用户未登录");
    
    await fbUpdateEmail(newEmail);
    // 手动更新本地store的user数据,即时刷新UI(Firebase状态变化后也会自动同步)
    this.user = { ...this.user, email: newEmail };
    return true;
  } catch (e: any) {
    this.error = e;
    return false;
  }
},

3. 调整组件脚本的调用逻辑

组件中调用updateEmail时,无需传递当前邮箱,直接传入新邮箱即可:

const doUpdateEmail = async () => {
  await updateEmail(updatedEmail.value).then(() => {
    console.log('更新成功');
    // 此处可添加成功提示toast
  }).catch((err) => {
    console.log('更新失败', err);
    // 此处可添加失败提示toast
  });
};

额外注意事项

  • 重新认证要求:如果用户最近未登录,Firebase会要求重新认证才能更新邮箱,此时需先调用reauthenticateWithCredential方法完成重新认证,再执行更新操作。
  • 精准错误处理:捕获Firebase返回的具体错误(如邮箱格式错误、用户未登录等),给用户更明确的提示信息。

内容的提问来源于stack exchange,提问作者R-b-n

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 03:37:06