TypeScriptと単一ファイルコンポーネントを使用しているので適宜読み替え。
index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <!DOCTYPE html> < html > < head > < meta charset = "utf-8" /> < meta http-equiv = "X-UA-Compatible" content = "IE=edge" > < title >template</ title > < meta name = "viewport" content = "width=device-width, initial-scale=1" > < link rel = "stylesheet" type = "text/css" media = "screen" href = "main.css" /> < script defer src = "./built/main.js" ></ script > </ head > < body > < div id = "app" class = "hidden" > < dragfile-component ></ dragfile-component > </ div > </ body > </ html > |
main.ts
コンポーネントを呼び出すのみ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | import Vue from "vue" import dragfileComponent from "./dragfile.vue" const v = new Vue({ el: "#app" , components: { dragfileComponent, }, data() { return { } }, methods: { handleTemplate() { // }, }, }) // 画面初期化までは非表示 IE11対策 v.$nextTick(() => { const app = document.getElementById( "app" ) if (app) { app.classList.remove( "hidden" ) } }) |
main.ts
単一ファイルコンポーネントを使用している。
重要部分はここ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | <template> <div> <div class= "draggable" v-bind:class= "{ dragover: isDragOver }" @dragleave.prevent= "onDragLeave" @dragover.prevent= "onDragOver" @drop.prevent= "onDrop" > <p>Drag & Drop</p> </div> <ul> <li v- for = "fileName in fileNameList" v-bind:key= "fileName" > {{ fileName }} </li> </ul> </div> </template> <script lang= "ts" > import Vue from "vue" export default Vue.extend({ props: { // }, data() { return { isDragOver: false , fileNameList: [] as string[], } }, /** Vue構築完了時の処理 */ created: function init() { this .msg = "Hello Vue" }, methods: { // ドラッグ範囲に入ったときの挙動 classを変えている onDragOver(event: any) { this .isDragOver = true // console.log(event) }, // ファイルがドロップされたときの挙動 ここでファイルを操作する onDrop(event: any) { this .isDragOver = false console.log(event) const files = event.dataTransfer.files as FileList // tslint:disable-next-line:prefer-for-of for (let i = 0; i < files.length; i++) { console.log(files[i]) this .fileNameList.push(files[i].name) } }, // ドラッグ範囲外に出たときの挙動 classを変えている onDragLeave(event: any) { this .isDragOver = false // console.log(event) }, }, }) </script> |
@dragleave, @dragover,@drop がそれぞれのイベント。
.preventを指定すると既存のイベントが無効になる。
呼び出された関数内で操作できないこともない。
main.css
マウスオーバーしたときに背景色を変えている。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | .draggable { width : 30% ; height : 30% ; top : 0 ; left : 0 ; right : 0 ; margin : auto ; text-align : center ; bottom : 0 ; position : fixed ; border : black dotted 1px ; } .dragover { background-color : aquamarine; } |
webpack.config.js
VueだけでなくTypeScriptも使用している。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | var path = require( 'path' ) var webpack = require( 'webpack' ) const { VueLoaderPlugin } = require( 'vue-loader' ) module.exports = { entry: { index: './16_Vue/1699_DragFile/main.ts' , }, output: { path: path.resolve(__dirname, './built' ), publicPath: '/built/' , filename: 'main.js' }, module: { rules: [ { test: /\.js$/, include: path.resolve( "src" ), use: [ { loader: "thread-loader" , options: { workers: require( 'os' ).cpus().length - 1, } } // your expensive loader (e.g babel-loader) ] }, { enforce: 'pre' , test: /\.ts$/, loader: 'tslint-loader' , exclude: /(node_modules)/, options: { configFile: 'tslint.json' } }, { test: /\.ts$/, exclude: /node_modules|vue\/src/, loader: 'ts-loader' , options: { appendTsSuffixTo: [/\.vue$/], transpileOnly: true } }, { test: /\.vue$/, loader: 'vue-loader' , options: { loaders: { 'ts' : 'ts-loader!tslint-loader' , }, // extractCSS: plugin // other vue-loader options go here } } ] }, resolve: { extensions: [ '.ts' , '.js' , '.vue' , '.json' ], alias: { 'vue$' : 'vue/dist/vue.esm.js' } }, devServer: { historyApiFallback: true , noInfo: true }, externals: { "vue" : "Vue" , 'element-ui' : 'ElementUI' }, cache: true , performance: { hints: false }, devtool: 'source-map' , plugins: [ // make sure to include the plugin for the magic new VueLoaderPlugin() ], } |
完成イメージ
上記例だと以下のような感じ。
ドロップされたファイルがリスト表示される。

実際に組み込むなら受け取ったファイルをコンポーネントの呼び出し元で受け取れるようにするとなおよし。