【じゅもん追加】Vue.jsでドラクエ風のポートフォリオを作った話 ②

# TL;TR

* つかえるじゅもんが増えました → [ドラクエ風ポートフォリオ](https://iwathi.netlify.com/)
* GitHubは[こちら](https://github.com/iwathi/dq_portfolio)
* コンポーネントの配置はdefaultで
* コンポーネントの表示・非表示はストア経由

![スクリーンショット 2018-12-10 22.44.25.png](https://qiita-image-store.s3.amazonaws.com/0/170821/490dd10d-d5a1-c217-84f0-f035253bcbbb.png)

# はじめに

　こちらの記事は[Vue.jsでドラクエ風のポートフォリオを作った話](https://qiita.com/iwathi/items/8f054d10590f32b438a4)
の続きになります。

　思いのほか様々な人にポートフォリオを見ていただき、ドラクエの偉大さを思い知りました。
ありがとうございました！

# 前回からの追記

* じゅもんの追加、を行いました

# 今回お話する内容

* コンポーネントの宣言と配置
* リアクティブなウィンドウの表示・非表示

　下記コンポーネントをまとめているデフォルト画面と②のtheCommandコンポーネントの話です。

<img width="545" alt="各コンポーネント.png" src="https://qiita-image-store.s3.amazonaws.com/0/170821/bbd8dcea-be61-6bde-a233-dcc1713968b5.png">


## デフォルト画面の設定

　各コンポーネントの宣言と構成をしています。

### default

```vue
<template>
  <div>
    <div class="sidebar">
      <TheStatus class="status" />
      <TheCommand class="sidemenu" />
    </div>
    <div class="pages">
      <nuxt/>
    </div>
    <div class="display-components">
      <div class="comment" v-if="commentDisplay">
        <TheComment/>
      </div>
      <TheChoice class="choice" v-if="choiceDisplay" />
      <TheStrength class="window" v-if="strengthDisplay" />
      <TheStrategy class="window" v-if="strategyDisplay" />
      <TheSpell class="window" v-if="spellDisplay" />
      <TheTool class="window" v-if="toolDisplay" />
    </div>
  </div>
</template>

<script>
import TheComment from '~/components/TheComment.vue'

export default {
  components: {
    TheCommand,
  },
```

　vuexでストアした値によって表示の制御をしています。
メッセージが出ているウィンドウ枠内でのクリックやタップというイベントは、各コンポーネントで発生していて、コンポーネント自体の表示は親コンポーネントでしているので、のでvuexで親コンポーネントへ状態を伝える必要があるためこのようにしています。

```vue
  computed: {
    commentDisplay: function(){
      return this.$store.state.commentDisplay
    },
  }
}
</script>
```

　各コンポーネントの配置はCSSで定義しています。
白枠や文字等の設定は各コンポーネント毎に設定していますので、ここでは設定していません。

```vue

<style>
html {
  position: relative;
  background: black;
  color: white;
  font-family: "Source Sans Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  font-size: 16px;
  word-spacing: 1px;
}

.window {
  position: absolute;
  top: 100px;
  left: 180px;
}

.pages {
  position: absolute;
  top: 10px;
  left: 180px;
}

.comment {
  position: absolute;
  top: 340px;
  left: 180px;
}

.comment::before {
  background-color: #000;
  color: #fff;
  position: relative;
  left: 37px;
  top: 12px;
}

</style>
```

### theCommand

　コマンドは他のコンポーネントの宝箱を開けた際のイベントなどによって追加されるので、vuexの内容を表示します。
コマンドの横に出てくる「▶」はv-on:mouseoverのイベントを使ってマウスが対象のコマンドの上に来ている際にv-ifで表示をするようにしています。

```vue
<template>
  <section>
    <div class="sidemenu-list">
      <ul>
        <li v-for="(menu, index) in commandList" v-bind:key="index" v-on:mouseleave="menuMouseleave(index)" v-on:mouseover="menuMouseover(index)" v-if="menu.display == true">
          <a class="menuCursor" v-if="menuChoice==index">▶</a>
          <a v-on:click="commandStateChange(menu.commandState)">{{menu.name}}</a>
        </li>
      </ul>
    </div>
  </section>
</template>
```

　クリックした際のイベントとしてはcommandStateの値によって動作を変えるように実装しています。
この辺はすごく汚いと感じているのでキレイに書ける方法があればそのように書きたいです。

```vue

<script>
import {mapState} from 'vuex'
export default {
  components: {
  },
  data: function() {
    return {
      menuChoice: -1,
    }
  },
  methods: {
    commandStateChange: function(commandState) {
      if(commandState == 2){
        this.$store.commit('setStrengthDisplay',true)
      }else if(commandState == 3){
        this.$store.commit('setStrategyDisplay',true)
      }else if(commandState == 4){
        this.$store.commit('setToolDisplay',true)
      }else if(commandState == 5){
        this.$store.commit('setSpellDisplay',true)
      }else{
      this.$store.commit('setCommentDisplay', true)
      this.$store.commit('setCommandState', commandState)
      }
    },
    menuMouseover: function(i){
      this.menuChoice = i
    },
    menuMouseleave: function(i){
      this.menuChoice = -1
    },
  },
  computed: {
    commandList: function(){
      return this.$store.state.commandList
    },
    toolCommand: function(){
      return this.$store.state.toolCommand
    },
    spellCommand: function(){
      return this.$store.state.spellCommand
    },
  }
}
</script>
```

　theCommandのコンポーネントで白枠などを指定しています。
a:linkやa:visitedのCSSのところで
```
text-decoration: none;
color: white;
```
とすることでリンク自体の色やクリックした後の色を無効化し白を維持させています。

```vue

<style scoped>
.menuCursor {
  text-align: left;
}
.sidemenu-list {
  text-align: center;
  width: 130px;
  height: 270px;
  padding:10px;
  margin-bottom:10px;
  border: 2px solid #fff;
  border-radius: 10px;
}
a:link {
  text-decoration: none;
  color: white;
}
a:visited {
  text-decoration: none;
  color: white;
}
</style>

```


# まとめ
* つかえるじゅもんが増えました → [ドラクエ風ポートフォリオ](https://iwathi.netlify.com/)
* GitHubは[こちら](https://github.com/iwathi/dq_portfolio)
* コンポーネントの配置はdefaultで
* コンポーネントの表示・非表示はストア経由