JavaScriptのフレームワークである「Vue.js」についての記事です。学習途中で至らない点等あると思うのですが、備忘録兼自分と同じ初学者の方向けにまとめてみました。
現在はVue.jsを用いてポートフォリオを書き換えつつ、学習を進めています。記述したコードも用いているので、是非参考にしてみてください。ポートフォリオはこちら、GitHubはこちらのページをご覧ください。
ポートフォリオ内の学習スキルを記述した以下の部分
を例にコンポーネントの書き方をまとめています。
インスタンス、ディレクティブに関する記事はこちらをご覧ください。
##目次
##1. コンポーネント
####1.1 コンポーネントとは
再利用することのできる部品。
本記事のはじめに載せたポートフォリオ内のskillsの項目のように、大枠のフォーマットを踏襲しつつ、中身だけ変えて使い回すことができる。
####1.2 メリット
- HTMLファイルのコードが簡潔になり分かりやすい。
- 大枠のDOM要素の変更が生じても、jsファイルの一箇所を直せば全てに適応されるので管理が楽。
jsファイルに以下のようなインスタンスが定義してあり、インスタンスのdataオプションオブジェクト内のskills配列の中身を全て表示したいとする。
const skills = new Vue({
el:'#skills',
data:{
skills:[
{
id:'frontend_skills',
show:'フロントエンド',
icon:true,
details:[
'HTML',
'CSS',
'JavaScript',
'jQuery',
],
},
{
id:'backend_skills',
show:'バックエンド',
icon2:true,
details:[
'php(Laravel)',
],
},
{
id:'database_skills',
show:'DataBase',
icon3:true,
details:[
'MySQL',
'Realtime<br>Database',
],
},
{
id:'infrastructure_skills',
show:'インフラ',
icon4:true,
details:[
'AWS(EC2,S3)',
],
},
{
id:'others',
show:'その他',
icon5:true,
details:[
'git',
'GitHub',
'firebase',
'Heroku',
'Bootstrap',
],
},
{
id:'studying',
show:'学習中',
icon6:true,
details:[
'Sass',
'Vue.js',
'React',
],
},
],
},
})
一つの手として、以下のようにHTMLファイルに直接書き込む方法がある。
見ての通り、6つの項目が続くためとても長い。また、DOM要素の変更が生じた際、6箇所直す必要がありミスが生じやすい。項目が6つだからなんとかなるが、項目の数がもっと多い場合は大変である・・・
<section id="skills">
<div>
<h5><i class="fas fa-pen"></i>Skills<i class="fas fa-pen"></i></h5>
</div>
<div id="frontend_skills">
<h6><i class="fab fa-html5"></i>フロントエンド</h6>
<div>
<ul>
<li>HTML</li>
<li>CSS</li>
<li>JavaScript</li>
<li>jQuery</li>
</ul>
</div>
</div>
<div id="backend_skills">
<h6><i class="fab fa-html5"></i>バックエンド</h6>
<div>
<ul>
<li>php(Laravel)</li>
</ul>
</div>
</div>
<div id="database_skills">
<h6><i class="fab fa-html5"></i>DataBase</h6>
<div>
<ul>
<li>MySQL</li>
<li>Realtime<br>Database</li>
</ul>
</div>
</div>
<div id="infrastructure_skills">
<h6><i class="fab fa-html5"></i>インフラ</h6>
<div>
<ul>
<li>AWS(EC2,S3)</li>
</ul>
</div>
</div>
<div id="others">
<h6><i class="fab fa-html5"></i>その他</h6>
<div>
<ul>
<li>git</li>
<li>GitHub</li>
<li>firebase</li>
<li>Heroku</li>
<li>Bootstrap</li>
</ul>
</div>
</div>
<div id="studying">
<h6><i class="fab fa-html5"></i>学習中</h6>
<div>
<ul>
<li>Sass</li>
<li>Vue.js</li>
<li>React</li>
</ul>
</div>
</div>
</section>
そこで登場するのがコンポーネント。実際に使用するとHTMLファイルを以下のように書き換えることができる。見ての通り、とてもシンプル!!!
<section id="skills">
<div>
<h5><i class="fas fa-pen"></i>Skills<i class="fas fa-pen"></i></h5>
</div>
<skills-component
v-for="skill in skills"
v-bind:key="skill.id"
v-bind:skill="skill"
></skills-component>
</section>
####1.3 書き方
Vue.component('skills-component',{
props:['skill'],
template:`
<div v-bind:id="skill.id">
<h6><i v-bind:class="{'fab fa-html5':skill.icon,'fab fa-php':skill.icon2,'fas fa-database':skill.icon3,'fas fa-network-wired':skill.icon4,'fab fa-github-square':skill.icon5,'fas fa-pen':skill.icon6}"></i>{{ skill.show }}</h6>
<div>
<ul class="skills">
<li v-for="detail in skill.details" v-html="detail"></li>
</ul>
</div>
</div>
`
})
今回のコードに出てきたVue.component
、props
、template
の3つの説明をしつつ、書き方を整理していく。
####1.4 Vue.component
Vue.component('skills-component',{
props:[''],
template:'',
})
Vue.componentメソッドを呼び出すことでコンポーネントを作成することができる。
第1引数には、コンポーネントにつける名前を渡す。もとから用意されてるHTML要素の名前とかぶるのを防ぐために、複数の単語を組み合わせて名前をつける。今回はskillsを表示するコンポーネントと言うことで、skill-component
という名前にしている。
第2引数には、コンポーネントの内容などをオプションとして渡す。今回は props
、templete
を渡している。
これにより、skills-componentというオリジナルの要素をHTMLファイルで使用することができる。
####1.5 templete
コンポーネントの中身を決めるもの。
中身は単一ルートである必要があるため、以下のような記述だとエラーが出る。解決策としては、全てをdiv要素
で囲んで一つのDOM要素にしてしまう。
Vue.component('skills-component',{
//propsは省略
template:`
<h6><i v-bind:class="{'fab fa-html5':skill.icon,'fab fa-php':skill.icon2,'fas fa-database':skill.icon3,'fas fa-network-wired':skill.icon4,'fab fa-github-square':skill.icon5,'fas fa-pen':skill.icon6}"></i>{{ skill.show }}</h6>
<div>
<ul class="skills">
<li v-for="detail in skill.details" v-html="detail"></li>
</ul>
</div>
`
})
このコンポーネントを、インスタンスのdataオプションオブジェクト内のskills配列の中身全てに使用するために、コンポーネント自体にv-forディレクティブ
を用いている。今回は配列から取り出したものをskillという変数に格納し、繰り返し処理をしている。
<section id="skills">
<skills-component
v-for="skill in skills"
></skills-component>
</section>
では、繰り返し処理をする中で、それぞれ異なった値を表示させるためにはどのようにすればいい???
そこで登場するのがpropsオプジョン。
####1.6 props
コンポーネントに値を渡す架け橋になるもの。
以下の場合、コンポーネントにインスタンスのdataオプションオブジェクト内のskills配列の要素のid,show,detailsプロパティを渡している。
今回はskills配列から取り出したものをskillという変数に格納し、繰り返し処理をしている。skillの持つプロパティを全て渡す場合、以下のようにプロパティをprops:['skill']
として書くこともできる。「skillの変数が持つ全てのプロパティを渡しますよ〜」ということを表している。
渡すプロパティが多くなるとコードが長くなってしまうため、こちらの書き方の方が良い。
Vue.component('skills-component',{
//一つずつプロパティを書く方法
props:[
'id',
'show',
'details',
],
//全てのプロパティを一気に書く方法
props:['skill'],
//templeteは省略
そして、以下のようにカスタム属性(propsで指定したプロパティのこと)
を通してプロパティの値を受け取らせる。
<section id="skills">
<!-- 一つずつプロパティを書く方法 -->
<skills-component
v-for="skill in skills"
v-bind:id="skill.id"
v-bind:show="skill.show"
v-bind:details="skill.details"
></skills-component>
<!-- 全てのプロパティを一気に書く方法 -->
<skills-component
v-for="skill in skills"
v-bind:skill="skill"
></skills-component>
</section>
以上で、コンポーネントのテンプレートにプロパティを渡すことができるため、繰り返し処理の中で、その都度異なった値を表示することができる。