以前ドラッグ&ドロップでファイル選択できる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です。