今ノリに乗っているjavascriptフレームワーク『Vue.js』
Vue.jsを利用するなら是非とも身に付けたいコンポーネントを使った構成について、今回は超簡易的なソースコードを例に挙げて解説していこうと思います。
概要
今回は非常に簡易的なログイン画面のようなものを作ってみます。
あとはComponent間のデータの受け渡しを把握しやすくするために、入力中の値をリアルタイムで表示する機能も実装します。
入力フォームに値を入力し、送信ボタンを押すことでサーバーにデータを送信し登録する形になります。
サーバー側は送信されたemailをユーザーテーブルに登録するという処理を行なっていますが、今回は関連性が薄いため説明は省略します。
最終的に出来上がるページはこんな感じ。無骨ですね。
ログイン前
ログイン後
ソース
HTML
<div id="main-flame"> <div v-if="!login"> <preview-email v-bind:disEmail="email"></preview-email> <email-input @input-email="emailValue"></email-input> <email-submit @submit-email="sendEmail"></email-submit> </div> <div v-else> Welcome! </div> </div> <script src="bundle.js"></script>
この後紹介するjavascriptソースで作成するカスタム要素を中心にして記述しています。
javascript
import Vue from 'vue' import axios from 'axios' // プレビュー表示 Vue.component('preview-email',{ template: '<p>email:{{ disemail }}</p>', props: ['disemail'] }) // 入力フォーム Vue.component('email-input',{ template: '<input v-on:input="emailInput" v-model="inemail" placeholder="edit me">', data (){ return { inemail: '' } }, methods: { emailInput: function(){ this.$emit('input-email', this.inemail) } } }) // 送信ボタン Vue.component('email-submit',{ template: '<button v-on:click="createUser" >送信</button>', methods: { createUser: function() { this.$emit('submit-email') } } }) // メインフレーム new Vue({ el: '#main-flame', data:{ email: '', sendResult: '', login: false }, methods:{ emailValue: function(inEmail){ this.email = inEmail }, sendEmail: function(){ axios.post('http://localhost:1323/users/',{ email: this.email }) .then(response => { this.login = true }) .catch(function (error) { console.log(error); }); } } })
基本的には親要素である、main-flameのIDを保持するdiv要素を経由させて入力フォーム、プレビュー箇所のデータのやりとりを行なっていくイメージです。ちなみにformタグを使用していないため、一般的な登録画面とは異なりますが、説明の便宜上このような構成を取っております。
以下でもうちょっと細かく見ていきます。
メインフレーム(親要素)
まずは
- 入力フォーム
- 送信ボタン
- プレビュー表示箇所
を内包する親要素です。
// メインフレーム new Vue({ el: '#main-flame', data:{ email: '', sendResult: '', login: false }, methods:{ emailValue: function(inEmail){ this.email = inEmail }, sendEmail: function(){ axios.post('http://localhost:1323/users/',{ email: this.email }) .then(response => { this.login = true this.email = '' }) .catch(function (error) { console.log(error); }); } } })
こちらはVue.jsを使い始めると紹介される一番ベーシックな書き方で定義しています。
el要素にコンポーネントを包み込むためのdivタグのidを記載します。これによって指定したdivタグ配下の要素が以下の処理の管理下に置かれるイメージです。
dataはこのメインフレーム内で扱うデータを定義しています。例えばemailであれば、このデータを元に入力フォームのデータをプレビュー表示箇所に受け渡しなりを行うために用意しています。
で、最後にmethodsですが、こちらは名前の通り実行する処理を書いていきます。上で説明したようなフォームの入力の保持であったりサーバーとの通信を行う処理を記述しています。
emailValueでは引数として渡された値(inEmail)をdataで用意したemailに代入します。
sendEmailではdataのemailの値をサーバーにPOSTする処理を行なっています。転送が成功した場合、表示制御に使っているloginをtrueに設定しています。これによって、Welcome!が表示されるようになります。
ここで宣言されているメソッドは子要素から呼び出されて処理を開始します。呼び出し方などの詳細は子要素の方で解説します。
入力フォーム
次は入力フォーム部分のコンポーネントです。
// 入力フォーム Vue.component('email-input',{ template: '<input v-on:input="emailInput" v-model="inemail" placeholder="edit me">', data (){ return { inemail: '' } }, methods: { emailInput: function(){ this.$emit('input-email', this.inemail) } } })
子要素は全てComponent形式で利用していきます。
templateには実際に描画するためのHTMLタグを記述します。
v-on:input="emailInput"によって、値が入力された時にmethodsで宣言しているemailInputが実行されます。
v-model="inemail"ではdateにあるinemailを入力フォームの値に紐付けています。
dataの記述の仕方がメインフレームの時と異なりますが、Componentではdataは関数である必要があるため、このように記述しています。
methodsのemailInputの内容がちょっとわかりにくいのですが、一旦HTMlのemail-inputを見てみてください。
<email-input @input-email="emailValue"></email-input>
email-inputタグにおいて@input-email="emailValue"とありますが、これは親要素であるフレームワーク内で用意されている関数であるemailValueをinput-emailという要素に結びつけています。
あとはmailInputの$emitにinput-emailを渡したい引数と共に渡すことで親要素のemailValueコールされます。
この$emitは親要素のイベントを発火させるためのメソッドです。
上で説明済みですが、親要素では引数に渡された入力フォームに入力された値を自身のdataにセットしているわけです。
ここでセットした値がプレビュー表示やボタン押下時のサーバー通信に利用されることとなります。
プレビュー表示
次に入力した値がリアルタイムで表示させるプレビュー表示部分の処理です。
// プレビュー表示 Vue.component('preview-email',{ template: '<p>email:{{ disemail }}</p>', props: ['disemail'] })
わかりやすいようにHTMLファイルの記述も再度載せておきます。
<preview-email v-bind:disEmail="email"></preview-email>
ここではそこまでややこしいことはやっておりませんが、HTMLのカスタム要素が少しわかりづらいかもしれません。
templateでは入力フォームの時と同じように、画面に表示される際のHTMLタグを記述しています。今回はpタグの中に{{ disemail }}と記述されることで、javascriptで処理された値を表示するようにしています。
表示させる値はpropsで宣言されている値です。このpropsは親要素からデータを受け取り、値が変化することになります・
HTMLの方でv-bindを利用して、propsに親要素で宣言されているdata、emailをセットしているのが確認できると思います。
送信ボタン
最後のコンポーネントである送信ボタンです。
// 送信ボタン Vue.component('email-submit',{ template: '<button v-on:click="createUser" >送信</button>', methods: { createUser: function() { this.$emit('submit-email') } } })
そしてこちらが対応するHTMLのコード。
<email-submit @submit-email="sendEmail"></email-submit>
基本的にやっていることは入力フォームと同じで、emitを使って親要素のイベントを発火しています。
ボタンをクリックすることで、
- 送信ボタンコンポーネントのcreateUserが呼ばれ
- その中で親要素のsendEmailが呼び出され
- axiosを利用したサーバー通信が行われる
といった流れになります。
まとめ
いかがだったでしょうか。親子関係においてどのようにデータが流れ、イベントが動き出すのか、ということがイメージできればそこまで難しくないことかと思います。
もし今回の投稿で不明な点、うまく行かない点などあれば、twitterや問い合わせから質問を投げてもらえればできる限りの対応をさせていただきます。
Vue.jsには単一ファイルコンポーネントという面白そうなアプローチもありますので、そちらについても取り組んでみて共有できればなと思います。
Vue.jsはこれからもどんどん盛り上がっていき、需要も増えるフレームワークでしょう。是非一度触ってみてください。
閲覧いただき、ありがとうございました。