Vue로 PWA 개발 - 그랜파 개발자
이미 등록한 마이로그 수정 기능을 구현합니다.
게시물(Post) 수정 기능을 구현하려면, 사용자가 게시물을 수정할 수 있는 화면을 제공하고, Firestore에서 기존 게시물 데이터를 업데이트하는 로직이 필요합니다. Vue.js와 Firestore를 사용해 게시물 수정 기능을 구현하는 방법을 설명드리겠습니다.
Firestore에서 게시물을 수정하기 위해서는 updateDoc 메서드를 사용하여 기존 문서를 업데이트할 수 있습니다. doc() 메서드를 사용해 특정 문서의 참조를 가져온 후, 수정할 데이터를 전달하면 Firestore에서 해당 데이터를 수정합니다.
Vuex에서 게시물 수정 액션을 정의하고, Firestore에서 게시물을 업데이트하는 로직을 작성합니다.
import { getFirestore, doc, updateDoc } from "firebase/firestore";
const db = getFirestore();
const store = new Vuex.Store({
state: {
posts: [], // 게시물 목록 저장
},
mutations: {
updatePost(state, updatedPost) {
const index = state.posts.findIndex(post => post.id === updatedPost.id);
if (index !== -1) {
state.posts.splice(index, 1, updatedPost); // 상태에서 게시물 수정
}
},
},
actions: {
// 게시물 수정 액션
async updatePost({ commit }, { postId, updatedData }) {
try {
const postRef = doc(db, "posts", postId);
await updateDoc(postRef, {
title: updatedData.title,
content: updatedData.content,
updatedAt: new Date(), // 수정한 시간 기록
});
commit('updatePost', { id: postId, ...updatedData });
console.log("게시물이 수정되었습니다.");
} catch (error) {
console.error("게시물 수정 실패:", error);
}
},
},
});
export default store;
<template>
<div>
<h3>Edit Post</h3>
<v-form ref="form" v-model="valid">
<v-text-field
label="Title"
v-model="editedPost.title"
:rules="[v => !!v || 'Title is required']"
></v-text-field>
<v-textarea
label="Content"
v-model="editedPost.content"
:rules="[v => !!v || 'Content is required']"
></v-textarea>
<v-btn :disabled="!valid" @click="submitPost">Save Changes</v-btn>
</v-form>
</div>
</template>
<script>
export default {
props: {
post: {
type: Object,
required: true,
},
},
data() {
return {
editedPost: { ...this.post }, // 초기값을 props로 전달된 post로 설정
valid: false, // 유효성 검사
};
},
methods: {
async submitPost() {
if (this.$refs.form.validate()) {
// Vuex 액션 호출하여 게시물 수정
await this.$store.dispatch('updatePost', {
postId: this.post.id,
updatedData: this.editedPost,
});
this.$router.push({ name: 'PostDetail', params: { postId: this.post.id } });
}
},
},
};
</script>
Vuex의 updatePost 뮤테이션을 사용해 Firestore에서 데이터를 업데이트한 후, 상태를 동기화하여 화면에서 바로 반영되도록 합니다. 수정된 게시물 데이터를 Vuex의 posts 배열에서 찾아 수정된 내용을 덮어씌웁니다.
게시물을 수정하는 페이지로 이동하기 위해서는 게시물 상세 화면에 수정 버튼을 추가하고, 해당 버튼을 클릭했을 때 수정 페이지로 이동하는 기능을 구현합니다.
<template>
<div>
<h1>{{ post.title }}</h1>
<p>{{ post.content }}</p>
<!-- 게시물 수정 버튼 -->
<v-btn @click="goToEdit">Edit Post</v-btn>
</div>
</template>
<script>
export default {
props: {
post: {
type: Object,
required: true,
},
},
methods: {
goToEdit() {
this.$router.push({ name: 'EditPost', params: { postId: this.post.id } });
},
},
};
</script>
수정 페이지로 이동할 수 있도록 Vue Router에서 라우팅 설정을 추가합니다.
import Vue from 'vue';
import Router from 'vue-router';
import PostDetail from './components/PostDetail.vue';
import EditPost from './components/EditPost.vue';
Vue.use(Router);
const routes = [
{
path: '/post/:postId',
name: 'PostDetail',
component: PostDetail,
props: true,
},
{
path: '/post/:postId/edit',
name: 'EditPost',
component: EditPost,
props: true,
},
];
export default new Router({
mode: 'history',
routes,
});
Firestore에서 게시물 수정: updateDoc을 사용해 Firestore에서 특정 게시물을 업데이트합니다.
Vuex의 상태 동기화: Firestore에서 게시물 수정 후 Vuex 상태를 업데이트하여 UI에서 바로 수정된 내용을 반영합니다.
Vue 컴포넌트: 사용자가 게시물을 수정할 수 있는 입력 폼을 제공하고, 수정된 내용을 Firestore에 반영합니다.
라우터 설정: 게시물 상세 페이지에서 수정 페이지로 이동할 수 있도록 라우터를 설정합니다.
이 방법으로 Vue.js와 Firestore를 사용하여 게시물 수정 기능을 쉽게 구현할 수 있습니다.
Vue.js에서 props를 사용하여 수정 화면에 데이터를 전달하는 방법은 라우터를 활용하는 방식입니다. 게시물의 수정 화면에 데이터를 넘기려면 라우트 파라미터를 이용하여 수정할 게시물의 postId와 관련된 데이터를 전달할 수 있습니다.
Vue Router에서는 props 옵션을 통해 라우트 파라미터를 컴포넌트로 전달할 수 있습니다. postId를 라우트로 전달하고, 해당 postId를 이용해 수정할 게시물의 데이터를 Firestore에서 가져와 수정 화면에서 사용할 수 있습니다.
import Vue from 'vue';
import Router from 'vue-router';
import EditPost from './components/EditPost.vue';
Vue.use(Router);
const routes = [
{
path: '/edit-post/:postId', // postId를 라우트 파라미터로 받음
name: 'EditPost',
component: EditPost,
props: true, // postId를 props로 전달
},
];
export default new Router({
mode: 'history',
routes,
});
props: true로 설정하면 postId를 URL 파라미터로 받아서 해당 컴포넌트에 props로 전달할 수 있습니다.
EditPost.vue 컴포넌트에서 props로 전달받은 postId를 이용해 Firestore에서 해당 게시물을 불러와 화면에 출력하고 수정할 수 있습니다.
<template>
<div>
<h2>Edit Post</h2>
<v-form v-if="post">
<v-text-field
v-model="post.title"
label="Post Title"
></v-text-field>
<v-textarea
v-model="post.content"
label="Post Content"
></v-textarea>
<v-btn @click="updatePost">Save Changes</v-btn>
</v-form>
</div>
</template>
<script>
import { getFirestore, doc, getDoc, updateDoc } from "firebase/firestore";
export default {
props: {
postId: {
type: String,
required: true,
},
},
data() {
return {
post: null, // 수정할 게시물 데이터
};
},
methods: {
async fetchPost() {
const db = getFirestore();
const postRef = doc(db, "posts", this.postId); // Firestore에서 postId로 게시물 가져옴
const postSnap = await getDoc(postRef);
if (postSnap.exists()) {
this.post = postSnap.data(); // 게시물 데이터를 post에 저장
} else {
console.log("No such document!");
}
},
async updatePost() {
const db = getFirestore();
const postRef = doc(db, "posts", this.postId);
await updateDoc(postRef, {
title: this.post.title,
content: this.post.content,
});
this.$router.push({ name: 'PostDetail', params: { postId: this.postId } }); // 수정 후 상세 페이지로 이동
},
},
mounted() {
this.fetchPost(); // 컴포넌트가 마운트되면 게시물 데이터를 가져옴
},
};
</script>
게시물 수정 페이지로 이동할 때는 router.push를 사용하여 postId를 파라미터로 넘겨줍니다.
<template>
<div>
<h1>{{ post.title }}</h1>
<p>{{ post.content }}</p>
<!-- 수정 버튼 -->
<v-btn v-if="isAuthor" @click="goToEdit">Edit Post</v-btn>
</div>
</template>
<script>
export default {
methods: {
goToEdit() {
this.$router.push({ name: 'EditPost', params: { postId: this.post.id } });
},
},
};
</script>
이 방법으로 수정 화면에서 props로 데이터를 넘기고, Firestore와 연동하여 게시물을 수정할 수 있습니다.