Vue 3 + Tailwindcss + Supabase로 블로그 만들기

안녕 얘들아

저는 7년 전부터 Vue를 사용하여 웹 애플리케이션을 개발해 왔으며 정말 마음에 듭니다!

Vue 3가 막 출시되었고 Tailwindcss로 첫 번째 Vue 3 애플리케이션을 만드는 방법에 대한 빠른 게시물을 작성하는 것이 흥미로웠습니다.



1. Vue.js 설치



전제 조건: Node.js 버전 15.0 이상을 설치하십시오.

CLI를 사용하여 앱을 빌드합니다.

npm init vue@latest


그 다음에:

✔ Project name: … <your-project-name>
✔ Add TypeScript? … No / Yes
✔ Add JSX Support? … No / Yes
✔ Add Vue Router for Single Page Application development? … No / Yes
✔ Add Pinia for state management? … No / Yes
✔ Add Vitest for Unit testing? … No / Yes
✔ Add Cypress for both Unit and End-to-End testing? … No / Yes
✔ Add ESLint for code quality? … No / Yes
✔ Add Prettier for code formatting? … No / Yes

Scaffolding project in ./<your-project-name>...
Done.


수파베이스 설치:

npm i @supabase/supabase-js


드디어:

npm i && npm run dev


이제 프로젝트가 실행 중이어야 합니다.

2. Tailwindcss 설치



이전 기사에서 따라야 할 모든 단계를 설명했습니다. .

3. 보기 및 구성 요소 정리



기본적으로 구성 요소와 보기가 있습니다. 그것들을 제거하고 대신 논문 파일을 만드십시오.

src/views/Home.vue
src/views/Post.vue
src/components/Header.vue
src/store.js
src/supabase.js


Header.vue 구성 요소를 다음과 같이 즉시 변경할 수 있습니다.

<template>
  <header class=" text-center my-8">
    <h1 class="text-blue-300 text-6xl font-bold mb-4" @click="$router.push('/')">Guillaume's blog</h1>
    <p class="text-xl text-slate-500">A blog with posts on what I like.</p>
  </header>
</template>


4. App.vue의 Vue-Router



여기에서 경로를 표시하는 루트 파일(App.vue)이 필요합니다.

<script setup>
import { RouterView } from 'vue-router'
import Header from './components/Header.vue'
</script>

<template>
  <Header />
  <RouterView />
</template>


또한 다음 페이지를 표시하려면 라우터가 필요합니다.

// src/router/index.js

import { createRouter, createWebHistory } from 'vue-router'


const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/',
      name: 'Home',
      component: () => import('../views/Home.vue')
    }, {
      path: '/post/:id',
      name: 'Post',
      component: () => import('../views/Post.vue')
    }
  ]
})

export default router



이제 2개의 경로를 사용할 수 있어야 합니다.

5. 수파베이스 구성



Please check my video in order to create your table "Posts" and configure your Supabase.



supabase.js로 이동하여 클라이언트를 구성합니다.

import { createClient } from '@supabase/supabase-js';

const supabaseUrl = import.meta.env.VITE_SUPABASE_URL;
const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEY;

const supabase = createClient(supabaseUrl, supabaseAnonKey);

export default supabase


이제 .env 파일을 만들어야 합니다.

touch .env

VITE_SUPABASE_URL=
VITE_SUPABASE_ANON_KEY=


서버를 다시 시작하십시오.

6. 상점을 만들자.



store.js에서 반응 상수를 만들어 봅시다. 여기에서 변수를 동적으로 만들고 요소를 표시하려면 반응성이 중요합니다. 그렇지 않으면 앱에서 데이터가 비어 있게 됩니다.

import { reactive } from 'vue'

const store = reactive({
  posts: []
})

export {store};


7. 집은 집이다



Home.vue 보기에는 Supabase에서 가져온 게시물 목록이 표시됩니다.

이를 위해 마운트 즉시 트리거되는 fetchPosts 함수를 생성합니다.

게시물이 없는 경우 '게시물이 없습니다'라는 메시지가 표시됩니다.

<script setup>
import { store } from '../store'
import supabase from '../supabase'

const getWordsNumber = (str) => (str.split(' ').length)

const fetchPosts = async () => {
  let { data: posts, error } = await supabase
  .from('posts')
  .select()

  if (error) throw new Error(error)

  store.posts = posts
} 

fetchPosts()
</script>

<template>
  <div class="Home">
    <main class="container mx-auto">
      <div v-if="store.posts.length < 1">
        There is no posts.
      </div>
      <div v-else>
        <div class="PostItem border border-slate-200 mb-4 p-4 rounded-lg cursor-pointer" v-for="item, itemIndex in store.posts" :key="itemIndex" @click="$router.push(`/post/${item.id}`)">
          <h1 class="text-slate-900 text-3xl font-bold">
            {{ item.title }}
          </h1>
          <p>{{ getWordsNumber(item.description) }} words.</p>
        </div>
      </div>
    </main>
  </div>
</template>


클릭하면 이전에 만든 게시물 경로로 이동하는 것을 볼 수 있습니다.

8. 포스트 보기



포스트 보기는 조금 다릅니다.

또한 Supabase에서 게시물을 가져와야 합니다. 그렇지 않으면 데이터가 비어 있게 됩니다.

fetchPost 기능을 살펴보십시오. 가드가 있습니다. 게시물이 이미 스토어에 있으면 가져오지 않고 찾은 항목을 게시물 변수에 적용합니다.

<script setup>
import { reactive } from 'vue'
import { useRoute } from 'vue-router'
import {store} from '../store'
import supabase from '../supabase'

const route = useRoute()

let post = reactive({})

const fetchPost = async (id) => {
  const found = store.posts.find(x => x.id === parseInt(route.params.id))
  if (found) {
    Object.assign(post, found)
    return
  }
  let { data, error } = await supabase
  .from('posts')
  .select()
  .eq('id', id)
  .single()

  if (error) throw new Error(error)

  Object.assign(post, data)
} 

fetchPost(route.params.id)
</script>

<template>
  <div class="Post text-center container mx-auto">
    <div v-if="!post">
      No post found.
    </div>
    <div v-else>
      <h1 class="text-slate-900 text-3xl font-bold mb-4">{{ post.title }}</h1>
      <p class="text-md text-slate-300">{{ post.created_at }}</p>
      <p class="text-xl text-slate-500">{{ post.description}}</p>
    </div>
  </div>
</template>


이 짧은 기사가 도움이 되었기를 바랍니다. 질문이나 모범 사례가 있으면 제 손님이 되어 주십시오.

최고 !

기욤

좋은 웹페이지 즐겨찾기