Rumah >hujung hadapan web >tutorial js >Mari kita bincangkan tentang cara membina aplikasi Angular menggunakan MemFire ​​​​Cloud

Mari kita bincangkan tentang cara membina aplikasi Angular menggunakan MemFire ​​​​Cloud

青灯夜游
青灯夜游ke hadapan
2022-08-30 20:44:121787semak imbas

Bagaimana untuk membina aplikasi Angular? Artikel berikut akan memperkenalkan kepada anda cara menggunakan MemFire ​​​​Cloud untuk membina aplikasi Angular Saya harap ia akan membantu anda!

Mari kita bincangkan tentang cara membina aplikasi Angular menggunakan MemFire ​​​​Cloud

[Cadangan tutorial berkaitan: "tutorial sudut"]

MemFire ​​​​Cloud ialah awan pembekal Pangkalan Data, pengguna boleh mencipta pangkalan data awan, mengurus pangkalan data dan melakukan operasi sandaran pada pangkalan data. Ia juga menyediakan bahagian belakang sebagai perkhidmatan Pengguna boleh membuat aplikasi baharu dalam masa 1 minit, menggunakan API dan SDK yang dijana secara automatik, dan mengakses pangkalan data awan, storan objek, pengesahan dan kebenaran pengguna dan fungsi lain kod dan mempercepatkan pembangunan aplikasi WEB atau APP.

Alamat video pembelajaran: www.bilibili.com/video/BV1wt…

Contoh ini menyediakan membina pengguna mudah menggunakan MemFire ​​​​Cloud dan Langkah sudut untuk mengurus aplikasi (dari awal). Ini termasuk:

  • MemFire ​​​​Cloud: pangkalan data MemFireDB untuk menyimpan data pengguna.
  • Pengesahan Pengguna Cloud MemFire: Pengguna boleh log masuk menggunakan pautan ajaib (hanya e-mel diperlukan, tiada kata laluan diperlukan).
  • MemFire ​​​​Cloud Storage: Pengguna boleh memuat naik foto.
  • Dasar Keselamatan Peringkat Baris: Data dilindungi supaya individu hanya boleh mengakses data mereka sendiri.
  • API Segera: API dijana secara automatik apabila membuat jadual pangkalan data.

Pada penghujung panduan ini, anda akan mempunyai apl yang membenarkan pengguna log masuk dan mengemas kini beberapa butiran profil asas:

Mari kita bincangkan tentang cara membina aplikasi Angular menggunakan MemFire ​​​​Cloud

Buat Aplikasi

Tujuan: Aplikasi kami adalah untuk mendapatkan satu siri sumber seperti pangkalan data dan storan awan melalui aplikasi yang dibuat di sini, dan mendapatkan pautan akses API dan kunci akses eksklusif aplikasi Pengguna boleh berkomunikasi dengan mudah dengan sumber di atas untuk berinteraksi.

Log Masukcloud.memfiredb.com/auth/login Cipta aplikasi

Mari kita bincangkan tentang cara membina aplikasi Angular menggunakan MemFire ​​​​Cloud

Buat jadual data

Klik Guna , cipta jadual data secara visual

1 Cipta jadual profil; >

Id medan jadual profil dikaitkan dengan kunci asing kepada medan id (jenis uuid) dalam jadual auth.users.

Mari kita bincangkan tentang cara membina aplikasi Angular menggunakan MemFire ​​​​Cloud2. Dayakan peraturan akses keselamatan data RLS untuk Profil

Pilih jadual Profil yang dibuat, klik pada bar kebenaran jadual, seperti yang ditunjukkan dalam rajah di bawah, klik butang "Dayakan RLS"

3 Benarkan setiap pengguna melihat maklumat peribadi awam

Mari kita bincangkan tentang cara membina aplikasi Angular menggunakan MemFire ​​​​CloudKlik butang "Peraturan Baharu", dan dalam kotak timbul, pilih ". Dayakan akses untuk semua pengguna" Kebenaran", masukkan nama dasar, pilih operasi "PILIH (pertanyaan)" dan klik butang "Buat Dasar", seperti yang ditunjukkan di bawah.

4 Hanya benarkan pengguna untuk menambah, memadam, mengubah suai dan menyemak maklumat profil peribadi mereka; kotak timbul, pilih " "Dayakan kebenaran akses untuk pengguna berdasarkan ID pengguna", masukkan nama dasar, pilih operasi "SEMUA" dan klik butang "Buat Dasar", seperti yang ditunjukkan di bawah.

Mari kita bincangkan tentang cara membina aplikasi Angular menggunakan MemFire ​​​​Cloud

Buat baldi avatar

Mari kita bincangkan tentang cara membina aplikasi Angular menggunakan MemFire ​​​​CloudBuat baldi storan awan untuk menyimpan imej avatar pengguna termasuk:

1. Cipta avatar baldiDalam bar navigasi storan awan aplikasi, klik butang "Timba Baharu" untuk mencipta avatar baldi.

2 Benarkan setiap pengguna melihat avatar baldi

Pilih avatar baldi, tukar ke lajur

Tetapan KebenaranMari kita bincangkan tentang cara membina aplikasi Angular menggunakan MemFire ​​​​Cloud dan klik butang "Peraturan Baharu" akan muncul kotak pop timbul penyuntingan dasar, pilih "Tersuai", seperti yang ditunjukkan di bawah:

Pilih operasi PILIH, masukkan nama dasar dan klik butang "Jana Dasar", seperti yang ditunjukkan dalam rajah di bawah.

Mari kita bincangkan tentang cara membina aplikasi Angular menggunakan MemFire ​​​​Cloud

3. Benarkan pengguna memuat naik avatar baldi; "Baharu" Klik butang "Peraturan" untuk muncul kotak pop timbul penyuntingan dasar, pilih "Tersuai", seperti yang ditunjukkan dalam rajah di bawah:

Pilih INSERT operasi, masukkan nama dasar, dan klik butang "Jana Dasar" , seperti yang ditunjukkan dalam rajah di bawah.

Mari kita bincangkan tentang cara membina aplikasi Angular menggunakan MemFire ​​​​Cloud

Lihat hasil

1Mari kita bincangkan tentang cara membina aplikasi Angular menggunakan MemFire ​​​​Cloud

SQL semua jadual data dan RLS (nama strategi digantikan dengan bahasa Inggeris)

1Mari kita bincangkan tentang cara membina aplikasi Angular menggunakan MemFire ​​​​Cloud

Dapatkan Kunci API

-- Create a table for public "profiles"
create table profiles (
  id uuid references auth.users not null,
  updated_at timestamp with time zone,
  username text unique,
  avatar_url text,
  website text,

  primary key (id),
  unique(username),
);

alter table profiles enable row level security;

create policy "Public profiles are viewable by everyone."
  on profiles for select
  using ( true );

create policy "Users can insert their own profile."
  on profiles for insert
  with check ( auth.uid() = id );

create policy "Users can update own profile."
  on profiles for update
  using ( auth.uid() = id );
-- Set up Storage!
insert into storage.buckets (id, name)
values ('avatars', 'avatars');

create policy "Avatar images are publicly accessible."
  on storage.objects for select
  using ( bucket_id = 'avatars' );

create policy "Anyone can upload an avatar."
  on storage.objects for insert
  with check ( bucket_id = 'avatars' );

Sekarang anda telah mencipta beberapa jadual pangkalan data, anda boleh menggunakan API yang dijana secara automatik untuk memasukkan data. Kami hanya perlu mendapatkan URL dan kunci anon daripada tetapan API. Pada halaman Aplikasi->Ringkasan, dapatkan alamat perkhidmatan dan maklumat token.

Kunci Anon (awam) ialah kunci API klien. Ia membenarkan "akses tanpa nama" ke pangkalan data anda sehingga pengguna log masuk. Selepas log masuk, kunci ditukar kepada token log masuk pengguna sendiri. Ini akan membolehkan keselamatan peringkat baris untuk data.

NOTA: Kunci servis_role (rahsia) menyediakan akses penuh kepada data anda, memintas sebarang dasar keselamatan. Kunci ini mesti dirahsiakan dan digunakan dalam persekitaran pelayan, tidak sekali-kali pada klien atau penyemak imbas. Dalam kod sampel seterusnya, supabaseUrl dan supabaseKey perlu disediakan.

Tetapan Pengesahan

Apabila pengguna mengklik pautan ajaib dalam e-mel untuk log masuk, mereka perlu melompat ke antara muka log masuk aplikasi kami. Di sini anda perlu mengkonfigurasi pengalihan URL yang berkaitan dalam tetapan pengesahan. Oleh kerana permohonan terakhir kami akan dimulakan pada port tempatan 4200 (atau port lain), jadi di sini kami menetapkan sementara url ke http://localhost:4200

Selain itu, anda boleh juga menyesuaikan dan menggunakan pelayan SMTP kami sendiri dalam antara muka ini.

Membina aplikasi

Mari membina aplikasi Angular dari awal.

Memulakan Projek

Kita boleh menggunakan Angular CLI untuk memulakan projek bernama

:

Angular memerlukan Node. js (>=14.15 memfiredb-angular

Kemudian mari kita pasang satu-satunya kebergantungan tambahan:

supabase-js

npm install -g @angular/cli
npx ng new memfiredb-angular --routing false --style css
cd memfiredb-angular

Akhir sekali, kami ingin menyimpan pembolehubah persekitaran dalam environment.ts, Semua yang kami perlukan ialah URL API dan kunci yang anda salin di atas.

npm install @supabase/supabase-js
fail src/environments/environment.ts

anon

Kini setelah kita mempunyai kelayakan API, buat

SupabaseService

oleh
export const environment = {
  production: false,
  supabaseUrl: "YOUR_SUPABASE_URL",
  supabaseKey: "YOUR_SUPABASE_KEY"
};
untuk memulakan klien Supabase dan Fungsi yang melaksanakan komunikasi dengan API Supabase.

ng g s supabasesrc/app/supabase.service.ts

Gaya kemas kini

import { Injectable } from '@angular/core';
import {AuthChangeEvent, createClient, Session, SupabaseClient} from '@supabase/supabase-js';
import {environment} from "../environments/environment";

export interface Profile {
  username: string;
  website: string;
  avatar_url: string;
}

@Injectable({
  providedIn: 'root'
})
export class SupabaseService {
  private supabase: SupabaseClient;

  constructor() {
    this.supabase = createClient(environment.supabaseUrl, environment.supabaseKey);
  }

  get user() {
    return this.supabase.auth.user();
  }

  get session() {
    return this.supabase.auth.session();
  }

  get profile() {
    return this.supabase
      .from('profiles')
      .select(`username, website, avatar_url`)
      .eq('id', this.user?.id)
      .single();
  }

  authChanges(callback: (event: AuthChangeEvent, session: Session | null) => void) {
    return this.supabase.auth.onAuthStateChange(callback);
  }

  signIn(email: string) {
    return this.supabase.auth.signIn({email});
  }

  signOut() {
    return this.supabase.auth.signOut();
  }

  updateProfile(profile: Profile) {
    const update = {
      ...profile,
      id: this.user?.id,
      updated_at: new Date()
    }

    return this.supabase.from('profiles').upsert(update, {
      returning: 'minimal', // Don't return the value after inserting
    });
  }

  downLoadImage(path: string) {
    return this.supabase.storage.from('avatars').download(path);
  }

  uploadAvatar(filePath: string, file: File) {
    return this.supabase.storage
      .from('avatars')
      .upload(filePath, file);
  }
}

Anda dapat melihat bahawa antara muka sebenarnya tidak begitu elegan, sila kemas kini Gayakannya untuk menjadikannya kelihatan lebih baik. Ubah suai fail .

src/styles.cssSediakan komponen log masuk

html,
body {
  --custom-font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu,
    Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
  --custom-bg-color: #101010;
  --custom-panel-color: #222;
  --custom-box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.8);
  --custom-color: #fff;
  --custom-color-brand: #24b47e;
  --custom-color-secondary: #666;
  --custom-border: 1px solid #333;
  --custom-border-radius: 5px;
  --custom-spacing: 5px;

  padding: 0;
  margin: 0;
  font-family: var(--custom-font-family);
  background-color: var(--custom-bg-color);
}

* {
  color: var(--custom-color);
  font-family: var(--custom-font-family);
  box-sizing: border-box;
}

html,
body,
#__next {
  height: 100vh;
  width: 100vw;
  overflow-x: hidden;
}

/* Grid */

.container {
  width: 90%;
  margin-left: auto;
  margin-right: auto;
}
.row {
  position: relative;
  width: 100%;
}
.row [class^='col'] {
  float: left;
  margin: 0.5rem 2%;
  min-height: 0.125rem;
}
.col-1,
.col-2,
.col-3,
.col-4,
.col-5,
.col-6,
.col-7,
.col-8,
.col-9,
.col-10,
.col-11,
.col-12 {
  width: 96%;
}
.col-1-sm {
  width: 4.33%;
}
.col-2-sm {
  width: 12.66%;
}
.col-3-sm {
  width: 21%;
}
.col-4-sm {
  width: 29.33%;
}
.col-5-sm {
  width: 37.66%;
}
.col-6-sm {
  width: 46%;
}
.col-7-sm {
  width: 54.33%;
}
.col-8-sm {
  width: 62.66%;
}
.col-9-sm {
  width: 71%;
}
.col-10-sm {
  width: 79.33%;
}
.col-11-sm {
  width: 87.66%;
}
.col-12-sm {
  width: 96%;
}
.row::after {
  content: '';
  display: table;
  clear: both;
}
.hidden-sm {
  display: none;
}

@media only screen and (min-width: 33.75em) {
  /* 540px */
  .container {
    width: 80%;
  }
}

@media only screen and (min-width: 45em) {
  /* 720px */
  .col-1 {
    width: 4.33%;
  }
  .col-2 {
    width: 12.66%;
  }
  .col-3 {
    width: 21%;
  }
  .col-4 {
    width: 29.33%;
  }
  .col-5 {
    width: 37.66%;
  }
  .col-6 {
    width: 46%;
  }
  .col-7 {
    width: 54.33%;
  }
  .col-8 {
    width: 62.66%;
  }
  .col-9 {
    width: 71%;
  }
  .col-10 {
    width: 79.33%;
  }
  .col-11 {
    width: 87.66%;
  }
  .col-12 {
    width: 96%;
  }
  .hidden-sm {
    display: block;
  }
}

@media only screen and (min-width: 60em) {
  /* 960px */
  .container {
    width: 75%;
    max-width: 60rem;
  }
}

/* Forms */

label {
  display: block;
  margin: 5px 0;
  color: var(--custom-color-secondary);
  font-size: 0.8rem;
  text-transform: uppercase;
}

input {
  width: 100%;
  border-radius: 5px;
  border: var(--custom-border);
  padding: 8px;
  font-size: 0.9rem;
  background-color: var(--custom-bg-color);
  color: var(--custom-color);
}

input[disabled] {
  color: var(--custom-color-secondary);
}

/* Utils */

.block {
  display: block;
  width: 100%;
}
.inline-block {
  display: inline-block;
  width: 100%;
}
.flex {
  display: flex;
}
.flex.column {
  flex-direction: column;
}
.flex.row {
  flex-direction: row;
}
.flex.flex-1 {
  flex: 1 1 0;
}
.flex-end {
  justify-content: flex-end;
}
.flex-center {
  justify-content: center;
}
.items-center {
  align-items: center;
}
.text-sm {
  font-size: 0.8rem;
  font-weight: 300;
}
.text-right {
  text-align: right;
}
.font-light {
  font-weight: 300;
}
.opacity-half {
  opacity: 50%;
}

/* Button */

button,
.button {
  color: var(--custom-color);
  border: var(--custom-border);
  background-color: var(--custom-bg-color);
  display: inline-block;
  text-align: center;
  border-radius: var(--custom-border-radius);
  padding: 0.5rem 1rem;
  cursor: pointer;
  text-align: center;
  font-size: 0.9rem;
  text-transform: uppercase;
}

button.primary,
.button.primary {
  background-color: var(--custom-color-brand);
  border: 1px solid var(--custom-color-brand);
}

/* Widgets */

.card {
  width: 100%;
  display: block;
  border: var(--custom-border);
  border-radius: var(--custom-border-radius);
  padding: var(--custom-spacing);
}

.avatar {
  border-radius: var(--custom-border-radius);
  overflow: hidden;
  max-width: 100%;
}
.avatar.image {
  object-fit: cover;
}
.avatar.no-image {
  background-color: #333;
  border: 1px solid rgb(200, 200, 200);
  border-radius: 5px;
}

.footer {
  position: absolute;
  max-width: 100%;
  bottom: 0;
  left: 0;
  right: 0;
  display: flex;
  flex-flow: row;
  border-top: var(--custom-border);
  background-color: var(--custom-bg-color);
}
.footer div {
  padding: var(--custom-spacing);
  display: flex;
  align-items: center;
  width: 100%;
}
.footer div > img {
  height: 20px;
  margin-left: 10px;
}
.footer > div:first-child {
  display: none;
}
.footer > div:nth-child(2) {
  justify-content: left;
}

@media only screen and (min-width: 60em) {
  /* 960px */
  .footer > div:first-child {
    display: flex;
  }
  .footer > div:nth-child(2) {
    justify-content: center;
  }
}

@keyframes spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

.mainHeader {
  width: 100%;
  font-size: 1.3rem;
  margin-bottom: 20px;
}

.avatarPlaceholder {
  border: var(--custom-border);
  border-radius: var(--custom-border-radius);
  width: 35px;
  height: 35px;
  background-color: rgba(255, 255, 255, 0.2);
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Auth */

.auth-widget {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.auth-widget > .button {
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  background-color: #444444;
  text-transform: none !important;
  transition: all 0.2s ease;
}

.auth-widget .button:hover {
  background-color: #2a2a2a;
}

.auth-widget .button > .loader {
  width: 17px;
  animation: spin 1s linear infinite;
  filter: invert(1);
}

/* Account */

.account {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.account > * > .avatarField {
  display: flex;
  align-items: center;
  margin-bottom: 30px;
}

.account > * > .avatarField > .avatarContainer {
  margin-right: 20px;
}

/* Profile Card */

.profileCard {
  border-radius: 5px;
  display: flex;
  border: var(--custom-border);
  background-color: var(--custom-panel-color);
  padding: 20px 20px;
  margin-bottom: 20px;
}

.profileCard:last-child {
  margin-bottom: 0px;
}

.profileCard > .userInfo {
  margin-left: 20px;
  font-weight: 300;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.profileCard > .userInfo > p {
  margin: 0;
}

.profileCard > .userInfo > .username {
  font-size: 1.3rem;
  font-weight: 500;
  margin-bottom: 5px;
}

.profileCard > .userInfo > .website {
  font-size: 0.9rem;
  color: var(--custom-color-brand);
  margin-bottom: 10px;
  text-decoration: none;
}

Mari sediakan komponen Angular untuk mengurus log masuk dan pendaftaran. Kami akan menggunakan Pautan Ajaib supaya pengguna boleh log masuk menggunakan e-mel mereka tanpa perlu menggunakan kata laluan. Cipta

AuthComponent menggunakan arahan CLI Sudut.

src/app/auth/auth.component.tsng g c auth

Halaman maklumat pengguna

import { Component } from '@angular/core';
import {SupabaseService} from "../supabase.service";

@Component({
  selector: 'app-auth',
  template: `
    <div>
      <form>
        <h1>Memfiredb + Angular</h1>
        <p>使用下面的电子邮件通过魔术链接登录</p>
        <div>
          <input>
        </div>
        <div>
          <button>
          {{loading ? 'Loading' : 'Send magic link'}}
          </button>
        </div>
      </form>
    </div>
  `,
})
export class AuthComponent {
  loading = false;

  constructor(private readonly supabase: SupabaseService) { }

  async handleLogin(input: string) {
    try {
      this.loading = true;
      await this.supabase.signIn(input);
      alert('请检查您的电子邮件以获取登录链接!');
    } catch (error:any) {
      alert(error.error_description || error.message)
    } finally {
      this.loading = false;
    }
  }
}

Selepas pengguna log masuk , kami boleh membenarkan mereka mengedit butiran profil mereka dan mengurus akaun mereka. Cipta AccountComponent menggunakan arahan CLI Sudut.

src/app/account/account.component.tsng g c account

Ubah suai fail kemasukan projek

import {Component, Input, OnInit} from '@angular/core';
import {Profile, SupabaseService} from "../supabase.service";
import {Session} from "@supabase/supabase-js";

@Component({
  selector: 'app-account',
  template: `
    <div>
      <div>
        <label>邮箱</label>
        <input>
      </div>
      <div>
        <label>名称</label>
        <input>
      </div>
      <div>
        <label>网址</label>
        <input>
      </div>

      <div>
        <button>
          {{loading ? 'Loading ...' : 'Update'}}
        </button>
      </div>

      <div>
        <button>
          退出登录
        </button>
      </div>
    </div>
  `
})
export class AccountComponent implements OnInit {
  loading = false;
  profile: Profile | undefined;

  @Input() session: Session | undefined;

  constructor(private readonly supabase: SupabaseService) { }

  ngOnInit() {
    this.getProfile();
  }

  async getProfile() {
    try {
      this.loading = true;
      let {data: profile, error, status} = await this.supabase.profile;

      if (error && status !== 406) {
        throw error;
      }

      if (profile) {
        this.profile = profile;
      }
    } catch (error:any) {
      alert(error.message)
    } finally {
      this.loading = false;
    }
  }

  async updateProfile(username: string, website: string, avatar_url: string = '') {
    try {
      this.loading = true;
      await this.supabase.updateProfile({username, website, avatar_url});
    } catch (error:any) {
      alert(error.message);
    } finally {
      this.loading = false;
    }
  }

  async signOut() {
    await this.supabase.signOut();
  }
}

Sekarang kami Dengan semua komponen sedia, mari kemas kini AppComponent:

src/app/app.component.ts

import {Component, OnInit} from '@angular/core';
import {SupabaseService} from "./supabase.service";

@Component({
  selector: 'app-root',
  template: `
  <div>
    <app-account></app-account>
    <ng-template>
      <app-auth></app-auth>
    </ng-template>
  </div>
  `
})
export class AppComponent implements OnInit {
  session = this.supabase.session;

  constructor(private readonly supabase: SupabaseService) { }

  ngOnInit() {
    this.supabase.authChanges((_, session) => this.session = session);
  }
}

完成后,在终端窗口中运行它:

npm run start

然后打开浏览器到 http://localhost:4200,你应该会看到完整的应用程序。

实现:上传头像及更新用户信息

每个 MemFire Cloud项目都配置了存储,用于管理照片和视频等大文件。

创建上传小组件

让我们为用户创建一个头像,以便他们可以上传个人资料照片。使用Angular CLI 命令创建AvatarComponent 。 ng g c avatar

src/app/avatar/avatar.component.ts

import {Component, EventEmitter, Input, Output} from '@angular/core';
import {SupabaseService} from "../supabase.service";
import {DomSanitizer, SafeResourceUrl} from "@angular/platform-browser";

@Component({
  selector: 'app-avatar',
  template: `
    <div>
      <img  alt="Mari kita bincangkan tentang cara membina aplikasi Angular menggunakan MemFire ​​​​Cloud" >
</div>
    <div></div>
    <div>
      <label>
        {{uploading ? 'Uploading ...' : 'Upload'}}
      </label>
      <input>
    </div>
  `,
})
export class AvatarComponent {
  _avatarUrl: SafeResourceUrl | undefined;
  uploading = false;

  @Input()
  set avatarUrl(url: string | undefined) {
    if (url) {
      this.downloadImage(url);
    }
  };

  @Output() upload = new EventEmitter<string>();

  constructor(
    private readonly supabase: SupabaseService,
    private readonly dom: DomSanitizer
  ) { }

  async downloadImage(path: string) {
    try {
      const {data} = await this.supabase.downLoadImage(path);
       if (data instanceof Blob) {
        this._avatarUrl = this.dom.bypassSecurityTrustResourceUrl(
          URL.createObjectURL(data)
        );
      }
    } catch (error:any) {
      console.error('下载图片出错: ', error.message);
    }
  }

  async uploadAvatar(event: any) {
    try {
      this.uploading = true;
      if (!event.target.files || event.target.files.length === 0) {
        throw new Error('必须选择要上载的图像。');
      }

      const file = event.target.files[0];
      const fileExt = file.name.split('.').pop();
      const fileName = `${Math.random()}.${fileExt}`;
      const filePath = `${fileName}`;

      await this.supabase.uploadAvatar(filePath, file);
      this.upload.emit(filePath);
      this.downloadImage(filePath)
    } catch (error:any) {
      alert(error.message);
    } finally {
      this.uploading = false;
    }
  }
}</string>

然后我们可以在AccountComponent html 模板的顶部添加小部件:

src/app/account/account.component.ts

import {Component, Input, OnInit} from '@angular/core';
import {Profile, SupabaseService} from "../supabase.service";
import {Session} from "@supabase/supabase-js";

@Component({
  selector: 'app-account',
  template: `
      <app-avatar>
    </app-avatar>
    <div>
      <div>
        <label>邮箱</label>
        <input>
      </div>
      <div>
        <label>名称</label>
        <input>
      </div>
      <div>
        <label>网址</label>
        <input>
      </div>

      <div>
        <button>
          {{loading ? 'Loading ...' : 'Update'}}
        </button>
      </div>

      <div>
        <button>
          退出登录
        </button>
      </div>
    </div>
  `
})
export class AccountComponent implements OnInit {
  loading = false;
  profile: Profile | undefined;

  @Input() session: Session | undefined;

  constructor(private readonly supabase: SupabaseService) { }

  ngOnInit() {
    this.getProfile();
  }

  async getProfile() {
    try {
      this.loading = true;
      let {data: profile, error, status} = await this.supabase.profile;

      if (error && status !== 406) {
        throw error;
      }

      if (profile) {
        this.profile = profile;
      }
    } catch (error:any) {
      alert(error.message)
    } finally {
      this.loading = false;
    }
  }

  async updateProfile(username: string, website: string, avatar_url: string = '') {
    try {
      this.loading = true;
      await this.supabase.updateProfile({username, website, avatar_url});
      alert("修改成功")
    } catch (error:any) {
      alert(error.message);
    } finally {
      this.loading = false;
    }
  }

  async signOut() {
    await this.supabase.signOut();
  }
}

恭喜!在这个阶段,您拥有一个功能齐全的应用程序!

更多编程相关知识,请访问:编程视频!!

Atas ialah kandungan terperinci Mari kita bincangkan tentang cara membina aplikasi Angular menggunakan MemFire ​​​​Cloud. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:juejin.cn. Jika ada pelanggaran, sila hubungi admin@php.cn Padam