[Vue.js] カンバン管理ツール　4．CSVからのインポート

## はじめに
本記事は以下で投稿した記事の続きです。
https://qiita.com/khata0131/items/c467dd192d053a184fb2

カンバン管理ツールとしての基本機能の構築は完了したため、
登録されたチケットを別ファイルに保存して読み込み・書き込みができるようにしていきます。
データ量が多くないのでCSVファイルにて管理することとし、
本記事ではCSVファイルからのインポートを実装します。

## 1．環境準備
ローカル環境で実行したプログラムからローカル環境のファイルを参照することは、
ブラウザのセキュリティーポリシーの観点から基本的にはできません。
（起動時のオプションなどを変更して可能になるブラウザもあり）

Vue.jsには、ローカル環境に簡易的な静的サーバーを作るコマンドが存在します。
プロジェクトが存在するディレクトリに移動して、以下のコマンドを実行します。
参考：https://zenn.dev/phi/articles/node-npx-http-server

```bat:コマンド
C:\pg\redmine>http-server
Starting up http-server, serving ./public

http-server version: 14.1.0

http-server settings:
CORS: disabled
Cache: 3600 seconds
Connection Timeout: 120 seconds
Directory Listings: visible
AutoIndex: visible
Serve GZIP Files: false
Serve Brotli Files: false
Default File Extension: none

Available on:
  http://192.168.0.152:8080
  http://127.0.0.1:8080
Hit CTRL-C to stop the server
```

実行結果として出力されたURL(localhostでも可)にアクセスすることで、
publicフォルダ配下のページが表示されます。
![csv-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428605/1f7b4d23-b1ef-16d7-5357-f82451c0440d.png)


## 2. CSVインポート

ローカルファイルを参照する準備ができたので、
CSVファイルを配列に格納するためのメソッドを作成します。
参考：//https://gist.github.com/tigawa/8858345

```js:main.js
    csv2Array: function (filePath) { //csvﾌｧｲﾙﾉ相対ﾊﾟｽor絶対ﾊﾟｽ
      
      var csvData = new Array();
      var data = new XMLHttpRequest();	
      data.open("GET", filePath, false); //true:非同期,false:同期
      data.send(null);
    
      var LF = String.fromCharCode(10); //改行ｺｰﾄﾞ
      var lines = data.responseText.split(LF);
      for (var i = 0; i < lines.length;++i) {
        var cells = lines[i].split(",");
        if( cells.length != 1 ) {
          csvData.push(cells);
        }
      }
      return csvData;
    }
```

CSVのインポートはページ読み込み時に実行したいため、
ライフサイクルフックのcreatedに実装します。（createdの説明は後述）
引数として、作成したCSVファイルの相対パスを指定します。

```js:main.js
created: function(){
    csvData = this.csv2Array("../csv/kanban.csv");
}
```



今回準備するCSVは以下の形式で作成します。

項目1：ストーリーNo
項目2：ステータスNo
項目3：チケットNo
項目4：ストーリー名 または、 チケット名

項目4について、ステータスNo、チケットNoが「0」の場合はストーリー名、
「1以上」の場合はチケット名として扱います。

```text:CSVファイル：例
1,0,0,Story1
1,1,1,Ticket1-1
1,1,2,Ticket1-2
1,2,1,Ticket1-3
2,0,0,Story2
2,1,1,Ticket2-1
3,0,0,Story3
```

CSVファイルから取得したデータを配列に格納し、
ストーリーとチケットを別の一時配列に振り分け直します。
その結果を、ストーリー・チケットの表示用の配列に格納します。

```js:main.js
created: function(){
    const lineStory = [];
    const lineTicket = [];

    csvData = this.csv2Array("../csv/kanban.csv");
    csvData.forEach(function(lines) {
      if(lines[1] == 0 && lines[2] == 0 ){
        lineStory.push(lines)
      }
      else{
        lineTicket.push(lines)
      }
    });
    for(var i = 0; i < lineStory.length; i++)
    {
      this.table.push({ storyTitle: lineStory[i][3], column: [{ list: [] }, { list: [] }, { list: [] }, { list: [] }] });
    }
    for(var j = 0; j < lineTicket.length; j++)
    {
      this.table[lineTicket[j][0]].column[lineTicket[j][1]-1].list.push({ ticketTitle: lineTicket[j][3] });
    }
  },
```

上記のCSVファイルを使用してページを表示した結果が以下です。

![csv-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428605/34bc55ce-dc28-92c3-5d36-1208abb68dc3.png)


## 補足：ライフサイクルフック created mounted

ライフサイクルフックとは、Vue.jsの初期化の中の決められたタイミングで実行される関数です。
参考：https://reffect.co.jp/vue/vue-js-created-mounted-diffrence

createdとmountedがありますが、以下の違いがあります。
・created：DOMがまだ作られていない状態
・mounted：DOMが作成された直後の状態

今回は、DOMを作成するためのテンプレートに使用している変数に値をセットする処理を実装する必要があったので、
createdにてCSVのインポートを実装しました。
しかし、実際に動きを確認してみると、mountedに実装しても正常に動作しました。

今回のプログラムでは、v-forによってストーリーやチケットを作成した配列の値を用いて表示しております。
これらは、初期表示時にのみDOMを作成しているわけではなく、Vueコンポーネントによって常時DOMの書き換えを行っております。
そのため、今回はcreatedでもmountedでもどちらでもよかったようです。
（初期表示時のDOMから値を取得してくるといった処理はcreatedでは実装不可のため、mountedにする必要あり）


## 終わりに
ローカル環境で開発を行う際にローカルファイルへのアクセスで毎回躓いていましたが、
Vueには便利な機能がありスムーズに開発することができました。
次回以降、CSVへのエクスポート処理を実装予定ですが、
処理のタイミングや非同期処理の制御など考慮する点が多いため楽しみです。