Vue.jsとjQueryライブラリを共存させなければいけない場合は、コンポーネントに閉じ込める。(select2版)

2018-12-04

禁断の融合魔術


もうjQueryなんて使いたくない! Vue.jsや、Reactを使って脱jQueryするんだ!

こんな、言葉が叫ばれて久しい昨今、皆様どうお過ごしでしょうか?

新しいプロジェクトでは、ほとんどが、脱jQeryを果たしていても、各フレームワークのテンプレートエンジン+jQuery+Vueが融合しているプロジェクトも実はあったりするのではないでしょうか?

または、お客様から、

「いやだ!この『ポワン』っていうアニメーションが気に入ってたんだから、このカレンダーはそのままのデザインにしてほしい!」

などの要望があり、泣く泣く、jQueryライブラリを使う事もあるかもしれません。

そんなときは、以下の方法で、なるべく被害が広がらないような、状態にしておきましょう(もちろん、Vue.jsを使用する場合は、jQueryを極力使わない選択をするのがベストです。)

対応前

絶望を感じる状況です。

Vue.js内で、jQueryを使う場合は、各コンポーネントの mounted に毎回jQueryライブラリの初期化処理を書くのが、おそらく・・多分・・定石だと思います。

さらに、各jQueryライブラリの初期化処理を methods に分けて書いて、mountedで、一つずつ呼び出す形にするとほんの少しだけスッキリします。

しかし、①のコメントをよく見ると、「select2は、store.jsで実施」と書いてあります。

な、、なんだってー!jQueryをVuex側で使用しているのか・・。

早速、見てみましょう。

とても辛い・・・。

特に、同じ画面でselect2などのライブラリを複数使用する時は、何回も同じ初期化処理を書かなくてはいけないので、classは同一にしたりしますよね。

すると、今度は①〜③のような感じで、data属性や、nameなどでイベント処理を分岐させたりしなければいけなくなりカオスです。

一番の問題は、どこにjQueryの記述を書くのか?というルールがないという事です。

jQueryには「CSSセレクタ」という強力な機能がありますので、何処であろうが、DOMを操作することができ、コンポーネントではなく、Vuex側に初期化処理を書いた場合、一体どこでイベントが発火するのかわからなくなってしまいます。

したがって、jQueryライブラリは、コンポーネントに閉じ込め、$emitで親コンポーネントにデータ(日付など)を渡したほうがいいのではないか?と思い試してみました。

 

その1.templateでそっと優しく包み込む

【注意】

同じページで何度も使用する可能性大なのでidは使わず、refを使用しましょう。

idをつけると、イベント発火がめちゃくちゃになります。

担当者を選択したはずなのに、ユーザを選ぶ為のselect2が選択されたりします。

その2.初期化処理は、mountedで

①動的なデータは全て、propsで親から受け取ります。

select2で必要になりそうなデータは、

optionList:option用のリスト

multiple:複数選択かどうか?

selectValue:デフォルトで選択されている値

の3つです。

②self.$refs.select2をjQueryオブジェクト化する

やはりjQueryライブラリの初期化は、mountedで実施します。

気をつけなければならないのは「絶対にCSSセレクタを使ってはならぬ」ということです。

refを使うことで、このコンポーネント内で、処理が完結します。

③$emitで親にデータを渡す

コレが一番のミソです。

select2でもdatepickerでも、値を選択した時に、Vuexのactionやmutationsを呼び出してしまうと、jQueryライブラリを使用する度に、Vuexに処理を追加しなくてはならず、面倒くさいし、可読性が一気に下がります。

これで、jQueryをコンポーネントの中に閉じ込めることができました。

その3.コンポーネントを呼び出す。

使用する時は、上記のような感じでpropsでデータを渡します。

今回は、複数選択なしなので、multipleのデータは渡さず、デフォルト値を使います。

$emitで発火させた、changeイベントで処理を実施するように記載してください。

「$event」にselect2コンポーネントから引数で渡されたデータが入っています。

これで(少しだけ)平和な世界が訪れました。めでたい!

 

—————————-

この記事がお役に立てたら、是非シェアをお願いします^^