ファイルからデータを読み取る必要がある場合があります。 以前は、サーバーに送信して、必要なデータを返す必要がありました。 現在では、 FileReaderAPIを使用してブラウザから直接ファイルにアクセスすることもできます。

UIレベルでテキストファイルを使用して些細なことを行うためにテキストファイルを読み取りたいだけの場合は、ファイルをサーバーに送信する必要はありません。 例として、ファイルからテキストエリアを埋める場合があります。

FileReader API

FileReader APIは、FileまたはBlobオブジェクトタイプを使用してさまざまな方法でデータを読み取るための優れたインターフェイスを提供します。

FileReaderインスタンスにはreadAsTextメソッドがあり、これを使用してファイルをテキストとして読み取ることができます。

const reader = new FileReader();
reader.readAsText(file);

FileReader APIは非同期であるため、状態を取得するために使用できるいくつかのイベントを公開します。 特に、ファイルが読み取られたときにデータにアクセスするには、onloadイベントが必要です。

const reader = new FileReader();
reader.onload = e => console.log(e.target.result);

reader.readAsText(file);

ご覧のとおり、テキストデータにはe.target.resultからアクセスできます。

ファイルリーダーコンポーネント

前のコードはすでにファイルを読み取っていますが、それでもファイルオブジェクトを指定する必要があります。 そのためには、<input type="file"> HTMLタグを使用する必要があります。これにより、ev.target.filesを介してファイルにアクセスできるchangeイベントがトリガーされます。

FileReader.vueコンポーネントを作成してすべてをまとめましょう。

FileReader.vue
<template>
  <label class="text-reader">
    <input type="file" @change="loadTextFromFile">
  </label>
</template>

<script>
export default {
  methods: {
    loadTextFromFile(ev) {
      const file = ev.target.files[0];
      const reader = new FileReader();

      reader.onload = e => this.$emit("load", e.target.result);
      reader.readAsText(file);
    }
  }
};
</script>

親コンポーネントがデータを処理できるように、コンポーネントはloadイベントを発行しています。

コンポーネントの使用

App.vue コンポーネントがすでにセットアップされているとしたら、それを使用してコンポーネントのデモを行いましょう。

App.vue
<template>
  <div id="app">
    <textarea rows="10" v-model="text"></textarea>
    <br>
    <text-reader @load="text = $event"></text-reader>
  </div>
</template>

<script>
import FileReader from "./FileReader";

export default {
  name: "app",
  data: () => ({ text: "" }),
  components: {
    FileReader
  }
};
</script>

textデータプロパティを追加する必要があります。例として、v-modelを使用してテキスト領域にバインドします。 最後に、@loadイベントをキャプチャし、$eventを介してtextプロパティをイベントペイロードに設定します。

ボーナス:ファイルボタンのスタイリング

<input type="file">タグは、ブラウザーごとに異なる方法でレンダリングされます。 カスタムスタイルが必要な場合は、それを非表示にして、代わりに<label>タグのスタイルを設定できます。

入力を非表示にするには、opacity: 0;cssプロパティを使用します。 display: block;またはvisibility: hidden;を使用すると、アクセスが困難になります。

また、ラベルの後ろに配置するには、ポジショニングとz-indexの組み合わせが必要です。

FileReader.vue
<template>
  <label class="text-reader">
    Read File
    <input type="file" @change="loadTextFromFile">
  </label>
</template>

<style>
.text-reader {
  position: relative;
  overflow: hidden;
  display: inline-block;

  /* Fancy button style 😎 */
  border: 2px solid black;
  border-radius: 5px;
  padding: 8px 12px;
  cursor: pointer;
}
.text-reader input {
  position: absolute;
  top: 0;
  left: 0;
  z-index: -1;
  opacity: 0;
}
</style>

これでうまくいくはずです。ファイル入力ボタンは完全に機能するはずです。

コードとデモはこのコードサンドボックスで見ることができます。

涼しくしてください🦄