nuxt.jsで一文字ずつ文字列を表示する

javascript勉強中です。

ゲームとかでよくある、メッセージを一文字ずつ表示するというのを、nuxtでやってやりました。
勉強のためにクロージャを使った場合と、そうでない場合とやってやりました。

撮影したものはgifなので少し表示が遅いです。
イメージです。

![giftest.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201764/5b393100-6cde-6951-7dd6-54173ff70e0c.gif)


予め配列で表示する予定のメッセージを用意しておきます。
["aaa","bbb","ccc"]
ボタンを押すとaaaを一文字ずつ表示します。
もう一度ボタンを押すとbbbを一文字ずつ表示します。
もう一度ボタンを押すとcccを一文字ずつ表示します。

##クロージャを使った場合


```vue:index.vue
<template>
  <div class="wid-wrap">
    <div id="top-image">
      <div class="mask">
        <div class="top-text">
            <button @click="run">次へ</button>
        </div>
        <div id="text-area"></div>
      </div>
    </div>
  </div>
</template>
```

次へボタンを押すと、text-areaにメッセージを一文字ずつ表示するようにします。
ボタンを押したらrunメソッドを発火させます。


### 用意したメッセージを設定する



```vue:index.vue

<script>

export default {

  data(){
    return {
      getval : this.getTargetMsg(),
      currentMsgArray : [],
    }
  },
  
  methods:{
    getTargetMsg(){
      //表示予定の文字列を配列で準備しておく。
      let frontMsg = [
        "秒刻みのスケジュールをこなす高田健志が合間を縫って予定帳を確認したところ、今月できる呼吸の回数はわずか5回であった",
        "【その歴史教科書、正しいものですか？】 近頃、政府によって改ざんされた歴史教科書が出回っているようです。 そこで簡単な判別方法をご紹介します。 1、適当なページを開く 2、「高田健志」の名前を探す これだけです。 見つからない場合はすぐに焼き払って下さい。 それは偽りの歴史です。",
        "クリスマスの夜、プレゼントを配りにやってきた高田健志はテレパスで少年の望むものを読み取ると、靴下に体をねじ込んだ"
        ]
    
        //クロージャを使って値を設定する
        return function(){
          //準備した文字がなくなったら何もしない
          if(frontMsg.length === 0)
            return false;
        
          //一つ取得
          let current = frontMsg.slice(0,1);
          //一つ削除
          frontMsg = frontMsg.slice(1);
          //配列を文字列で返す
          return current[0]
      }
    },
  },
}
</script>

```
["aaa","bbbb","cccc"]とあったとして
getval()を呼び出す度に、順番に中身が取れるようにしています。
今回は勉強も兼ねてクロージャを使いました。

### メッセージを一文字ずつ表示する

```vue:index.vue

<script>

export default {

  data(){
    return {
      getval : this.getTargetMsg(),
      currentMsgArray : [],
    }
  },
  
  methods:{
    run(){
      //一度テキスト表示エリアを空にする
      document.getElementById('text-area').innerHTML = ""
      //表示するメッセージを取得する
      const currentArray = this.getval()
      //メッセージを一文字ずつ分解して配列に入れる。
      this.currentMsgArray = Array.from(currentArray)
      //メッセージを一文字ずつ表示する
      this.printChar()
    },

    printChar(){
      
      console.log("called!")
      //全部取り出したら何もしない。
      if(this.currentMsgArray.length === 0)
        return
      //表示する文字を取得する
      let currentChar = this.currentMsgArray.slice(0, 1)
      //表示エリアに取得した文字を追加する
      document.getElementById('text-area').innerHTML += currentChar
      //配列の先頭を削除する。(もう表示したので)
      this.currentMsgArray = this.currentMsgArray.slice(1)
      //50後にもう一度このメソッドを呼び出す。
      setTimeout(this.printChar,50)
    },

      getTargetMsg(){
        ...省略
     },

  },
}
</script>

```

runメソッドでは、先ほど用意したメッセージから、表示する文字列を取得して
それを一文字ずつ配列の要素として入れておきます。
printCharメソッドはsetTimeoutによって、runメソッドにて準備した配列から要素を一つずつとりだして、text-areaに表示しています。


##　クロージャを使わない場合

```vue:index.vue
<script>

  data(){
    return {
      getval : this.getTargetMsg(),
      currentMsgArray : [],
      frontMsg:[
        "秒刻みのスケジュールをこなす高田健志が合間を縫って予定帳を確認したところ、今月できる呼吸の回数はわずか5回であった",
        "【その歴史教科書、正しいものですか？】 近頃、政府によって改ざんされた歴史教科書が出回っているようです。 そこで簡単な判別方法をご紹介します。 1、適当なページを開く 2、「高田健志」の名前を探す これだけです。 見つからない場合はすぐに焼き払って下さい。 それは偽りの歴史です。",
        "クリスマスの夜、プレゼントを配りにやってきた高田健志はテレパスで少年の望むものを読み取ると、靴下に体をねじ込んだ"
        ],
    }
  },
  
  methods:{

    run(){
      //一度テキスト表示エリアを空にする
      document.getElementById('text-area').innerHTML = ""
      //メッセージ一覧から取得する
      if(this.frontMsg.length === 0)
        return
      const currentTarget = this.frontMsg.slice(0,1)
      //メッセージ一覧を一つ削除する
      this.frontMsg = this.frontMsg.slice(1)
      //メッセージを一文字ずつ分解して配列に入れる。
      this.currentMsgArray = Array.from(currentTarget[0])
      //メッセージを一文字ずつ表示する
      this.printChar()
    },
    printChar(){
      
      console.log("called!")
      //全部取り出したら何もしない。
      if(this.currentMsgArray.length === 0)
        return
      //表示する文字を取得する
      let currentChar = this.currentMsgArray.slice(0, 1)
      //表示エリアに取得した文字を追加する
      document.getElementById('text-area').innerHTML += currentChar
      //配列の先頭を削除する。(もう表示したので)
      this.currentMsgArray = this.currentMsgArray.slice(1)
      //50後にもう一度このメソッドを呼び出す。
      setTimeout(this.printChar,50)
    },

  },
}
</script>
```

やってることはdataで定義した配列から取り出して削除してってやってるだけなので
思考は同じです。

長くなりましたが以上です