https://github.com/loy124/Vue/tree/master/틱택토
일일히 props에 데이터를 넘겨주는 방식에 굉장한 불편함이 따르기때문에
props로 값을 넘겨주는 방식 + Vue 자체에서 $root 를 활용하여 최상단의 데이터값을 가져올수 있는 방식이 활용되었다
root쪽
Tictactoe.vue
:table-data (v-bind:table-data) 를 활용하여
tableData의 값을 자식 컴퍼넌트 table-component에 넘겨준다
<template>
<div>
<div>{{ turn }}님의 턴입니다.</div>
<table-component :table-data="tableData"></table-component>
<div v-if="winner">{{ winner }}님의 승리!</div>
</div>
</template>
<script>
import Vue from 'vue';
import TableComponent from './TableComponent';
export default {
components: {
TableComponent,
},
data() {
return {
tableData: [
['', '', ''],
['', '', ''],
['', '', ''],
],
turn: 'O',
winner: '',
};
},
methods: {
//뷰에서 객체나 배열이 있고 내부의값을 인덱스로 변경하면 화면에 적용되지 않는다
//객체로 key값을 바꾸는경우도 마찬가지
// //push등으로 사용하면 적용이 된다
// onChangeData(){
// this.tableData[0][1] = 'O';
// }
onChangeData() {
//this.tableData[1][0] = 'X' 작동하지 않는다
//Vue를 import하고 바꾸고싶은 값을 Vue.set을 사용한다
// this.tableData[1][0]에 'X'를 넣는다
// Vue.set(this.tableData[1], 0, 'X');
//Vue를 import 안하더라도 해당 방식으로 해결가능하다
// this.$set(this.tableData[1], 0, 'X');
},
},
computed: {},
mounted() {},
beforeDestroy() {},
};
</script>
<style scoped></style>
TableComponent.vue
props로 tableData를 전달받고 해당 tableData를 각각 rowData, index로 나누어서 tr-component에
:row-data, :row-index 로 값을 넘겨준다
<template>
<table>
<tr-component
v-for="(rowData, index) in tableData"
:key="index"
:row-data="rowData"
:row-index="index"
></tr-component>
</table>
</template>
<script>
import TrComponent from './TrComponent';
export default {
components: {
TrComponent,
},
props: {
tableData: Array,
},
};
</script>
<style>
table {
border-collapse: collapse;
}
td {
border: 1px solid black;
width: 40px;
height: 40px;
text-align: center;
}
</style>
TrComponent.vue
row-data, :row-index 를 통해 rowData rowIndex를 넘겨받고
rowData는 ["", "", ""] 식의 배열로 구성되어있기 때문에
이를 또 cellData와 cellIndex로 나누어서 td컴포넌트에 넘겨준다
<template>
<tr>
<td-component
v-for="(cellData, index) in rowData"
:key="index"
:cell-data="cellData"
:cell-index="index"
:row-index="rowIndex"
></td-component>
</tr>
</template>
<script>
import TdComponent from './TdComponent';
export default {
components: {
TdComponent,
},
data() {
return {
parent: '부모',
};
},
props: {
rowData: Array,
rowIndex: Number,
},
};
</script>
<style></style>
TdComponent.vue
넘겨받은 cellData를 활용해서 받아온다
이곳에서 O X 표시를 나타내줘야 하는데
정상적으로 나타나지 않게된다
javascript및 vue의 한계로써
배열로된 index값을 통해 값을 바꿔주면 정상적으로 화면이 바뀌지 않는다
따라서 Vue.set 혹은 $set을 활용하여 새로 그려주는 작업이 필요하다
<template>
<td @click="onClickTd">{{ cellData }}</td>
</template>
<script>
export default {
props: {
cellData: String,
rowIndex: Number,
cellIndex: Number,
},
methods: {
onClickTd() {
//root값의 데이터를 가져온다
// console.log(this.$root.$data);
//부모의 데이터를 가져온다
// console.log(this.$parent.$data);
//자식 컴포넌트에서 부모컴포넌트의 데이터를 변경할 수 있다.
//화면에서 반영이 되지 않는다
//부모의 데이터는 잘 변경이되는데 화면에는 그려지지 않는다
// this.$root.$data.tableData[this.rowIndex][
// this.cellIndex
// ] = this.$root.$data.turn;
//this.$set으로 일치화해주는 작업을 실시한다
// 또한 인덱스를 여러번 쓰는경우 마지막 index를 key로 하면 된다
if (this.cellData) return;
const rootData = this.$root.$data;
this.$set(
rootData.tableData[this.rowIndex],
this.cellIndex,
rootData.turn,
);
let win = false;
if (
rootData.tableData[this.rowIndex][0] === rootData.turn &&
rootData.tableData[this.rowIndex][1] === rootData.turn &&
rootData.tableData[this.rowIndex][2] === rootData.turn
) {
win = true;
}
if (
rootData.tableData[0][this.cellIndex] === rootData.turn &&
rootData.tableData[1][this.cellIndex] === rootData.turn &&
rootData.tableData[2][this.cellIndex] === rootData.turn
) {
win = true;
}
//대각선
if (
rootData.tableData[0][0] === rootData.turn &&
rootData.tableData[1][1] === rootData.turn &&
rootData.tableData[2][2] === rootData.turn
) {
win = true;
}
if (
rootData.tableData[0][2] === rootData.turn &&
rootData.tableData[1][1] === rootData.turn &&
rootData.tableData[2][0] === rootData.turn
) {
win = true;
}
//승리했을때
if (win) {
rootData.winner = rootData.turn;
rootData.turn = 'O';
rootData.tableData = [
['', '', ''],
['', '', ''],
['', '', ''],
];
} else {
//무승부일때
let all = true; //all이 true면 무승부
//무승부 검사
rootData.tableData.forEach(row => {
//2차원 배열이니 두번 forEach 실행
row.forEach(cell => {
// 칸이 비어있는경우면 all = false
if (!cell) {
all = false;
}
});
});
//무승부일때 값 초기화
if (all) {
rootData.winner = '';
rootData.turn = 'O';
rootData.tableData = [
['', '', ''],
['', '', ''],
['', '', ''],
];
//무승부가 아니므로 턴만 넘긴다
} else {
rootData.turn = rootData.turn === 'O' ? 'X' : 'O';
}
}
// console.log(rootData);
},
},
};
</script>
<style></style>
'Vue > vue 기초 공부하기' 카테고리의 다른 글
Vue로 틱택토만들기(Vuex) (0) | 2020.02.22 |
---|---|
Vue로 틱택토 만들기(EventBus 활용) (0) | 2020.02.22 |
로또 번호 생성 프로그램 만들기 (props, component 활용) (0) | 2020.01.26 |
Vue 가위바위보 게임 만들기 (vue-LifeCylce 활용) (0) | 2020.01.19 |
반응속도 측정 게임 만들기(v-if, v-show, computed 활용) (0) | 2020.01.12 |