返回 导航

其他

hangge.com

Vue3 - Supabase的集成与使用详解1(安装配置、查询数据库数据)

作者:hangge | 2024-02-23 09:11
    Supabase 是一个开源的后端即服务(Backend-as-a-ServiceBaaS)平台,提供了数据库、认证和实时推送等功能。通过 VueSupabase 的结合,我们可以构建出现代化的、具备实时数据能力的 Web 应用。本文将详细介绍如何在 Vue 3 项目中集成 Supabase,并进行表数据的查询。

一、安装配置

1,Supabase 准备工作

(1)Supabase 支持私有化部署,我们可以通过容器技术部署一个私有的 Supabase 服务来使用,具体可以参考我之前写的文章:

(2)当然我们也可以直接使用 Supabase 官方提供的在线服务,支持免费和付费使用方式。免费使用有一些限制的,但对于学习测试,或者简单的应用也是足够的。

(3)假设我们使用 Supabase 官方在线服务,登录 Supabase 控制台,创建一个新项目,然后在项目设置中找到 API 的地址和 API 密钥。这两个后面在 Vue 项目中需要用到。

(4)接着我们创建一张 book 书籍表:

(5)然后在该表中添加一些测试数据:

2,Vue 准备工作

(1)首先我们执行如下命令创建一个 Vue3 项目:
npm init vue@latest my-app

(2)接着进入项目文件夹,并安装 Supabase 客户端库:
cd my-app
npm install @supabase/supabase-js

(3)在项目中创建一个 /src/lib 目录,创建一个名为 supabaseClient.js 的文件:

(4)supabaseClient.js 文件内容如下,使用 Supabase 上对应项目 URL 和公共 APIanon)密钥初始化 Supabase 客户端:
import { createClient } from '@supabase/supabase-js'

export const supabase = createClient('https://hucdsynwgldpummggxva.supabase.co', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Imh1Y2RzeW53Z2xkcHVtbWdneHZhIiwicm9sZSI6ImFub24iLCJpYXQiOjE3MDIxMjkwMDEsImV4cCI6MjAxNzcwNTAwMX0.ndfQkMSYvjtfvdK9lPza23tam6Pn4QKEaOpEEMKGMf0')

二、表数据的查询

1,基本查询

(1)将 App.vue 文件代码修改成如下,查询所有 book 表中的数据并展示到页面中:
<script setup>
// 引入Vue 3的响应式引用(ref)和生命周期钩子(onMounted)
import { ref, onMounted } from 'vue'

// 引入Supabase客户端实例
import { supabase } from './lib/supabaseClient'

// 创建一个响应式的引用(ref)用于存储书籍数据
const books = ref([])

// 定义异步函数,用于从Supabase查询书籍数据并更新books引用
async function getBooks() {
  // 使用Supabase实例的select方法从'book'表中获取所有数据
  const { data } = await supabase.from('book').select()

  // 将查询结果更新到books引用中
  books.value = data
}

// 在组件被挂载后(mounted)执行getBooks函数,获取并更新书籍数据
onMounted(() => {
  getBooks()
})
</script>

<template>
  <!-- 展示书籍数据的无序列表 -->
  <ul>
    <li v-for="book in books" :key="book.id">
      {{ book.name }} (编号:{{ book.id }},价格:{{ book.price }})
    </li>
  </ul>
</template>

(2)运行结果如下:

2,带分页的查询

(1)查询时使用 range 方法可以构建对数值列进行范围查询的条件,该方法传入查询范围的起始值和结束值:
const { data } = await supabase.from('book').select().range(0,1)

(2)上面代码运行后只查询出 book 表的前两条数据:

3,带过滤条件的查询

(1)下面代码使用 Supabase 实例的 select 方法从 'book' 表中获取价格大于 30 的数据:
const { data } = await supabase.from('book').select().gt('price', 30)

(2)下面是一些常用的过滤器:
注意:详细的过滤器使用详解可以参考 Supabase 的官方文档(点击查看
await supabase
  .from('book')
  .select("*") // 选择所有列(通配符)
  // Filters(过滤器)
  .eq('column', 'Equal to')  // 等于(Equal to)
  .gt('column', 'Greater than')  // 大于(Greater than)
  .lt('column', 'Less than')  // 小于(Less than)
  .gte('column', 'Greater than or equal to')  // 大于等于(Greater than or equal to)
  .lte('column', 'Less than or equal to')  // 小于等于(Less than or equal to)
  .like('column', '%CaseSensitive%')  // 类似(Like),区分大小写
  .ilike('column', '%CaseInsensitive%')  // 类似(iLike),不区分大小写
  .is('column', null)  // 是空值(Is null)
  .in('column', ['Array', 'Values'])  // 在指定值数组中(In)
  .neq('column', 'Not equal to')  // 不等于(Not equal to)
  // Arrays(数组)
  .cs('array_column', ['array', 'contains'])  // 包含数组(array contains)
  .cd('array_column', ['contained', 'by']);  // 被数组包含(contained by)

4,一对多关联查询

(1)这里假设我们再增加一个出版社 publisher 表,出版社与书籍为一对多关系。这次我们直接使用 SQL 语句创建表:
注意book 上的外键是必须的,否则将无法关联查询。
drop table if exists book;
drop table if exists publisher;

create table publisher (
  "id" bigint generated by default as identity primary key,
  "name" character varying
);

create table book (
  "id" bigint generated by default as identity primary key,
  "name" character varying,
  "price" numeric,
  "publisher_id" int references publisher
);

INSERT INTO publisher ("id", "name") VALUES
  (1, '百花文艺出版社'),
  (2, '人民文学出版社');

INSERT INTO book ("name", "price", "publisher_id") VALUES
  ('我与地坛', 29.00, 1),
  ('失败者的春秋', 38.00, 2),
  ('南北战争三百年', 35.00, 1);

(2)Vue 代码修改如下,查询 book 表数据时增加了关联 publisher 表,并将结果打印出来:
<script setup>
// 引入Vue 3的响应式引用(ref)和生命周期钩子(onMounted)
import { ref, onMounted } from 'vue'

// 引入Supabase客户端实例
import { supabase } from './lib/supabaseClient'

// 创建一个响应式的引用(ref)用于存储书籍数据
const books = ref([])

// 定义异步函数,用于从Supabase查询书籍数据并更新books引用
async function getBooks() {
  // 使用Supabase实例的select方法从'book'表中获取价格大于30的数据
  const { data } = await supabase.from('book').select(`
    id,
    name, 
    price,
    publisher ( id, name )
  `)
  console.log(data)

  // 将查询结果更新到books引用中
  books.value = data
}

// 在组件被挂载后(mounted)执行getBooks函数,获取并更新书籍数据
onMounted(() => {
  getBooks()
})
</script>

<template>
  <!-- 展示书籍数据的无序列表 -->
  <ul>
    <li v-for="book in books" :key="book.id">
      {{ book.name }} (编号:{{ book.id }},价格:{{ book.price }},出版社:{{ book.publisher.name }})
    </li>
  </ul>
</template>

(3)运行结果如下:


5,多对多关联查询

(1)这里假设我们再增加一个标签 tag 表,标签与书籍为多对多关系。我们使用如下 SQL 语句创建标签表和多对多关联的中间表:
DROP TABLE IF EXISTS tag_book_association;
DROP TABLE IF EXISTS tag;

CREATE TABLE tag (
  "id" BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
  "name" CHARACTER VARYING
);

CREATE TABLE tag_book_association (
  "tag_id" BIGINT REFERENCES tag,
  "book_id" BIGINT REFERENCES book,
  PRIMARY KEY ("tag_id", "book_id")
);

INSERT INTO tag ("id", "name") VALUES
  (1, '文学'),
  (2, '历史'),
  (3, '自传');

INSERT INTO tag_book_association ("tag_id", "book_id") VALUES
  (1, 1),
  (3, 1),
  (2, 2),
  (3, 2),
  (2, 3);

(2)Vue 代码修改如下,查询 book 表数据是增加了关联 tag 表,并将结果打印出来:
<script setup>
// 引入Vue 3的响应式引用(ref)和生命周期钩子(onMounted)
import { ref, onMounted } from 'vue'

// 引入Supabase客户端实例
import { supabase } from './lib/supabaseClient'

// 创建一个响应式的引用(ref)用于存储书籍数据
const books = ref([])

// 定义异步函数,用于从Supabase查询书籍数据并更新books引用
async function getBooks() {
  // 使用Supabase实例的select方法从'book'表中获取价格大于30的数据
  const { data } = await supabase.from('book').select(`
    id,
    name, 
    price,
    publisher ( id, name ),
    tag ( id, name )
  `)
  console.log(data)

  // 将查询结果更新到books引用中
  books.value = data
}

// 在组件被挂载后(mounted)执行getBooks函数,获取并更新书籍数据
onMounted(() => {
  getBooks()
})
</script>

<template>
  <!-- 展示书籍数据的无序列表 -->
  <ul>
    <li v-for="book in books" :key="book.id">
      {{ book.name }} (编号:{{ book.id }},价格:{{ book.price }},出版社:{{ book.publisher.name }})
      <ul>
        <li v-for="tag in book.tag" :key="tag.id">{{ tag.name }}</li>
      </ul>
    </li>
  </ul>
</template>

(3)运行结果如下:

评论

全部评论(0)

回到顶部