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; } }, }, });
问题分析与解决
报错原因
- Firebase User对象的email属性只读:Firebase Auth返回的
User实例中,email是只读属性,不能直接赋值修改,必须通过Firebase官方提供的updateEmail()方法完成更新。 - 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
相关产品推荐
相关产品推荐

