更新记录
1.0.0(2025-05-30) 下载此版本
完成基本功能
平台兼容性
uni-app(4.01)
Vue2 | Vue3 | Chrome | Safari | app-vue | app-nvue | Android | iOS | 鸿蒙 |
---|---|---|---|---|---|---|---|---|
√ | √ | √ | √ | √ | √ | √ | √ | - |
微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 快应用-华为 | 快应用-联盟 |
---|---|---|---|---|---|---|---|---|---|---|
√ | - | - | - | - | - | - | - | - | - | - |
anfun-supabase
Supabase UniApp 版本 - 为 uni-app 开发者提供的 Supabase JavaScript 客户端
📖 插件介绍
anfun-supabase
是 Supabase 官方 JavaScript 客户端的 uni-app 适配版本,专为 uni-app 开发者打造。Supabase 是一个开源的 Firebase 替代方案,提供实时数据库、身份验证、即时 API、边缘函数、文件存储等功能。
本插件让您可以在 uni-app 项目中轻松使用 Supabase 的所有功能,支持多端开发(H5、小程序、App)。
✨ 主要特性
- 🔐 身份验证 - 完整的用户认证系统,支持邮箱、手机号、第三方登录
- 📊 实时数据库 - PostgreSQL 数据库,支持实时订阅数据变化(未测试)
- 🗄️ 文件存储 - 安全的文件上传和管理
- ⚡ 边缘函数 - 服务端逻辑执行
- 🔄 实时通信 - WebSocket 实时数据同步(未测试)
- 📱 多端支持 - 支持 H5、微信小程序、App 等多个平台
📦 安装使用
1. 基础配置
在项目中创建 Supabase 客户端:
import { createClient } from "@/uni_modules/anfun-supabase";
const supabaseUrl = "https://your-project.supabase.co";
const supabaseKey = "your-anon-key";
export const supabase = createClient(supabaseUrl, supabaseKey);
📚 使用示例
用户认证
// 用户注册
async function signUp() {
const { data, error } = await supabase.auth.signUp({
email: "user@example.com",
password: "password123",
});
if (error) {
console.error("注册失败:", error.message);
} else {
console.log("注册成功:", data.user);
}
}
// 用户登录
async function signIn() {
const { data, error } = await supabase.auth.signInWithPassword({
email: "user@example.com",
password: "password123",
});
if (error) {
console.error("登录失败:", error.message);
} else {
console.log("登录成功:", data.user);
}
}
// 获取当前用户
async function getCurrentUser() {
const {
data: { user },
} = await supabase.auth.getUser();
return user;
}
// 退出登录
async function signOut() {
const { error } = await supabase.auth.signOut();
if (error) {
console.error("退出失败:", error.message);
}
}
数据库操作
// 查询数据
async function fetchTodos() {
const { data, error } = await supabase
.from("todos")
.select("*")
.order("created_at", { ascending: false });
if (error) {
console.error("查询失败:", error.message);
} else {
return data;
}
}
// 插入数据
async function addTodo(title) {
const { data, error } = await supabase
.from("todos")
.insert([{ title: title, completed: false }])
.select();
if (error) {
console.error("添加失败:", error.message);
} else {
console.log("添加成功:", data);
}
}
// 更新数据
async function updateTodo(id, updates) {
const { data, error } = await supabase
.from("todos")
.update(updates)
.eq("id", id)
.select();
if (error) {
console.error("更新失败:", error.message);
} else {
console.log("更新成功:", data);
}
}
// 删除数据
async function deleteTodo(id) {
const { error } = await supabase.from("todos").delete().eq("id", id);
if (error) {
console.error("删除失败:", error.message);
}
}
实时订阅
// 订阅数据变化
function subscribeToTodos() {
const subscription = supabase
.channel("todos")
.on(
"postgres_changes",
{ event: "*", schema: "public", table: "todos" },
(payload) => {
console.log("数据变化:", payload);
// 处理数据变化
handleDataChange(payload);
}
)
.subscribe();
return subscription;
}
// 取消订阅
function unsubscribe(subscription) {
supabase.removeChannel(subscription);
}
文件存储
// 上传文件
async function uploadFile(file, fileName) {
const { data, error } = await supabase.storage
.from("avatars")
.upload(fileName, file);
if (error) {
console.error("上传失败:", error.message);
} else {
console.log("上传成功:", data);
}
}
// 获取文件 URL
function getFileUrl(fileName) {
const { data } = supabase.storage.from("avatars").getPublicUrl(fileName);
return data.publicUrl;
}
// 下载文件
async function downloadFile(fileName) {
const { data, error } = await supabase.storage
.from("avatars")
.download(fileName);
if (error) {
console.error("下载失败:", error.message);
} else {
return data;
}
}
边缘函数调用
// 调用边缘函数
async function invokeFunction(functionName, params) {
const { data, error } = await supabase.functions.invoke(functionName, {
body: params,
});
if (error) {
console.error("函数调用失败:", error.message);
} else {
return data;
}
}
🔧 完整示例
以下是一个完整的 Todo 应用示例:
<template>
<view class="container">
<view class="header">
<input v-model="newTodo" placeholder="添加新任务" @confirm="addTodo" />
<button @click="addTodo">添加</button>
</view>
<view class="todo-list">
<view
v-for="todo in todos"
:key="todo.id"
class="todo-item"
:class="{ completed: todo.completed }"
>
<text @click="toggleTodo(todo)">{{ todo.title }}</text>
<button @click="deleteTodo(todo.id)">删除</button>
</view>
</view>
</view>
</template>
<script>
import { createClient } from "@/uni_modules/anfun-supabase";
const supabaseUrl = "https://your-project.supabase.co";
const supabaseKey = "your-anon-key";
export const supabase = createClient(supabaseUrl, supabaseKey);
export default {
data() {
return {
todos: [],
newTodo: "",
subscription: null,
};
},
async onLoad() {
await this.fetchTodos();
this.subscribeToChanges();
},
onUnload() {
if (this.subscription) {
supabase.removeChannel(this.subscription);
}
},
methods: {
async fetchTodos() {
const { data, error } = await supabase
.from("todos")
.select("*")
.order("created_at", { ascending: false });
if (error) {
uni.showToast({ title: "加载失败", icon: "error" });
} else {
this.todos = data;
}
},
async addTodo() {
if (!this.newTodo.trim()) return;
const { error } = await supabase
.from("todos")
.insert([{ title: this.newTodo, completed: false }]);
if (error) {
uni.showToast({ title: "添加失败", icon: "error" });
} else {
this.newTodo = "";
}
},
async toggleTodo(todo) {
const { error } = await supabase
.from("todos")
.update({ completed: !todo.completed })
.eq("id", todo.id);
if (error) {
uni.showToast({ title: "更新失败", icon: "error" });
}
},
async deleteTodo(id) {
const { error } = await supabase.from("todos").delete().eq("id", id);
if (error) {
uni.showToast({ title: "删除失败", icon: "error" });
}
},
subscribeToChanges() {
this.subscription = supabase
.channel("todos")
.on(
"postgres_changes",
{ event: "*", schema: "public", table: "todos" },
() => {
this.fetchTodos();
}
)
.subscribe();
},
},
};
</script>
<style>
.container {
padding: 20px;
}
.header {
display: flex;
margin-bottom: 20px;
}
.todo-item {
display: flex;
justify-content: space-between;
padding: 10px;
border-bottom: 1px solid #eee;
}
.completed {
opacity: 0.6;
text-decoration: line-through;
}
</style>
📋 注意事项
- 环境配置:确保在 Supabase 控制台中正确配置了数据库表和 RLS 策略
- 密钥安全:不要在客户端代码中暴露
service_role
密钥,只使用anon
密钥 - 网络请求:在小程序中使用时,需要在小程序后台配置 Supabase 域名为合法域名
- 实时功能:实时订阅功能在某些小程序平台可能受限(未测试)
让 uni-app 开发更简单,让 Supabase 更好用! 🚀