質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

1930閲覧

vuejsにて、値が入っているはずのcomputedプロパティを出力すると空のオブジェクトになっている

yu_yeah

総合スコア14

Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2020/05/31 10:00

前提・実現したいこと

はじめての質問で至らぬ箇所もあると思いますが、よろしくお願いします。

以下のようなcsvアップロード、加工、ダウンロードするプログラムを組んでいます。

  1. ドラッグアンドドロップされたcsvを変数に格納(こちらの記事を参考に作成)
  2. 変数に格納されたcsvを配列に変換
  3. 一部の文字列を置換したり、抽出したりして別の配列を作成
  4. 作成した配列をcsvにしてダウンロード(こちらにあがっているコードを利用)

発生している問題・エラーメッセージ

後に載せてあるcomputedプロパティのfileAsArrayでcsvを配列に直し、methodsのprocessDataで一部データを抽出しております。
しかし、一度目のprocessDataの呼び出しでは、computedプロパティのfileAsArrayが以下のようになり、値が取り出せません。(後述のprocessData内のconsole.logで確認をしております)

▶︎[]

クリックして展開すると、以下のようになり、値自体は読めていることが確認できます。

▶︎[] 0: (16) ["品目区分名", "納期", "自社名", "発行日", "品目番号", "品目名", "員数", "母材", "材質", "寸法1", "寸法2", "寸法3", "長さ分母", "数量", "発注先1", "発注先2 "] 1: (16) ["品目", "2020/6/1", "社名", "2020/5/27", "品目番号の例", "品目の例", "", "", "", "0", "", "", "1", "1", "", " "]

二度目は正常に取り出すことができています。

▶︎[Array(16), Array(16), Array(16), Array(16), Array(1)]

クリックして展開すると、

▶︎[Array(16), Array(16), Array(16), Array(16), Array(1)] 0: (16) ["品目区分名", "納期", "自社名", "発行日", "品目番号", "品目名", "員数", "母材", "材質", "寸法1", "寸法2", "寸法3", "長さ分母", "数量", "発注先1", "発注先2 "] 1: (16) ["品目", "2020/6/1", "社名", "2020/5/27", "品目番号の例", "品目の例", "", "", "", "0", "", "", "1", "1", "", " "]
  • 1回目のオブジェクトの値はなぜ取り出せないのか
  • 1回目と2回目の呼び出しでなぜ違う挙動をするのか

についてご教授いただけると幸いです。

該当のソースコード

javascript

1 <script> 2 const app = new Vue({ 3 el: "#app", 4 data: { 5 isEnter: false, 6 message: "", 7 error: false, 8 files: [], 9 output_array: [["仕入先コード", "納品書番号", "追跡番号", "個口数", "入荷予定日", "詳細", "品番", "バーコード", "数量", "仕入単価"]] 10 }, 11 computed: { 12 filesAsArray: function() { 13 let file_tmp_array = [] 14 this.files.forEach(file => { 15 var file_reader = new FileReader(); 16 file_reader.readAsText(file, "SJIS"); 17 var tmp_array = [] 18 file_reader.addEventListener('load', function(){ 19 var lines = file_reader.result.replace(/"/g, "").replace(/ /g, "").split("\n"); 20 lines.forEach(line => { 21 arrFile = line.split(','); 22 tmp_array.push(arrFile) 23 }) 24 }) 25 file_tmp_array.push(tmp_array) 26 }) 27 return file_tmp_array 28 } 29 }, 30 methods: { 31 dropFile() { 32 var tmp = []; 33 tmp = [...event.dataTransfer.files] 34 tmp.forEach(item => { 35 if (item.type.match("text/csv")){ 36 this.files.push(item) 37 }else{ 38 this.message = 'CSVファイルを選択してください'; 39 this.error = true; 40 } 41 }) 42 this.isEnter = false; 43 }, 44 processData() { 45 console.log(this.filesAsArray[0]) 46 tmp_data = this.filesAsArray[0]; 47 48 for (i=0; i<tmp_data.length; i++){ 49 line = tmp_data[i]; 50 if (line[0] === "hogehoge" && line[4].length === 5){ 51 delivery_date = this.formattingDate(line[1]); 52 this.output_array.push(["001", "", "", "", delivery_date, "", line[4], "", line[13], ""]) 53 } 54 } 55 }, 56 formattingDate(str_date) { 57 splited_date = str_date.split("/"); 58 // 月の0埋め 59 if (splited_date[1].length === 1) { 60 splited_date[1] = '0' + splited_date[1]; 61 } 62 // 日付の0埋め 63 if (splited_date[2].length === 1) { 64 splited_date[2] = '0' + splited_date[2]; 65 } 66 return splited_date[0] + splited_date[1] + splited_date[2] 67 } 68 } 69 }) 70 71 </script>

一応、該当箇所のhtmlも載せておきます。二度目は取り出せる、というのは、2回変換のボタンをクリックし、processDataを走らせていることを指しています。

html

1 <div id="app"> 2 <div class="drop_area" @dragenter="dragEnter" 3 @dragleave="dragLeave" @dragover.prevent @drop.prevent="dropFile" :class="{enter: isEnter}"> 4 csvをアップロード 5 </div> 6 <div> 7 <ul> 8 <li v-for="file in files"> 9 <span>{{ file.name }}</span> 10 </li> 11 </ul> 12 </div> 13 <div v-show="message"> 14 <p>{{ message }}</p> 15 </div> 16 <div v-show="files.length"> 17 <button class="button" @click="processData">変換</button> 18 </div> 19 <csv-download v-show="files.length" :data-json=output_array></csv-download> 20 </div>

補足情報(FW/ツールのバージョンなど)

Vue.js v2.6.11
Google Chrome : 83.0.4103.61(Official Build) (64 ビット)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

変換ボタンが押されるとどうなるかを考えます。

  1. processData が実行され、filesAsArray が参照されます。
  2. FileReader オブジェクトが作成されます。
  3. readAsText メソッドにより 非同期に 読み込みが開始されます。
  4. load イベントが監視され、完了すると同時に内容が配列に分解されて file_tmp_array に格納されます。
  5. processData で参照されている filesAsArray は「値が格納されるのを待っている配列」が入っています。

つまり、最初にアクセスするときに空になるのは「読み込みが非同期だから」と考えられます。
file_tmp_array が最初に返ってくるタイミングではまだ load が完了していないのです。

fileswatch して、変化があったら裏で読み込みを開始する」など、非同期処理の待機時間をなんとか上手く解決します。
ちなみに↑の方法だと読み込みが完了する前に変換ボタンを素早く押されてしまったら同じ結果になると思うので、完了までボタンを無効にするなど工夫が必要です。

投稿2020/06/01 02:50

htsign

総合スコア870

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yu_yeah

2020/06/01 03:32

なるほど! とても分かりやすい説明ありがとうございます! 解決しました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問