日記
なんかこう人生に対してやる気がでないときってあるよね!
今、そんな感じ。
よくあるのであまり気にしてないのだけれども、もしこれが続くようなことがあった場合、フリーランスだと怖いなぁって思う。
小説の死のロングウォークを思い出したりするよ。
よくよく考えれば、会社員でも同じかもしれないけれども。
前回の続き
前回はdrop.vue
コンポーネントを作成して、main.js
に登録したところまでを行いました。
その続きを書いていくんだよ!
drop.vueにドラッグ & ドロップでファイル選択を追加する
前回は、inputタグだけを使ってファイル選択のみがてきていた状態でしたが、当初の予定通りドラッグ&ドロップ機能もつけていきます。
まずはテンプレートですが、以下のように、ドラッグ&ドロップができるエリアを用意してあげます。
スタイルは、ここには記載しませんが、drop
クラスに対してpaddingなりwidth、heightを指定して、エリアを確保しています。
drop.vue
<template>
<div class="drop" @dragleave.prevent @dragover.prevent @drop.prevent="onDrop">
</div>
</template>
@dragleave.prevent
あたりはドラッグ&ドロップでファイル選択するにあたって定番の処理でしょうか。
ブラウザにドラッグ&ドロップをしてしまうと、ブラウザがファイルを表示しようとしてくれます。
Vue.jsではイベント名の後に.prevent
と書くこと、デフォルトのイベントの処理をキャンセルすることができます。
ドラッグ&ドロップを行ったときのファイルは@drop
イベントが発生したときのonDrop
に書くことにします。
さて、onDrop
の処理を書く前に、ドラッグ&ドロップのエリアの中にinputタグもいれることにします。
drop.vue
<template>
<div class="drop" @dragleave.prevent @dragover.prevent @drop.prevent="onDrop">
<div class="drop__default-container">
<label> ファイルを選択
<input class="drop__input" type="file" multiple="multiple" @change="onDrop">
</label>
</div>
</div>
</template>
こんな感じになりました。
onDropの処理を書く
つづいてonDrop
の処理を書いていきます。
といっても大した内容ではないのでさくっといきます。
drop.vue
<script>
export default {
methods:{
onDrop:function(event){
let fileList = event.target.files ?
event.target.files:
event.dataTransfer.files;
let files = [];
for(let i = 0; i < fileList.length; i++){
files.push(fileList[i]);
}
}
},
}
</script>
onDrop
はファイル選択とドラッグ&ドロップから呼ばれます。
ファイル選択から呼ばれた場合、event.target.files
からファイルを取得することができます。
一方、ドラッグ&ドロップの場合は、event.dataTransfer.files
で取得することができます。
その後に、取得したファイルをfiles
変数に格納しています。
これだけでとりあえず、ファイルを取得するコンポーネントdropが完成しました!
ちょっと前回を振りかえる
前回は、dropコンポーネントをもつmain.js
がいました。
main.js
はcreate.html
のフォームの内容をaxiosでサーバーに送信する処理を担っています。
main.js
const Drop = require('./components/drop');
new Vue({
el:'.form',
data:{
title:'',
files:[]
},
methods:{
onSubmit:function(){
let data = new FormData;
data.append('title', this.title);
for(let i = 0; i < this.files.length; i++){
data.append('files[]', this.files[i]);
}
axios.post('/file',data)
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.log(error);
})
},
},
components:{
'drop':Drop
}
create.html
はこんな感じで、省略しちゃってますがさきほどのmain.js
を読み込んでおります。
create.html
<form class="simple-form">
<h2>ファイルアップロード</h2>
<label for="title">タイトル</label>
<input type="text" name="title" v-model="title">
<button type="button" @click="onSubmit">投稿する</button>
<drop></drop>
</form>
図にするとこんな感じでしょうか。
それでですね、今drop.vue
にファイル選択とドラッグ&ドロップでファイルを取得することができるようになりました。
今回、この取得したファイルをmain.jsに渡して、サーバーに送信したいわけです。
子のdrop.vueから親にデータを渡す
ということで、Vue.jsのコンポーネントで避けて通れないemitを使うことにします。
このへんについては、以前も書いたのでここでは割愛します。
www.tohuandkonsome.site
イメージはものっそい汚い絵ですが、こんな感じになります。
コードはこんな感じになります。
drop.vue
<script>
export default {
methods:{
onDrop:function(event){
let fileList = event.target.files ?
event.target.files:
event.dataTransfer.files;
let files = [];
for(let i = 0; i < fileList.length; i++){
files.push(fileList[i]);
}
this.$emit('send-file', files);
}
},
}
</script>
create.html
では、ややこしいですがdrop.vueが発生するイベントsend-file
をキャッチして、sendFile
関数を呼びます。
create.html
<form class="simple-form">
<h2>ファイルアップロード</h2>
<label for="title">タイトル</label>
<input type="text" name="title" v-model="title">
<button type="button" @click="onSubmit">投稿する</button>
<drop @send-file="sendFile"></drop>
</form>
最後にsendFile
関数をmain.js
に書いてあげます。
main.js
const Drop = require('./components/drop');
new Vue({
el:'.form',
data:{
title:'',
files:[]
},
methods:{
onSubmit:function(){
},
sendFile(files){
this.files = files;
}
},
components:{
'drop':Drop
}
senfFile
は、drop.vue
が発火させるイベントからfiles変数を受け取っています。この中身をmain.js
のデータであるthis.files
に格納することで無事、子から親にデータを渡すことができました。
あとは、前回書きましたonSubmit
の処理を書くことで選択したファイルをサーバーに送信することができるようになりました。
やりたかったことは以上になります。
他にもdrop.vueコンポーネントは、ファイル選択したあとも見た目がかわらなかったりするので、もう少し使い勝手のよいコンポーネントに直したりとかも宿題はあるのですが、こちらは気がむいたら書いていこうと思います。