본문 바로가기

Vue/vue 기초 공부하기

로또 번호 생성 프로그램 만들기 (props, component 활용)

https://github.com/loy124/Vue/tree/master/로또

 

loy124/Vue

Vue 공부. Contribute to loy124/Vue development by creating an account on GitHub.

github.com

 

props는 부모컴포넌트에서 자식 컴포넌트에 값을 전달할때 사용한다

v-bind:number(어트리뷰트)를 넘겨준다 

자식컴포넌트에 넘겨주면

props: ['number'] 혹은

props:{

number : Number(자료형 설정, Boolean 등등)

}

 

LottoGenerator.vue

<template>
  <div>
    <div>당첨 숫자</div>
    <div id="결과창">
      <lotto-ball
        v-for="ball in winBalls"
        :key="ball"
        v-bind:number="ball"
      ></lotto-ball>
    </div>
    <div>보너스</div>
    <lotto-ball v-if="bonus" :number="bonus"></lotto-ball>
    <button v-if="redo" @click="onClickRedo">한번 더!</button>
  </div>
</template>

<script>
import LottoBall from './LottoBall';

function getWinNumbers() {
  console.log('getWinNumbers');
  const candidate = Array(45)
    .fill()
    .map((v, i) => i + 1);

  const shuffle = [];
  while (candidate.length > 0) {
    //splice는 배열을 하나씩 빼주면서 랜덤으로 채운것들을 하나씩 뽑아서 shuffle에 넣어준다
    shuffle.push(
      candidate.splice(Math.floor(Math.random() * candidate.length), 1)[0],
    );
    // console.log(candidate);
    // console.log(shuffle);
  }
  //맨 마지막 번호는 보너스 번호
  const bonusNumber = shuffle[shuffle.length - 1];

  //정답 번호를 앞에서부터 6개를 뽑은 후 오름차순 정리 한다
  // c - p 일 경우 내림차순
  const winNumbers = shuffle.slice(0, 6).sort((p, c) => p - c);

  // 승리한 번호의 배열(spread) 과 보너스 번호를 한 배열로 리턴해준다
  return [...winNumbers, bonusNumber];
}

const timeouts = [];
export default {
  components: {
    // 'lotto-ball': LottoBall,
    //뷰에서 PascalCase는 자동으로 kebab-case 로 바꿔준다
    LottoBall,
  },
  data() {
    return {
      winNumbers: getWinNumbers(),
      //하나씩 1초마다 winBalls 에 넣어준다 winBalls는 시각적인 용도
      winBalls: [],
      bonus: null,
      redo: false,
    };
  },

  computed: {},
  methods: {
    onClickRedo() {
      this.winNumbers = getWinNumbers();
      this.winBalls = [];
      this.bonus = null;
      this.redo = false;
      this.showBalls();
    },
    showBalls() {
      //먼저 보너스를 제외한 공을 뽑는다
      for (let i = 0; i < this.winNumbers.length - 1; i++) {
        timeouts[i] = setTimeout(() => {
          this.winBalls.push(this.winNumbers[i]);
        }, (i + 1) * 1000);
      }
      timeouts[6] = setTimeout(() => {
        this.bonus = this.winNumbers[6];
        this.redo = true;
      }, 7000);
    },
  },
  mounted() {
    this.showBalls();
  },
  beforeDestroy() {
    timeouts.forEach(t => clearTimeout(t));
  },
  // 어떤 값이 바뀌었는지 안바뀌었는지 감시하는 기능
  // 자주쓰면 좋지 않다
  // watch: {
  //   // bonus(value, oldvalue) {
  //   //   if (value === null) {
  //   //     console.log(value, oldvalue);
  //   //     this.showBalls();
  //   //   }
  //   // },
  //   redo(value, oldvalue) {
  //     if (value === false) {
  //       console.log(value, oldvalue);
  //       this.showBalls();
  //     }
  //   },
  // },
};
</script>

<style scoped></style>

 

뷰쪽을 담당하는 LottoBall.vue

 

<template>
  <div class="ball" :style="styleObject">{{ number }}</div>
</template>

<script>
export default {
  name: 'LottoBall',
  // props: {
  //   number: Number,
  // },
  // props: ['number'],
  props: {
    number: Number, //자료형을 설정해준다
  },

  computed: {
    styleObject() {
      let background;
      if (this.number <= 10) {
        background = 'red';
      } else if (this.number <= 20) {
        background = 'orange';
      } else if (this.number <= 30) {
        background = 'yellow';
      } else if (this.number <= 40) {
        background = 'blue';
      } else {
        background = 'green';
      }
      return {
        background,
      };
    },
  },
  //프롭스로 받은 것을 바꾸는것은 금지되어있다.(읽기 전용)
};
</script>

<style>
.ball {
  display: inline-block;
  border: 1px solid black;
  border-radius: 20px;
  width: 40px;
  height: 40px;
  line-height: 40px;
  font-size: 20px;
  text-align: center;
  margin-right: 20px;
}
</style>