[Vue] Vuex를 이용한 인스타그램 좋아요 기능
[Vue] Vuex를 이용한 인스타그램 좋아요 기능
@숙제
피드 사진을 누르면 Likes가 1 증가하고, 다시 누르면 Likes가 1 감소한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
(store.js)
import { createStore } from "vuex";
const store = createStore({
state () {
return {
likes: 36,
}
},
mutations: {
changeLikes(state, data){
const isLikes = data[0];
const idx = data[1];
state.likes[idx] += (isLikes) ? 1 : -1;
}
}
})
export default store;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
(Post.vue)
<template>
<div class="post">
<div class="post-header">
<div class="profile" :style="{ backgroundImage : `url('${post.userImage}')` }"></div>
<span class="profile-name">{{ post.name }}</span>
</div>
<div class="post-body" :class="`${post.filter}`" :style="{ backgroundImage : `url('${post.postImage}')` }" @click="clickLikes"></div>
<div class="post-content">
<div class="icon">
<button type="button" class="btn_like" :class="{on : Likes}" title="좋아요"></button>
<button type="button" class="btn_comment" title="댓글 달기"></button>
<button type="button" class="btn_dm" title="게시물 공유"></button>
<button type="button" class="btn_keep" title="저장"></button>
</div>
<!-- <p class="like">{{ post.likes }} Likes</p> -->
<p class="like">{{ $store.state.likes[idx] }} Likes</p>
<p class="content"><strong>{{ post.name }}</strong> {{ post.content }}</p>
<p class="date">{{ post.date }}</p>
</div>
</div>
</template>
<script>
export default {
name: 'compPost',
data(){
return {
Likes: false,
}
},
methods: {
clickLikes(){
this.Likes = !this.Likes;
this.$store.commit('changeLikes', [this.Likes, this.idx]);
}
},
props: {
data: Object,
post: Object,
idx: Number,
filter: Text,
}
}
</script>
@강의 정답
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
(store.js)
import { createStore } from "vuex";
const store = createStore({
state () {
return {
likes: [ 36, 0, 5 ],
isLikes: [false, false, false],
}
},
mutations: {
changeLikes(state, data){
state.likes[data] += (state.isLikes[data]) ? -1 : 1;
state.isLikes[data] = !state.isLikes[data]
}
}
})
export default store;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
(Post.vue)
<template>
<div class="post">
<div class="post-header">
<div class="profile" :style="{ backgroundImage : `url('${post.userImage}')` }"></div>
<span class="profile-name">{{ post.name }}</span>
</div>
<div class="post-body" :class="`${post.filter}`" :style="{ backgroundImage : `url('${post.postImage}')` }" @click="clickLikes"></div>
<div class="post-content">
<div class="icon">
<button type="button" class="btn_like" :class="{on : $store.state.isLikes[idx]}" title="좋아요"></button>
<button type="button" class="btn_comment" title="댓글 달기"></button>
<button type="button" class="btn_dm" title="게시물 공유"></button>
<button type="button" class="btn_keep" title="저장"></button>
</div>
<!-- <p class="like">{{ post.likes }} Likes</p> -->
<p class="like">{{ $store.state.likes[idx] }} Likes</p>
<p class="content"><strong>{{ post.name }}</strong> {{ post.content }}</p>
<p class="date">{{ post.date }}</p>
</div>
</div>
</template>
<script>
export default {
name: 'compPost',
methods: {
clickLikes(){
this.$store.commit('changeLikes', this.idx);
}
},
props: {
data: Object,
post: Object,
idx: Number,
filter: Text,
}
}
</script>
@응용
게시물 등록 시 Likes 배열을 추가해보자
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
(store.js)
import { createStore } from "vuex";
const store = createStore({
state () {
return {
likes: [ 36, 0, 5 ],
isLikes: [false, false, false],
}
},
mutations: {
changeLikes(state, data){
state.likes[data] += (state.isLikes[data]) ? -1 : 1;
state.isLikes[data] = !state.isLikes[data]
},
LikesItemShift(state){
state.likes.unshift(0);
state.isLikes.unshift(false);
}
}
})
export default store;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
(App.vue)
<template>
<div class="header">
<h1 class="logo"><a href="#" title="vue-stagram"></a></h1>
<div class="header-button-left">
<a href="#" v-if="tab==1 || tab==2" @click="tab=0">Cancel</a>
</div>
<div class="header-button-right">
<a href="#" v-if="tab==1" @click="tab=2">Next</a>
<a href="#" v-if="tab==2" @click="publish">Write</a>
</div>
</div>
<Container :post="post" :tab="tab" :SelectFilter="SelectFilter" :uploadImage="uploadImage" @write=" n => uploadText = n " />
<button @click="more();" type="button" class="btn_more" v-if="tab==0">더보기</button>
<div class="footer">
<div class="file_wrap" v-if="tab==0">
<input type="file" id="file" class="inputfile" accept="image/*" multiple @change="upload">
<label for="file" class="input-plus" title="이미지 업로드"></label>
</div>
</div>
</template>
<script>
import post from './assets/data.js'
import Container from './components/Container.vue'
import axios from 'axios'
export default {
name:'App',
data(){
return {
post : post,
get: 0,
tab: 0,
uploadImage: '',
uploadText: '',
SelectFilter: '',
}
},
methods: {
publish(){
const newPost = {
name: "aluvy",
userImage: "./img/profile1.jpg",
postImage: this.uploadImage,
likes: 0,
date: "May 15",
liked: false,
content: this.uploadText,
filter: this.SelectFilter,
};
this.post.unshift(newPost);
this.tab = 0;
this.$store.commit('LikesItemShift');
},
upload(e){
const file = e.target.files; // 업로드한 파일이 담겨있음
const type = "image";
if( file[0].type.indexOf(type) == -1 ){ // 문자열이 존재하지 않으면 -1 리턴
alert("이미지만 업로드 해주세요.");
return;
}
const url = URL.createObjectURL(file[0]); // 업로드한 파일의 임시 URL
this.tab = 1;
this.uploadImage = url;
},
more(){
if( this.get > 1 ){
const btn_more = document.querySelector(".btn_more");
const p = document.createElement("p");
p.innerText = "게시물이 없습니다.";
p.classList.add("no_post");
btn_more.after(p);
btn_more.remove();
return;
}
axios.get(`https://codingapple1.github.io/vue/more${this.get}.json`)
.then( result => {
this.post.push(result.data);
this.get++;
})
.catch( error =>{
// 요청 실패 시
console.log(error);
})
}
},
components:{
Container,
},
mounted(){
this.emitter.on('FilterName', (a)=>{
this.SelectFilter = a;
console.log(this.SelectFilter);
});
}
}
</script>
This post is licensed under CC BY 4.0 by the author.