build out Vuex Mutations and Actions for our EventList & EventShow pages, and even implement some pagination.
EventList 및 EventShow 페이지에 대한 Vuex Mutations 및 Action을 구축하고 일부 페이지 매김도 구현합니다.
Problem: Loading our EventList using Vuex
The first step to making this component use Vuex is to create a new Mutation and an Action.
이 컴포넌트에서 Vuex를 사용하도록 만드는 첫 번째 단계는 새로운 Mutation과 Action을 생성하는 것입니다.
We want this component to properly use Vuex to retrieve and display events.
이 구성 요소가 Vuex를 올바르게 사용하여 이벤트를 검색하고 표시하기를 원합니다.
Solution
/store.js
SET_EVENTS Mutation sets all the events, and our fetchEvents action simply calls our EventService and then calls our Mutation.
SET_EVENTS Mutation은 모든 이벤트를 설정하고 fetchEvents 작업은 단순히 EventService를 호출한 다음 Mutation을 호출합니다.
state: {
...
events: [] // already exists
}
mutations: {
...
SET_EVENTS(state, events) {
state.events = events
}
},
actions: {
...
fetchEvents({ commit }) {
EventService.getEvents()
.then(response => {
commit('SET_EVENTS', response.data)
})
.catch(error => {
console.log('There was an error:', error.response)
})
}
}
/views/EventList.vue
Imported the mapState helper, and removed the line that imported EventService.
mapState helper를 가져오고 EventService를 가져온 줄을 제거했습니다.
created() {
EventService.getEvents()
.then(response => {
this.events = response.data
})
.catch(error => {
console.log('There was an error:', error.response)
})
}
우의 code 가 다음과 같이 pagination 까지 지원하여 다음과 같이 action 을 호출하는 방식으로 변경이된다
created() {
this.perPage = 3 // Setting perPage here and not in data means it won't be reactive.
// We don't need it to be reactive, and this way our component has access to it.
this.$store.dispatch('fetchEvents', {
perPage: this.perPage,
page: this.page
})
},
Removed our data option, and our created lifecycle hook simply calls our new Action.
아래와 간은 data 옵션을 제거하고 생성된 수명 주기 후크는 단순히 새 action을 호출하는 것으로 변경이된다.
data() {
return {
events: []
}
},
note) code 를 simple 하게 작성할 수 있다
<script>
import EventCard from '@/components/EventCard.vue'
import { mapState } from 'vuex'
export default {
components: {
EventCard
},
created() {
this.$store.dispatch('fetchEvents')
},
computed: mapState(['events'])
}
</script>
Problem: Pagination
We might have thousands of events and we probably shouldn’t fetch all of them at once.
수천 개의 이벤트가 있을 수 있으며 모든 이벤트를 한 번에 가져오면 안 됩니다.
Instead, we need to paginate like Google search results.
대신 Google 검색결과처럼 페이지를 매겨야 합니다.
JSON-SERVR 에서 지원하는 pagination 관련 build-in API 는 아래와 같다.
GitHub - typicode/json-server: Get a full fake REST API with zero coding in less than 30 seconds (seriously)
Get a full fake REST API with zero coding in less than 30 seconds (seriously) - GitHub - typicode/json-server: Get a full fake REST API with zero coding in less than 30 seconds (seriously)
github.com
paramters
_limit : limit the number of items we show on a page : 페이지에 표시되는 항목 수를 제한한다.
_page : give us the data on our paticular page : 특정 페이지의 데이터를 알려준다.
examples : /events?_limit=3&_page=2 : 이 API는 page 당 3개의 event를 return 하고, page2 에 list up 할 event 를 전달헤 준다
Solution
some chages need to be made
/services/EventService.js
getEvents(perPage, page) {
return apiClient.get('/events?_limit=' + perPage +
'&_page=' + page)
},
/store.js
we need to check if we already have this particular event in our events State array by calling it from inside our fetchEvent action in store.js.
store.js의 fetchEvent 액션 내에서 이를 호출하여 이벤트 State 배열에 이 특정 이벤트가 이미 있는지 확인해야 합니다.
We call our getters.getEventById(id) with the id of the event we want to display. If it is found, we commit a Mutation, otherwise we go ahead and get that single event from the API.
표시하려는 이벤트의 ID를 사용하여 getters.getEventById(id)를 호출합니다. 발견되면 Mutation을 커밋하고, 그렇지 않으면 API에서 해당 단일 이벤트를 가져옵니다.
...
actions: {
....
fetchEvent({ commit, getters }, id) { // Send in the getters
var event = getters.getEventById(id) // See if we already have this event
if (event) { // If we do, set the event
commit('SET_EVENT', event)
} else { // If not, get it with the API.
EventService.getEvent(id)
.then(response => {
commit('SET_EVENT', response.data)
})
.catch(error => {
console.log('There was an error:', error.response)
})
}
}
},
getters: {
getEventById: state => id => {
return state.events.find(event => event.id === id)
}
}
/views/EventList.vue
using ES2015 argument destructuring to pull out { perPage, page }
ES2015 argument destructuring를 사용하여 { perPage, page } 꺼낸다.
This is because the second argument with both mutations and actions is effectively a payload . The payload in both Actions and Mutations can be a single variable or a single object.
이는 두 번째 인수가 mutations 와 actions 는 사실상 페이로드입니다. Action과 Mutation의 페이로드는 단일 변수 또는 단일 개체입니다.
<script>
import EventCard from '@/components/EventCard.vue'
import { mapState } from 'vuex'
export default {
components: {
EventCard
},
created() {
this.perPage = 3 // Setting perPage here and not in data means it won't be reactive.
// We don't need it to be reactive, and this way our component has access to it.
this.$store.dispatch('fetchEvents', {
perPage: this.perPage,
page: this.page
})
},
computed: {
page() {
return parseInt(this.$route.query.page) || 1
},
hasNextPage() {
return this.eventsTotal > this.page * this.perPage
},
...mapState(['events', 'eventsTotal'])
}
}
</script>
Problem: The Component isn’t reloading
when we use the link to go to page two, nothing changes. But if we refresh, it does work.
문제점은 링크를 사용하여 두 번째 페이지로 이동해도 아무 변화가 없습니다. 하지만 새로 고치면 작동합니다.
You want to reload a component with a change of query parameters.
solution 은 쿼리 매개변수를 변경하여 구성요소를 다시 로드하는 것입니다..
Solution
- Watch the page computed property to see if it changes (which it does when we change the page), and when it does, dispatch the fetchEvent action.
- 페이지 computed 속성을 관찰하여 변경되는지 확인합니다(우리가 페이지 변경하먄 변경이됨), 변경되면 fetchEvent action을 dispatch 합니다.
- Tell our router to reload components when the full URL changes, including the query parameters.
- 쿼리 매개변수를 포함하여 전체 URL이 변경되면 components를 다시 로드하도록 라우터에 지시합니다.
/App.vue
아래와 깉이 :key="$route.fullPath" 를 추가함
<template>
<div id="app">
<NavBar/>
<router-view :key="$route.fullPath"/>
</div>
</template>
Extra Credit
문제점은 “Next Page” link doesn’t disappear when we reach the last page.
해결책은 It would be easy if we knew how many events we have total.
json-server is actually giving us this data on each event request listing as a header.,
toal event 갯수를 header 에 실어 보내는 것을 이용하여 해결함.
EventList.vue to see if eventsTotal > (this.page * 3) . If this is true, we have a next page.
EventList.vue 를 사용하여 eventsTotal > (this.page * 3) 인지 확인하고. 이것이 사실이라면 다음 페이지가 있는 것입니다.
/store.js
fetchEvents({ commit }, { perPage, page }) {
EventService.getEvents(perPage, page)
.then(response => {
console.log('Total events are ' +
response.headers['x-total-count'])
commit('SET_EVENTS', response.data)
})
Problem: Implementing the Show Event Page
When a user clicks on an event to get to the ShowEvent page, what do we do inside Vuex?
사용자가 이벤트를 클릭하여 ShowEvent 페이지로 이동하면 Vuex 내에서 무엇을 합니까?
Solution
Adding a new object to our State called event to store the event that is currently being viewed.
현재 보고 있는 이벤트를 저장하기 위해 이벤트라는 새 객체를 State에 추가합니다.
/store.js
fetchEvent({ commit }, id) {
var event = getters.getEventById(id)
if (event) {
commit('SET_EVENT', event)
} else {
EventService.getEvent(id)
.then(response => {
commit('SET_EVENT', response.data)
})
.catch(error => {
console.log('There was an error:', error.response)
})
}
}
},
/views/EventShow.vue
<script>
import { mapState } from 'vuex'
export default {
props: ['id'],
created() {
this.$store.dispatch('fetchEvent', this.id)
},
computed: mapState(['event'])
}
Problem: We’re Loading Data Twice
it seems wasteful to do another call to the API, when we already have the data needed in hand.
필요한 데이터가 이미 확보되어 있는데 API를 다시 호출하는 것은 낭비인 것 같습니다.
Solution
When we get to the ShowEvent page, we need to check if we already have this particular event in our events
ShowEvent 페이지에 도달하면 이벤트에 이 특정 이벤트가 이미 있는지 확인해야 합니다.
/store.js
fetchEvent({ commit, getters }, id) { // Send in the getters
var event = getters.getEventById(id) // See if we already have this event
if (event) { // If we do, set the event
commit('SET_EVENT', event)
} else { // If not, get it with the API.
EventService.getEvent(id)
.then(response => {
commit('SET_EVENT', response.data)
})
.catch(error => {
console.log('There was an error:', error.response)
})
}
}
},
getters: {
getEventById: state => id => {
return state.events.find(event => event.id === id)
}
}
Summary
- How to fetch a list of events and a single event with Vuex.
- Vuex를 사용하여 이벤트 목록과 단일 이벤트를 가져오는 방법.
- How to paginate with Vuex.
- Vuex로 페이지를 매기는 방법.
- How to use query parameters on our router, and ensure our components are reloaded when they change.
- 라우터에서 쿼리 매개변수를 사용하는 방법과 components 가 변경될 때 다시 로드되는지 확인한다.
- How to optimize our Vuex State so we’re not reloading data twice.
- 데이터를 두 번 다시 로드하지 않도록 Vuex 상태를 최적화하는 방법.
Resources
https://github.com/Code-Pop/real-world-vue/releases/tag/lesson13-mutations%26actions2-finish
Release lesson13-mutations&actions2-finish · Code-Pop/real-world-vue
Now using the local property
github.com
https://github.com/Code-Pop/real-world-vue/releases/tag/lesson-13-extra-credit-finish
Release lesson-13-extra-credit-finish · Code-Pop/real-world-vue
Now using the local property
github.com
'Java Scripts > Vue.js' 카테고리의 다른 글
Vue : Flash Messages (0) | 2022.05.01 |
---|---|
Vue : Programmatic Navigation (0) | 2022.04.30 |
Vuex - Mutation & Action - 1 (0) | 2022.04.18 |
Vue MultiSelect (0) | 2022.04.09 |
Vue 3 -Teleport (0) | 2022.03.22 |