以前ドラッグ&ドロップでファイル選択できるinput要素をVue.jsで作りました。それを今度はSvelteに書き直してみました。ついでに得た知見も披露します。
デモ
まずは完成品をご覧ください。
前回つくったものと動作自体は同じですので、詳しい説明は省略します。
使い方
<div id="drag"></div> <script src="https://pandanoir.net/js/drag.js"></script> <script> new Drag({ target: document.getElementById('drag'), data: { name: 'hoge', }, }); </script>
まず、drag.jsを読み込みます。次にnew Drag({target: element})と書きます。以上です。
dataにオブジェクトを渡すと、そのプロパティと値がfile-inputの属性として設定されます。
VueからSvelteへ変換するときに苦戦したこと
基本的にVueとSvelteは似ているので、
@click→on:click:class="{hoge: fuga}"→class:hoge="fuga"
とこののようにカンタンに変換ができます。
しかし、「コンポーネント内の特定の要素に、任意の属性値を設定したい」という部分が難しかったです。
親要素のプロパティはどこに行くべきか?
例えばVueで以下のようにしたら、input要素へnameとacceptは渡ってほしいですよね?
import drag from '../js/drag.vue';
const app = new Vue({
el: '#app',
components: {drag},
template: `<drag name="upload_file" accpet=".png"/>`
});
これをVueではinheritAttrsをfalseにして、v-bind="$attrs$をコンポーネント内のinput要素につけることで、カンタンに実現できます。
しかし、Svelteではややトリッキーなことをしなければなりません。
まず、Vue.jsのような$attrsがありません。そのため、new Drag({ data: data })のようにdataで渡すようにします。
そして、これをbindするときも一癖あります。単に<input {...options.data}>としても、生成段階ではthis.optionsがありませんので、エラーが出ます。そのため、this.options.dataを一度受け取る作業を行います。
export default {
oncreate() {
this.set({
props: this.options.data
});
},
あとは<input {...props}>としてやればOKです。