Vue.js+Pinia+Supabase:当前登录用户信息获取及用户名存储问题
Pinia + Supabase 用户名存储与获取问题
我的代码
Pinia状态管理文件 auth.js
//auth.js (pinia store) import { defineStore } from 'pinia' import supabase from '../supabase' import {ref, watch} from 'vue' export const useAuthStore = defineStore('user', () =>{ const user = ref(null) const error = ref(null) const fetchUser = async () => { user.value = await supabase.auth.user(); } const signUp = async (email, password, username) => { const { error } = await supabase.auth.signUp({ email, password, }, { data: { username: username} }) if (error) { error.value = error.message; } } const signIn = async (email, password) => { const { data, error } = await supabase.auth.signInWithPassword({ email, password, }) if (error) { error.value = error.message; } else { user.value = data; } } const signOut = async () => { await supabase.auth.signOut(); user.value = null; } })
遇到的问题
- 不确定注册时的用户名是否成功上传到Supabase,获取用户信息时得到异常对象;
- 希望在注册表单添加用户名输入项,将信息存入Supabase,并能从Pinia Store中获取该信息。
尝试的getUsername函数
const getUsername = async () => { if (!user.value) { // 用户未登录则返回null return null; } const { data, error } = await supabase .from("users") .select("username") .eq("email", user.value.email) .single(); if (error) { // 获取失败返回null return null; } else { // 返回用户名 return data.username; } }
组件渲染代码
<template> <main> <h1 v-if="!authStore.user">Welcome to My App!</h1> <p v-if="!authStore.user">Please, sign in or sign up to continue.</p> <h1 v-if="authStore.user">Greetings! {{ username }}</h1> </main> </template> <script setup> import {useAuthStore} from '../stores/auth' const authStore = useAuthStore(); const username = authStore.fetchUser; // 这里是测试代码 </script>
解决方案
1. 修正用户信息获取逻辑
Supabase的auth.user()已被弃用,改用auth.getUser(),同时登录成功后要正确获取用户对象而非整个返回数据:
修改auth.js中的fetchUser和signIn函数:
const fetchUser = async () => { // 使用新的getUser方法获取用户 const { data: { user } } = await supabase.auth.getUser(); user.value = user; } const signIn = async (email, password) => { const { data, error } = await supabase.auth.signInWithPassword({ email, password, }) if (error) { error.value = error.message; } else { // 取data.user而非整个data user.value = data.user; } }
2. 直接从用户元数据获取用户名
注册时传入的username会自动存在用户的user_metadata字段中,无需额外查询数据库,可直接从Pinia的user对象中读取:
方式一:在Store中添加获取用户名的方法
在auth.js中添加:
// 同步获取用户名,无需异步请求 const getUsername = () => { return user.value?.user_metadata?.username || null; }
方式二:在组件中直接计算
修改组件代码:
<template> <main> <h1 v-if="!authStore.user">欢迎来到我的应用!</h1> <p v-if="!authStore.user">请登录或注册以继续。</p> <h1 v-if="authStore.user">你好!{{ username }}</h1> </main> </template> <script setup> import { useAuthStore } from '../stores/auth' import { onMounted, computed } from 'vue' const authStore = useAuthStore(); // 页面挂载时初始化用户信息 onMounted(async () => { await authStore.fetchUser(); }) // 用计算属性实时获取用户名 const username = computed(() => { return authStore.user?.user_metadata?.username || '未知用户'; }) </script>
3. 验证用户名是否存储成功
登录Supabase控制台,进入Auth -> Users,查看对应用户的user_metadata字段,即可确认username是否存在。
4. 如需单独存储到users表(可选)
如果需要将用户信息存入自定义的users表,需先在Supabase创建该表(包含id、email、username字段),然后修改注册函数:
const signUp = async (email, password, username) => { const { data, error } = await supabase.auth.signUp({ email, password, }, { data: { username: username} }) if (error) { error.value = error.message; return; } // 注册成功后插入数据到users表 if (data.user) { await supabase.from('users').insert({ id: data.user.id, email: data.user.email, username: username }) } }
此时你之前写的getUsername异步函数即可正常使用,但注意要将其加入到Pinia Store的返回对象中,才能在组件中调用。
内容的提问来源于stack exchange,提问作者Gimhel
相关产品推荐
相关产品推荐

