Nuxt ist ein JavaScript-Framework, das die bestehende Funktionalität von Vue.js um Features wie serverseitiges Rendering, statische Seitengenerierung, dateibasierte Routen und automatische Code-Aufteilung erweitert.
Ich habe es genossen, Frameworks wie Nuxt und Next zu verwenden, da sie nicht nur mehr Funktionen, sondern auch eine bessere Leistung und eine bessere Entwicklererfahrung bieten als die zugrundeliegenden Bibliotheken allein, ohne viele neue Konzepte lernen zu müssen. Aus diesem Grund greifen viele Entwickler bei der Erstellung neuer Projekte standardmäßig auf diese Frameworks zurück, im Gegensatz zu ihren Single-Page-Application (SPA)-Vorgängern, die ursprünglich den Weg für ihren Erfolg ebneten.
Im Geiste dieser Abstraktionen bin ich auch ein großer Fan von serverlosen/verwalteten Diensten, die viel von der Schwerstarbeit beim Aufbau von Backend-Funktionen und -Funktionalitäten für Dinge wie Authentifizierung, Dateispeicher, Daten, Compute und eine API-Schicht übernehmen. Dienste und Tools wie Supabase, Firebase, Netlify, AWS Amplify und Hasura ermöglichen es traditionell Frontend-Entwicklern, ihre persönlichen Fähigkeiten und Kenntnisse zu erweitern, um diese verschiedenen wichtigen Teile der Backend-Funktionalität hinzuzufügen, ohne selbst Backend-Entwickler werden zu müssen.
In diesem Tutorial bauen wir eine Multi-User-App von Grund auf mit Nuxt und Supabase und verwenden Tailwind CSS für das Styling.
Warum ich Supabase mag
Supabase ist eine Open-Source-Alternative zu Firebase, mit der Sie in wenigen Minuten ein Echtzeit-Backend erstellen können. Zum Zeitpunkt des Schreibens unterstützt Supabase Funktionen wie Dateispeicher, Echtzeit-API + Postgres-Datenbank, Authentifizierung und bald serverlose Funktionen.

Postgres
Einer der Gründe, warum ich Supabase mag, ist die einfache Einrichtung. Außerdem bietet es Postgres als Datenebene.
Ich baue seit 10 Jahren Apps. Eine der größten Einschränkungen, auf die ich bei NoSQL Backend-as-a-Service (BaaS)-Angeboten gestoßen bin, ist, wie schwierig es für Entwickler ist, ihre Apps zu skalieren und erfolgreich zu sein. Mit NoSQL ist es viel schwieriger, Daten zu modellieren, Migrationen durchzuführen und Datenzugriffsmuster zu ändern, nachdem Sie mit dem Aufbau Ihrer App begonnen haben. Funktionen wie Beziehungen zu ermöglichen, ist in der NoSQL-Welt ebenfalls viel schwieriger zu verstehen.
Supabase nutzt Postgres, um eine extrem reichhaltige Palette leistungsfähiger Abfragefähigkeiten direkt nutzbar zu machen, ohne zusätzlichen Backend-Code schreiben zu müssen. Echtzeit ist ebenfalls standardmäßig integriert.
Auth
Es ist wirklich einfach, Autorisierungsregeln für bestimmte Tabellen einzurichten, was die Autorisierung und feingranulare Zugriffskontrollen ohne großen Aufwand ermöglicht.
Wenn Sie ein Projekt erstellen, erhalten Sie von Supabase automatisch eine Postgres-SQL-Datenbank, Benutzerauthentifizierung und einen API-Endpunkt. Von dort aus können Sie problemlos zusätzliche Funktionen implementieren, wie z. B. Echtzeit-Abonnements und Dateispeicher.
Mehrere Authentifizierungsanbieter
Eine weitere Sache, die mir an Supabase gefällt, ist die Vielfalt der Authentifizierungsanbieter, die sofort einsatzbereit sind. Supabase ermöglicht all die folgenden Arten von Authentifizierungsmechanismen
- Benutzername und Passwort
- Magischer E-Mail-Link
- Apple
- Discord
- GitHub
- Azure
- GitLab
- Bitbucket
Die Zutaten der App
Die meisten Anwendungen, auch wenn sie in ihren Implementierungsdetails unterschiedliche Merkmale aufweisen, nutzen oft einen ähnlichen Satz von Funktionalitäten, die miteinander verbunden sind. Dies sind normalerweise
- Benutzerauthentifizierung
- Clientseitiges Identitätsmanagement
- Routing
- Dateispeicher
- Datenbank
- API-Schicht
- API-Autorisierung
Das Verständnis, wie man eine Full-Stack-App erstellt, die all diese Funktionen implementiert, legt den Grundstein dafür, dass Entwickler viele andere verschiedene Arten von Anwendungen erstellen können, die auf dieser oder einer ähnlichen Funktionalität basieren. Die App, die wir in diesem Tutorial erstellen, implementiert die meisten dieser Funktionen.
Nicht authentifizierte Benutzer können andere Beiträge in einer Liste anzeigen und dann die Beitragsdetails anzeigen, indem sie darauf klicken und zur einzelnen Beitragsseite navigieren. Benutzer können sich mit ihrer E-Mail-Adresse anmelden und erhalten einen magischen Link zur Anmeldung. Sobald sie angemeldet sind, können sie Links zum Erstellen und Bearbeiten ihrer eigenen Beiträge anzeigen. Wir bieten auch eine Profilansicht, in der Benutzer ihr Benutzerprofil einsehen und sich abmelden können.
Nachdem wir die App überprüft haben, fangen wir mit dem Bauen an!
Unsere Supabase-App starten
Als erstes müssen wir die Supabase-App erstellen. Gehen Sie zu Supabase.io und klicken Sie auf **Start Your Project**. Authentifizieren Sie sich und erstellen Sie ein neues Projekt unter der Organisation, die Ihnen in Ihrem Konto zugewiesen wurde.

Geben Sie dem Projekt einen **Namen** und ein **Passwort** und klicken Sie auf **Create new project**. Es dauert ungefähr zwei Minuten, bis Ihr Projekt hochgefahren ist.
Tabelle erstellen
Sobald das Projekt bereit ist, erstellen wir die Tabelle für unsere App zusammen mit allen erforderlichen Berechtigungen. Klicken Sie dazu auf den Link **SQL** im linken Menü.

Klicken Sie unter **Open queries** auf **Query-1** und fügen Sie die folgende SQL-Abfrage in den bereitgestellten Textbereich ein und klicken Sie auf **R**un.
CREATE TABLE posts (
id bigint generated by default as identity primary key,
user_id uuid references auth.users not null,
user_email text,
title text,
content text,
inserted_at timestamp with time zone default timezone('utc'::text, now()) not null
);
alter table posts enable row level security;
create policy "Individuals can create posts." on posts for
insert with check (auth.uid() = user_id);
create policy "Individuals can update their own posts." on posts for
update using (auth.uid() = user_id);
create policy "Individuals can delete their own posts." on posts for
delete using (auth.uid() = user_id);
create policy "Posts are public." on posts for
select using (true);

Dies erstellt die posts-Tabelle für die Datenbank unserer App. Es werden auch einige zeilenbasierte Berechtigungen für die Datenbank aktiviert.
- Jeder Benutzer kann eine Liste von Beiträgen oder einzelne Beiträge abfragen.
- Nur angemeldete Benutzer können einen Beitrag erstellen. Die Autorisierungsregeln besagen, dass ihre Benutzer-ID mit der Benutzer-ID übereinstimmen muss, die als Argument übergeben wird.
- Nur der Besitzer eines Beitrags kann ihn aktualisieren oder löschen.
Wenn wir nun auf den Link **Table editor** klicken, sollten wir unsere neue Tabelle mit dem richtigen Schema sehen.

Das ist alles, was wir für das Supabase-Projekt benötigen! Wir können mit unserer lokalen Entwicklungsumgebung fortfahren, um das Frontend mit Nuxt zu erstellen.
Projekteinrichtung
Beginnen wir mit dem Aufbau des Frontends. Öffnen Sie ein Terminal in einem leeren Verzeichnis und erstellen Sie die Nuxt-App
yarn create nuxt-app nuxt-supabase
Hier werden wir mit den folgenden Fragen konfrontiert
? Project name: nuxt-supabase
? Programming language: JavaScript
? Package manager: (your preference)
? UI framework: Tailwind CSS
? Nuxt.js modules: n/a
? Linting tools: n/a
? Testing framework: None
? Rendering mode: Universal (SSR / SSG)
? Deployment target: Server (Node.js hosting)
? Development tools: n/a
? What is your GitHub username? (your username)
? Version control system: Git
Nachdem das Projekt erstellt wurde, wechseln Sie in das neue Verzeichnis
cd nuxt-supabase
Konfiguration und Abhängigkeiten
Nachdem das Projekt initialisiert wurde, müssen wir einige Abhängigkeiten für Supabase sowie für Tailwind CSS installieren. Wir müssen auch das Nuxt-Projekt konfigurieren, damit es diese Tools erkennt und verwendet.
Tailwind CSS
Fangen wir mit Tailwind an. Installieren Sie die Tailwind-Abhängigkeiten mit npm oder Yarn
npm install -D tailwindcss@latest postcss@latest autoprefixer@latest @tailwindcss/typography
Führen Sie dann den folgenden Befehl aus, um eine tailwind.config.js-Datei zu erstellen
npx tailwind init
Erstellen Sie dann einen neuen Ordner namens assets/css im Projektverzeichnis und darin eine Datei namens tailwind.css. Hier ist ein Code, den wir dort einfügen können, um das zu importieren, was wir von Tailwind benötigen.
/* assets/css/tailwind.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
Fügen Sie dann das Modul @nuxtjs/tailwindcss zum Abschnitt buildModules der Datei nuxt.config.js hinzu (dies wurde möglicherweise bereits von der Tailwind CLI aktualisiert).
buildModules: [
'@nuxtjs/tailwindcss'
],
Tailwind ist nun eingerichtet und wir können die Utility-Klassen direkt in unserem HTML verwenden! 🎉
Markdown-Editor und Parser
Als nächstes installieren und konfigurieren wir einen Markdown-Editor und -Parser, der es Benutzern ermöglicht, Blogbeiträge mit Formatierung und Rich-Text-Bearbeitungsfunktionen zu schreiben. Wir verwenden marked zusammen mit der Vue SimpleMDE-Bibliothek, um dies zu ermöglichen.
npm install vue-simplemde marked
Als nächstes müssen wir eine neue Vue-Komponente definieren, um den neuen Markdown-Editor in unserem HTML zu verwenden. Erstellen Sie also einen neuen Ordner namens plugins und fügen Sie darin eine neue Datei namens simplemde.js hinzu. Hier ist der Code, den wir darin benötigen, um das zu importieren, was wir brauchen.
/* plugins/simplemde.js */
import Vue from 'vue'
import VueSimplemde from 'vue-simplemde'
import 'simplemde/dist/simplemde.min.css'
Vue.component('vue-simplemde', VueSimplemde)
Öffnen Sie als Nächstes nuxt.config.js und aktualisieren Sie die css-Globale, sodass sie das simplemde-CSS sowie das Plugins-Array enthalten.
css: [
'simplemde/dist/simplemde.min.css',
],
plugins: [
{ src: '~plugins/simplemde.js', mode: 'client' },
],
Jetzt können wir vue-simplemde direkt in unserem HTML verwenden, wann immer wir die Komponente nutzen möchten!
Supabase konfigurieren
Das Letzte, was wir konfigurieren müssen, ist der Supabase-Client. Dies ist die API, mit der wir mit dem Supabase-Backend für Authentifizierung und Datenzugriff interagieren.
Installieren Sie zuerst die Supabase JavaScript-Bibliothek
npm install @supabase/supabase-js
Erstellen wir als Nächstes ein weiteres Plugin, das eine $supabase-Variable in den Scope unserer App injiziert, damit wir jederzeit und überall darauf zugreifen können. Wir müssen den API-Endpunkt und den öffentlichen API-Schlüssel für unser Projekt abrufen, die wir im Supabase-Dashboard im Tab Einstellungen finden.

Erstellen wir nun eine neue Datei client.js im Ordner plugins mit dem folgenden Code darin.
/* plugins/client.js */
import { createClient } from '@supabase/supabase-js'
const supabase = createClient(
"https://yoururl.supabase.co",
"your-api-key"
)
export default (_, inject) => {
inject('supabase', supabase)
}
Nun können wir das Array plugins in nuxt.config.js mit dem neuen Plugin aktualisieren.
plugins: [
{ src: '~plugins/client.js' },
{ src: '~plugins/simplemde.js', mode: 'client' },
],
Das ist das Letzte, was wir tun müssen, um unser Projekt einzurichten. Jetzt können wir mit dem Schreiben von Code beginnen!
Layout erstellen
Unsere App benötigt eine gute Layout-Komponente, um die Navigation sowie einige grundlegende Stile zu enthalten, die auf allen anderen Seiten angewendet werden.
Um ein Layout zu verwenden, sucht Nuxt nach einem layouts-Verzeichnis für ein default-Layout, das auf alle Seiten angewendet wird. Wir können Layouts seitenweise überschreiben, wenn wir etwas Spezifisches anpassen müssen. Der Einfachheit halber halten wir uns in diesem Tutorial für alles an das Standardlayout.
Wir benötigen diesen layouts-Ordner, also fügen Sie ihn zum Projektverzeichnis hinzu und fügen Sie darin eine Datei default.vue mit dem folgenden Markup für das Standardlayout hinzu.
<!-- layouts/default.vue -->
<template>
<div>
<nav class="p-6 border-b border-gray-300">
<NuxtLink to="/" class="mr-6">
Home
</NuxtLink>
<NuxtLink to="/profile" class="mr-6">
Profile
</NuxtLink>
<NuxtLink to="/create-post" class="mr-6" v-if="authenticated">
Create post
</NuxtLink>
<NuxtLink to="/my-posts" class="mr-6" v-if="authenticated">
My Posts
</NuxtLink>
</nav>
<div class="py-8 px-16">
<Nuxt />
</div>
</div>
</template>
<script>
export default {
data: () => ({
authenticated: false,
authListener: null
}),
async mounted() {
/* When the app loads, check to see if the user is signed in */
/* also create a listener for when someone signs in or out */
const { data: authListener } = this.$supabase.auth.onAuthStateChange(
() => this.checkUser()
)
this.authListener = authListener
this.checkUser()
},
methods: {
async checkUser() {
const user = await this.$supabase.auth.user()
if (user) {
this.authenticated = true
} else {
this.authenticated = false
}
}
},
beforeUnmount() {
this.authListener?.unsubscribe()
}
}
</script>
Das Layout hat zwei Links, die standardmäßig angezeigt werden, und zwei weitere, die nur angezeigt werden, wenn ein Benutzer angemeldet ist.

Um den angemeldeten Benutzer jederzeit abzurufen (oder zu sehen, ob er authentifiziert ist), verwenden wir die Methode supabase.auth.user(). Wenn ein Benutzer angemeldet ist, wird sein Profil zurückgegeben. Wenn nicht, ist der Rückgabewert null.
Die Startseite
Als Nächstes aktualisieren wir die Startseite. Wenn der Benutzer die App öffnet, möchten wir eine Liste von Beiträgen anzeigen und ihm ermöglichen, darauf zu klicken und zum Lesen des Beitrags zu navigieren. Wenn keine Beiträge vorhanden sind, zeigen wir stattdessen eine Nachricht an.
In dieser Komponente machen wir unseren ersten Aufruf an das Supabase-Backend, um Daten abzurufen – in diesem Fall rufen wir ein Array ab, das alle Beiträge enthält. Sehen Sie, wie intuitiv die Supabase-API mit Ihren Daten interagiert, meiner Meinung nach.
/* example of how to fetch data from Supabase */
const { data: posts, error } = await this.$supabase
.from('posts')
.select('*')
Supabase bietet Filter und Modifier, die es einfach machen, eine reichhaltige Auswahl an verschiedenen Datenzugriffsmustern und Datenauswahlmengen zu implementieren. Wenn wir zum Beispiel die letzte Abfrage aktualisieren möchten, um nur nach Benutzern mit einer bestimmten Benutzer-ID abzufragen, könnten wir das so machen:
const { data: posts, error } = await this.$supabase
.from('posts')
.select('*')
.filter('user_id', 'eq', 'some-user-id')
Aktualisieren Sie die Vorlagendatei für die Startseite, pages/index.vue, mit dem folgenden Markup und fragen Sie die Anzeige einer Beitragsliste ab.
<!-- pages/index.vue -->
<template>
<main>
<div v-for="post in posts" :key="post.id">
<NuxtLink key={post.id} :to="`/posts/${post.id}`">
<div class="cursor-pointer border-b border-gray-300 mt-8 pb-4">
<h2 class="text-xl font-semibold">{{ post.title }}</h2>
<p class="text-gray-500 mt-2">Author: {{ post.user_email }}</p>
</div>
</NuxtLink>
</div>
<h1 v-if="loaded && !posts.length" class="text-2xl">No posts...</h1>
</main>
</template>
<script>
export default {
async created() {
const { data: posts, error } = await this.$supabase
.from('posts')
.select('*')
this.posts = posts
this.loaded = true
},
data() {
return {
loaded: false,
posts: []
}
}
}
</script>

Benutzerprofil
Erstellen wir nun die Profilseite mit einer neuen Datei profile.vue im Verzeichnis pages mit dem folgenden Code.
<!-- pages/profile.vue -->
<template>
<main class="m-auto py-20" style="width: 700px">
<!-- if the user is not signed in, show the sign in form -->
<div v-if="!profile && !submitted" class="flex flex-col">
<h2 class="text-2xl">Sign up / sign in</h2>
<input v-model="email" placeholder="Email" class="border py-2 px-4 rounded mt-4" />
<button
@click="signIn"
class="mt-4 py-4 px-20 w-full bg-blue-500 text-white font-bold"
>Submit</button>
</div>
<!-- if the user is signed in, show them their profile -->
<div v-if="profile">
<h2 class="text-xl">Hello, {{ profile.email }}</h2>
<p class="text-gray-400 my-3">User ID: {{ profile.id }}</p>
<button
@click="signOut"
class="mt-4 py-4 px-20 w-full bg-blue-500 text-white font-bold"
>Sign Out</button>
</div>
<div v-if="submitted">
<h1 class="text-xl text-center">Please check your email to sign in</h1>
</div>
</main>
</template>
<script>
export default {
data: () => ({
profile: null,
submitted: false,
email: ''
}),
methods: {
async signOut() {
/* signOut deletes the user's session */
await this.$supabase.auth.signOut()
this.profile = null
},
async signIn() {
/* signIn sends the user a magic link */
const { email } = this
if (!email) return
const { error, data } = await this.$supabase.auth.signIn({
email
})
this.submitted = true
},
},
async mounted() {
/* when the component loads, fetch the user's profile */
const profile = await this.$supabase.auth.user()
this.profile = profile
}
}
</script>
Im Template haben wir ein paar verschiedene Ansichten:
- Wenn der Benutzer nicht angemeldet ist, zeigen Sie ihm das Anmeldeformular.
- Wenn der Benutzer angemeldet ist, zeigen Sie ihm seine Profilinformationen und eine Abmeldeschaltfläche an.
- Wenn der Benutzer das Anmeldeformular abgeschickt hat, zeigen Sie ihm eine Nachricht, dass er seine E-Mail überprüfen soll.
Diese App nutzt Magic-Link-Authentifizierung wegen ihrer Einfachheit. Es gibt keinen separaten Prozess für die Registrierung und Anmeldung. Alles, was der Benutzer tun muss, ist, seine E-Mail-Adresse einzugeben, und er erhält einen Link zur Anmeldung. Sobald er auf den Link klickt, wird eine Sitzung in seinem Browser von Supabase eingerichtet und er wird zur App weitergeleitet.

Beitrag erstellen
Als Nächstes erstellen wir die Seite mit dem Formular, das es Benutzern ermöglicht, neue Beiträge zu erstellen und zu speichern. Das bedeutet eine neue Datei create-post.vue im Verzeichnis pages mit Code für den Beitragseditor.
<!-- pages/create-post.vue -->
<template>
<main>
<div id="editor">
<h1 class="text-3xl font-semibold tracking-wide mt-6">Create new post</h1>
<input
name="title"
placeholder="Title"
v-model="post.title"
class="border-b pb-2 text-lg my-4 focus:outline-none w-full font-light text-gray-500 placeholder-gray-500 y-2"
/>
<client-only>
<vue-simplemde v-model="post.content"></vue-simplemde>
</client-only>
<button
type="button"
class="mb-4 w-full bg-blue-500 text-white font-semibold px-8 py-4"
@click="createPost"
>Create Post</button>
</div>
</main>
</template>
<script>
export default {
data() {
return {
post: {}
}
},
methods: {
async createPost() {
const {title, content} = this.post
if (!title || !content) return
const user = this.$supabase.auth.user()
const { data } = await this.$supabase
.from('posts')
.insert([
{ title, content, user_id: user.id, user_email: user.email }
])
.single()
this.$router.push(`/posts/${data.id}`)
}
}
}
</script>
Dieser Code verwendet die vue-simplemde-Komponente, die wir in einem früheren Schritt als Plugin registriert haben! Sie ist in eine client-only-Komponente eingebettet, die die Komponente nur auf der Client-Seite rendert – vue-simplemde ist ein reines Client-Side-Plugin, daher ist es nicht notwendig, es auf dem Server zu haben.
Die Funktion createPost erstellt einen neuen Beitrag in der Supabase-Datenbank und leitet uns dann zur Ansicht des einzelnen Beitrags auf einer Seite, die wir noch nicht erstellt haben. Lassen Sie uns das jetzt tun!

Dynamische Routen zur Anzeige einzelner Beiträge
Um eine dynamische Route in Nuxt zu erstellen, müssen wir einen Unterstrich vor .vue im Dateinamen (oder vor dem Verzeichnisnamen) setzen.
Wenn ein Benutzer zu einer Seite navigiert, z. B. /posts/123. Wir möchten die Beitrags-ID 123 verwenden, um die Daten für den Beitrag abzurufen. In der App können wir dann auf die Routenparameter zugreifen, indem wir route.params referenzieren.
Lassen Sie uns also noch einen neuen Ordner, pages/posts, mit einer neuen Datei darin namens _id.vue hinzufügen.
<!-- pages/posts/_id.vue -->
<template>
<main>
<div>
<h1 class="text-5xl mt-4 font-semibold tracking-wide">{{ post.title }}</h1>
<p class="text-sm font-light my-4">by {{ post.user_email }}</p>
<div class="mt-8 prose" >
<div v-html="compiledMarkdown"></div>
</div>
</div>
</main>
</template>
<script>
import marked from 'marked'
export default {
computed: {
compiledMarkdown: function () {
return marked(this.post.content, { sanitize: true })
}
},
async asyncData({ route, $supabase }) {
/* use the ID from the route parameter to fetch the post */
const { data: post } = await $supabase
.from('posts')
.select()
.filter('id', 'eq', route.params.id)
.single()
return {
post
}
}
}
</script>
Beim Laden der Seite wird der Routenparameter verwendet, um die Beitragsmetadaten abzurufen.
Beiträge verwalten
Das letzte Feature, das wir uns wünschen, ist, Benutzern die Möglichkeit zu geben, ihre eigenen Beiträge zu bearbeiten und zu löschen. Um das tun zu können, sollten wir ihnen eine Seite bereitstellen, die ihre eigenen Beiträge anzeigt, anstatt die aller Beiträge.
Das stimmt, wir brauchen eine weitere neue Datei, diesmal namens my-posts.vue, im Verzeichnis pages. Sie ruft nur die Beiträge des aktuell authentifizierten Benutzers ab.
<!-- pages/my-posts.vue -->
<template>
<main>
<div v-for="post in posts" :key="post.id">
<div class="cursor-pointer border-b border-gray-300 mt-8 pb-4">
<h2 class="text-xl font-semibold">{{ post.title }}</h2>
<p class="text-gray-500 mt-2">Author: {{ post.user_email }}</p>
<NuxtLink :to="`/edit-post?id=${post.id}`" class="text-sm mr-4 text-blue-500">Edit Post</NuxtLink>
<NuxtLink :to="`/posts/${post.id}`" class="text-sm mr-4 text-blue-500">View Post</NuxtLink>
<button
class="text-sm mr-4 text-red-500"
@click="deletePost(post.id)"
>Delete Post</button>
</div>
</div>
<h1 v-if="loaded && !posts.length" class="text-2xl">No posts...</h1>
</main>
</template>
<script>
export default {
async created() {
this.fetchPosts()
},
data() {
return {
posts: [],
loaded: false
}
},
methods: {
async fetchPosts() {
const user = this.$supabase.auth.user()
if (!user) return
/* fetch only the posts for the signed in user */
const { data: posts, error } = await this.$supabase
.from('posts')
.select('*')
.filter('user_id', 'eq', user.id)
this.posts = posts
this.loaded = true
},
async deletePost(id) {
await this.$supabase
.from('posts')
.delete()
.match({ id })
this.fetchPosts()
}
}
}
</script>
Die Abfrage auf dieser Seite zum Abrufen der Beiträge verwendet einen Filter, der die Benutzer-ID des angemeldeten Benutzers übergibt. Es gibt auch eine Schaltfläche zum Löschen eines Beitrags und eine Schaltfläche zum Bearbeiten eines Beitrags. Wenn ein Beitrag gelöscht wird, rufen wir die Beiträge erneut ab, um die Benutzeroberfläche zu aktualisieren. Wenn ein Benutzer einen Beitrag bearbeiten möchte, leiten wir ihn zur Seite edit-post.vue weiter, die wir als Nächstes erstellen.
Einen Beitrag bearbeiten
Die letzte Seite, die wir erstellen möchten, ermöglicht es Benutzern, einen Beitrag zu bearbeiten. Diese Seite ähnelt sehr der Seite create-post.vue. Der Hauptunterschied besteht darin, dass wir den Beitrag anhand der aus dem Routenparameter abgerufenen id abrufen. Erstellen Sie also diese Datei und legen Sie sie mit diesem Code in den Ordner pages.
<!-- pages/edit-post.vue -->
<template>
<main>
<div id="editor">
<h1 class="text-3xl font-semibold tracking-wide mt-6">Create new post</h1>
<input
name="title"
placeholder="Title"
v-model="post.title"
class="border-b pb-2 text-lg my-4 focus:outline-none w-full font-light text-gray-500 placeholder-gray-500 y-2"
/>
<client-only>
<vue-simplemde v-model="post.content"></vue-simplemde>
</client-only>
<button
type="button"
class="mb-4 w-full bg-blue-500 text-white font-semibold px-8 py-4"
@click="editPost"
>Edit Post</button>
</div>
</main>
</template>
<script>
export default {
async created() {
/* when the page loads, fetch the post using the route id parameter */
const id = this.$route.query.id
const { data: post } = await this.$supabase
.from('posts')
.select()
.filter('id', 'eq', id)
.single()
if (!post) this.$router.push('/')
this.post = post
},
data() {
return {
post: {}
}
},
methods: {
async editPost() {
/* when the user edits a post, redirect them back to their posts */
const { title, content } = this.post
if (!title || !content) return
await this.$supabase
.from('posts')
.update([
{ title, content }
])
.match({ id: this.post.id })
this.$router.push('/my-posts')
}
}
}
</script>

Ausprobieren
Das ist der gesamte Code, wir sollten ihn ausprobieren können! Wir können lokal mit dem folgenden Befehl testen:
npm run dev
Wenn die App geladen ist, melden Sie sich mit dem auf der Profilseite aktivierten Magic-Link für ein neues Konto an. Sobald Sie sich registriert haben, testen Sie alles, indem Sie Beiträge hinzufügen, bearbeiten und löschen.

Zusammenfassung
Ziemlich gut, oder? Das ist die Art von Leichtigkeit und Einfachheit, von der ich am Anfang dieses Tutorials gesprochen habe. Wir haben eine neue App mit Supabase gestartet und mit ein paar Abhängigkeiten, etwas Konfiguration und einer Handvoll Vorlagen haben wir eine voll funktionsfähige App erstellt, mit der Leute Blog-Beiträge erstellen und verwalten können – komplett mit einem Backend, das Authentifizierung, Identitätsmanagement und Routing unterstützt!
Was wir haben, ist eine grundlegende Funktionalität, aber Sie können wahrscheinlich sehen, welches hohe Potenzial hier für mehr besteht. Und ich hoffe, Sie tun das auch! Mit allen richtigen Zutaten können Sie das, was wir gemacht haben, erweitern und mit Ihren eigenen Verbesserungen und Stilen ergänzen.
Interessanter Lesestoff!
Ich kann Ihr Repository nicht klonen. Fehler unten
[email protected]: Zugriff verweigert (publickey).