(Vue.js) 버튼이벤트를 통해 새로운 이미지를 생성하는 법

Cho Dragoo·2021년 7월 20일
0

Vue.js 소소한 꿀 팁

목록 보기
3/3

문제가 생긴 지점

src\views\randomPhotoGenerator.vue

<template>
  <div>
    <div class="button_container">
      <button class="randomDog btnStyle">개 사진 생성버튼</button>
      <button class="randomFox btnStyle">
        여우 사진 생성버튼
      </button>
      <button class="randomCat btnStyle" @click="createdCatImg">
        고양이 사진 생성버튼
      </button>
    </div>
    <div class="image_posted" v-for="Img in catImgs" :key="Img.id">
      {{ Img }}
    </div>
  </div>
</template>

<script>
import { fetchCatsInfo } from "../api/index.js";
export default {
  data() {
    return {
      Imgs: this.image,
      catImgs: [],
    };
  },
  created() {
    this.$store.dispatch("FETCH_CATS_INFO");
  },
  mounted() {},
  methods: {
    createdCatImg() {
      fetchCatsInfo()
        .then((res) => {
          let image = new Image(300);
          image.src = res.data.file;
          this.catImgs.push(this.Imgs);
        })
        .catch((error) => {
          console.log(error);
        });
    },
  },
};
</script>

<style></style>

본래 구상했던 건 고양이 생성 버튼을 클릭하면 methods에서 존재하는 createdCatImg함수가 실행, 이 함수에서는 이미지 객체 생성하고 API에서 파싱된 이미지 주소를 이 이미지 객체에 대입, 대입 된 Imgs<template> 구간에서 “Mustache” 구문(이중 중괄호)에 적용되어 브라우저에 이미지를 표시 하는 것 이였다.

하지만 당연하게도 작동은 전혀 없었고 별로 도움이 되지 않는 오류만 나왔다.



서버를 작동 하자마자 브라우저에 파싱된 이미지를 생성되는 작업은 무난했지만

이번 경우는 처음 실행하는 작업이 아닌 버튼을 눌러서 하나의 이미지만 불러오는 로직이라 많이 까다로웠다.




문제정리

아직 Vue.js에 대한 이해가 부족한 탓이지만 여하튼 해결해야 하는 점을 먼저 정리해야 한다.


1. 이미지 객체를 Vue에서 생성하는 법
2. API에서 파싱한 이미지 주소를 img테그 src에 전달하는 법


이 점을 해결하기 위해 여러가지로 구글링한 결과 참고할 예시가 있었다.



[Vue.js] 이미지 경로를 변수, data 값, URL로 이미지 연결하는 방법 (require이용)



여기서 확실히 참고가 된 것은 :src="${변수}"였다.

data() 내부를 참조해 변수와 이름이 같은 벨류가 보이면 그 벨류의 값이 이미지 주소가 된다.

템플릿 리터럴 (Template Literals)은 순수자바스크립트에서 잘 활용했지만 Vue에서는 여기서 어떻게 활용할지 어려워 했는데 data()에서 template안으로 적용할 수 있다는 걸 이번 작업으로 확실히 알게됬다.




해결책

<template>
.
.
.

    <img
      class="image_posted"
      v-for="Img in catImgs"
      :key="Img.id"
      :src="`${Img}`"
      alt="귀여운 고양이 사진"
    />
  </div>
</template>

사진만 추가되는 것이라 img테그만 작성하고 필요한 속성을 전부 적용해도 된다.

그 다음 <script>를 살펴보면..



<script>
import { fetchCatsInfo } from "../api/index.js";

export default {
  data() {
    return {
      Img: "test",
      catImgs: [],
    };
  },
  created() {
    this.$store.dispatch("FETCH_CATS_INFO");
  },
  mounted() {},
  methods: {
    createdCatImg() {
      fetchCatsInfo()
        .then((res) => {
          this.Img = res.data.file;
          this.catImgs.push(this.Img);

          window.scrollBy(0, 1500);
        })
        .catch((error) => {
          console.log(error);
        });
    },
  },
};
</script>

본인이 순수 js에서 구현했을 때는 let image = new Image(300)코드로 이미지 객체를 생성하고 속성을 한땀한땀 적용 후 appendChild라는 메소드를 이용해 이미지를 삽입했지만

Vue에서는 이미지 객체를 따로 만들 필요 없이 v-for속성이 있는 img테그를 작성하고 버튼 이벤트로 이미지주소를 대입만하면 이미지를 가진 노드가 하나하나씩 생성된다. 그리고 this.Img, this.catImgs을 보듯이 data()함수가 인식할 수 있게 this를 빼 먹지 말고 적용해야 한다.

template에 존재하는 img테그안에 v-for 반복문이 있고 이미지 주소가 할당되지 않으면 브라우저에 생성되지 않는다. 버튼 이벤트를 일으켜 Img에 의미있는 이미지 주소가 대입 되면 비로소 브라우저에 이미지가 생성된다.




문제해결소감

이렇게 알아갈 건 알았어도 Vue.js의 노드 생성 원리가 완전히 이해되지는 않았다.

catImgs: [] 배열 속성은 보이지 않는 부모 노드의 역할이고

this.catImgs.push(this.Img)는 보이지 않는 부모 노드 내부에 Img 테그를 생성하는 자식 노드 정도의 과정이라 이해하는 걸로 우선 생각해두었다.

profile
어떤 문제든 파악 할 수 있으며 해결책을 찾을 수 있는 개발능력을 꿈꾸고 있습니다.

0개의 댓글