이번 시간에는 About페이지를 작업해보도록 하겠습니다.
About.vue
의 페이지의 template내용을 수정해줄 것이며, About페이지에서 사용할 데이터를 about.js파일에 세팅 해 줄 것입니다.
export default {
namespaced: true,
state: () => ({
name: '0seo8',
email: '0seo8@naver.com',
blog: 'https://velog.io/@0seo8',
phone: '+82-10-1234-5678',
image: '~/assets/0seo.jpg',
})
}
이렇게 작성한 데이터를 About.vue에서 활용할 수 있도록 코드를 작성해줍니다.
<template>
<div class="about">
<div class="photo">
<img
:src="image"
:alt="name" />
</div>
<div class="name">
{{ name }}
</div>
<div>{{ email }}</div>
<div>{{ blog }}</div>
<div>{{ phone }}</div>
</div>
</template>
<script>
export default {
computed: {
image() {
return this.$store.state.about.image
}
name() {
return this.$store.state.about.name
},
email() {
return this.$store.state.about.email
},
blog() {
return this.$store.state.about.blog
},
phone() {
return this.$store.state.about.phone
}
}
}
</script>
computed에 작성한 내용은 추후 Vuex의 Helper기능을 이용해 간소화시켜볼 예정입니다.
아울러 현재 about페이지에서도 이미지를 불러오기 전 로딩애니메이션이 작동하도록 작성해보도록 하겠습니다.
data() {
return {
imageLoading: true,
}
},
...
mounted() {
this.init()
},
methods: {
async init() {
await this.$loadImage(this.image)
this.imageLoading = false
}
}
처음 데이터가 만들어질 때는 true이지만 이미지를 잘 불러온 후에는 false로 바뀌게 됩니다.
그리고 메소드 부분에는 this.$loadImage
라는 이전에 만들어놓았던 메소드를 실행하는데 그 인수로는 이미지 경로에 해당하는 데이터를 넣어줍니다.
마지막으로 생성된 메소드가 컴포넌트가 화면에 연결이 된 다음에 실행될 수 있도록 작업해줍니다.
✅주의
created(), mounted() 함수에서는 비동기를 동작시킬 수가 없습니다. 따라서 mounted앞에는 async를 붙이지 않고 별도에 메소드를 만들어 비동기로 처리한 함수를 마운트에서 실행해줍니다.
전체 코드
<template>
<div class="about">
<div class="photo">
<Loader
v-if="imageLoading"✅
absolute />
<img
:src="image"
:alt="name" />
</div>
<div class="name">
{{ name }}
</div>
<div>{{ email }}</div>
<div>{{ blog }}</div>
<div>{{ phone }}</div>
</div>
</template>
<script>
import Loader from '~/components/Loader'✅
export default {
components: {✅
Loader
},
data() {
return {
imageLoading: true,✅
}
},
computed: {
image() {
return this.$store.state.about.image
},
name() {
return this.$store.state.about.name
},
email() {
return this.$store.state.about.email
},
blog() {
return this.$store.state.about.blog
},
phone() {
return this.$store.state.about.phone
}
},
mounted() {✅
this.init()
},
methods: {
async init() {
await this.$loadImage(this.image)
this.imageLoading = false
}
}
}
</script>
<style lang="scss" scoped>
@import "~/scss/main";
.about {
text-align: center;
.photo {
width: 250px;
height: 250px;
margin: 40px auto 20px;
padding: 30px;
border: 10px solid $gray-300;
border-radius: 50%;
box-sizing: border-box;
background-color: $gray-200;
position: relative; ✅
img {
width: 100%;
border-radius: 50%;
}
}
.name {
font-size: 40px;
font-family: "Oswald", snas-serif;
margin-bottom: 20px;
}
}
</style>