럿고의 개발 노트

[인프런] 웹 게임을 만들며 배우는 Vue 6. 로또 추점기 본문

Vue.js Note/[인프런] 웹 게임을 만들며 배우는 Vue(동영상 강의)

[인프런] 웹 게임을 만들며 배우는 Vue 6. 로또 추점기

KimSeYun 2019. 11. 14. 12:26

[인프런] 웹 게임을 만들며 배우는 Vue

6. 로또 추첨기

6.1. vue 스타일 가이드

https://kr.vuejs.org/v2/style-guide/

6.2. 자식 컴포넌트와 props

6.3. 로또 추첨기 구현하기

6.4. watch 사용해보기

- watch는 왠만하면 사용하지 말것! 무한반복의 굴레에 들어갈수도 있음.

- 예제(웹 게임)을 통해 Vue를 만나는 시간으로, 예제를 풀면서 주석으로 배운 내용과 알아야 할 내용을 최대한 적어 놓았습니다. 코드와 주석을 참고해주세요!. 노드와 웹팩을 사용하여 설정파일들이 존재합니다. 아래 깃허브를 참고해주세요.

[main.js]


1
2
3
4
import Vue from 'vue';
import LottoGenerator from './LottoGenerator';
 
new Vue(LottoGenerator).$mount('#root');
cs


[package.json]

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
{
  "name""lotto-generator",
  "version""1.0.0",
  "description""",
  "main""index.js",
  "scripts": {
    "bulid""webpack --watch",
    "dev""webpack-dev-server --hot"
  },
  "author""",
  "license""ISC",
  "dependencies": {
    "vue""^2.6.10",
    "vue-loader""^15.7.2",
    "vue-template-compiler""^2.6.10",
    "webpack""^4.41.2",
    "webpack-cli""^3.3.10"
  },
  "devDependencies": {
    "css-loader""^3.2.0",
    "vue-style-loader""^4.1.2",
    "webpack-dev-server""^3.9.0"
  }
}
 
cs


[webpack.config.js]


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
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const path = require('path'); // 경로 불러오는 것
 
module.exports = { // 노드에 모듈을 만듬, 이안에 웹팩 모든 설정을 넣으면 됨.
    mode:'development'// 배포할건지 개발한건지
    devtool: 'eval'// 개발할때는 eval, 배포할때는 hid,den-source-map
    resolve: {
        extensions: ['.js''.vue'], // 이걸 하면 import할때 확장자를 넣어줄 필요가 없다.
    },
    entry: { // 스크립트를 모인것 중에서 대표적인 스크립트
        app : path.join(__dirname, 'main.js'), // app은 하나로 합친 스크립트 이름
    },
    module: { // 웹팩의 핵심 // entry로 처리하다가 이상한거 나오면 loader를 실행
        rules: [{ // 합칠때 어떻게 합칠지를 설정해주는 것
            test: /\.vue$/// .vue로 끝나는 파일은 vue-loader를 사용하겠다, 정규표현식
            loader: 'vue-loader'// npm i vue-loader
        },{
            test: /\.css$/
            use: [ // loader와 user는 똑같은 기능
                'vue-style-loader',
                'css-loader',
            ]
        }],
    },
    plugins: [
        new VueLoaderPlugin(),
    ],
    output: {
        filename: '[name].js'// 출력할 파일 이름(최종결과)
        path: path.join(__dirname, 'dist'), // 폴더 경로
        publicPath: '/dist'// webpack-dev-server 세팅시 필요
    },
};
 
// entry, module, plugins, output이 주 설정 나머지는 부가적인 설정
cs


[LottoGenerator.html]


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>로또생성기</title>
</head>
<body>
    <!-- 컴포넌트 여러개 만드는것 
        watch기능
        vue.js 공식문서 스타일 가이드에서 필수는 꼭 지켜주는 것을 추천함
        (규칙 A,B는 왠만하면 지켜야함!)
        그리고 v-for에는 :key를 같이 붙여줘야함. 
        컴포넌트 이름은 무조건 2단어 이상으로 하는 것을 추천
    -->
    <div id="root"></div>
    <script src ="dist/app.js"></script>
</body>
</html>
cs


[LottoGenerator.vue]


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
<template>
<div>
    <div>당첨 숫자</div>
    <div id  = "결과창">
        <lotto-ball v-for="ball in winBalls" :key="ball" :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() {
    const candidate = Array(45).fill().map((v, i) => i + 1); // fill(배열의 시작 인덱스부터 끝 인덱스까지 이전까지 정적인 값 하나로 채움
    const shuffle = [];
    while (candidate.length > 0) {
      shuffle.push(candidate.splice(Math.floor(Math.random() * candidate.length), 1)[0]);
    }
    const bonusNumber = shuffle[shuffle.length - 1];
    const winNumbers = shuffle.slice(06).sort((p, c) => p - c);
    return [...winNumbers, bonusNumber];
  }
 
const timeouts = [];
 
export default {
components:{
    LottoBall,
},
 data(){
     return{
         winNumbers: getWinNumbers(), // 처음에 7개를 다 뽑아내는 것
         winBalls: [], // WinNnmbers에 있는 값을 하나씩 추가해서, 시각적인 모습을 보여주기 위해
         bonus: null,
         redo: false,
     };
 },
 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);
     })
 },
};
</script>
 
<style scoped> 
 
</style>
cs


[LottoBall.vue]


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
<template>
    <div class="ball" :style="stlyeObject">{{number}}</div>
</template>
 
<script>
export default {
    name'LottoBall',
    props: { // LottoGenerator컴포넌트가 LottoBall 컴포넌트를 사용하면 부모자식관계가 생기는데, 부모가 자식에게 데이터를 줄수 있는데, 그 역할을 하는 것이 props
    //대신 props는 자식이 데이터를 변경할수 없다. readonly라고 생각하면 됨.
    number: Number,
    },
    computed: {
        stlyeObject(){
        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 scoped>
    .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>
cs


깃허브 주소

https://github.com/ksy90101/Vue.js/tree/master/vue-Webgame-inflearn/Chapter06




출처

https://www.inflearn.com/course/web-game-vue/dashboard

Comments