N予備校1章終えた人向けVue入門1
この記事はN予備校のプログラミング入門Webアプリコースの1章を終えた人に向けたVue入門記事です。
別にN予備校の中の人ではないです。
では始めます。
Vueとはなにか?
Vueとは、ブラウザ上でhtml
とcss
とjs
を使って、スマホのアプリのようなリッチなUI体験を提供できるようにするために生まれたものです。Vueが生まれるまでは、主にjQueryと呼ばれるライブラリが使われていました。しかし、jQueryを使っても、中規模以上のアプリを作るには、jsとcssでは辛いものがありました。そこで、webコンポーネントという思想が生まれました。webコンポーネントとは、画面上の構成要素の一つ一つを部品(コンポーネント)として扱えるようにするという考え方です。webコンポーネントのメリットは、プログラマーが1度コンポーネントを作ってしまえば(例えばボタンコンポーネントなど)、あとはそのコンポーネントを再利用してアプリ内で使い回せることや、コンポーネント単位でcssを定義できる(グローバルcssを使わずに済む)ことです。N予備校1章の場合とwebコンポーネントを比較してみましょう。
N予備校1章の場合
- 最初にhtmlタグを定義してidやclassをつける
- jsで
getElementById
で読み込み、innerHTML
などで文章を変更したり、clickイベントを定義したりする。 - 同じような機能を複数作りたいときは、その分 htmlとjsをコピペして記述
webコンポーネントの場合
- 最初にコンポーネントの中にhtmlタグを定義してidやclassをつける
- コンポーネントに対して、clickイベントを定義したりする
- コンポーネントは使い回せるため、同じコードを2回書かなくてもよい
もちろんN予備校1章の方法でも、使い回せるように書くことはできますが、その分のスキルは必要になります。webコンポーネントの場合は一度コンポーネントを書けば、あとは積み木のように積み上げていくだけです。
現在のブラウザ上のwebアプリ開発(フロントエンド開発)においては、jQueryではなくwebコンポーネントの思想をくんだAngularやReactやVueが利用されることが多いです。
jsの辛さ
大規模なwebアプリをjsで作成するには、ある程度の技術(とルール)が必要になってきます。例えば、変数のスコープ管理、状態の管理をどうするか、どのファイルに何を記述するかなどです。また、そのためには即時関数などのテクニックが要求されたりします。うまく管理できなければ、複雑なコードができてしまい、誰もメンテナンスしたがらない、機能追加すればバグを生むwebアプリが出来上がります。そのため、そこらへんを軽減してくれる考え方やフレームワークが必要になってくるのです。
cssの辛さ
大規模なwebアプリをcssでスタリングするには、ある程度の技術(とルール)が必要になってきます。というのは、cssはグローバルに定義されてしまうからです。例えば、10種類くらいあるページで、.my-card
というcssをどこかで定義したとします。そのcssをいろんな場所で使っていたとします。もしある特定のページで.my-card
のスタイルを変えたいと思って修正した場合、他の9ページの.my-card
が適用されているスタイルに予期せぬ表示のズレが生じる可能性があります。さらに、cssはcssセレクタをつかって、子や孫要素にもスタイルを指定できるため、さらなる意図せぬ影響がでてくるかもしれません。これを防ぐためには、cssの命名規則にBEMを使うなどのテクニックを利用するか、もしくは何かしらのフレームワークを用いて、グローバルなcssを使わなくするしかありません。
jQueryとはなにか
N予備校1章で皆さんは、getEelementById
やinnerHTML
を使ってテキストを書き換えたりonclick
に対して関数を代入して、クリックイベントリスナーを定義したりしました。では、文章をクリックごとに表示したり、非表示にしたりする挙動はどうすれば実現できるでしょうか(この文章を見ているということは「jQuery」とはなにかをクリックしましたね)?この挙動を簡単に実現してくれるライブラリが、まさにjQueryです。
なぜjQueryは流行ったのか
皆さんはあまり意識しないかもしれませんが、実はブラウザというものは各ブラウザごとに機能に違いがあります。ブラウザ上でwebアプリを提供する側は、この機能の差に気を使って作成しなければいけませんでした。Aブラウザはこの機能が使えるが、Bブラウザは使えないので、違うやり方で実現するなどです。これはかなりアプリ制作者にとってストレスでした。jQueryはこれらブラウザ間の差分をうまく吸収してくれました。アプリ制作者はブラウザごとの差を意識しなくてよくなったのです。これもjQueryが流行った一因でした。ただし、ブラウザ間の差も少なくなってきています。また、PostCSSと呼ばれる技術も出てきており、jQueryのブラウザ間の差分吸収といったメリットは薄くなってきています。
jQueryはオワコン(終わったコンテンツ)なのか
jQueryはあまり使われなくなったから、jQueryはオワコン(終わったコンテンツ)みたいな話がありますが、そうではないです。単純に役割が変わったのです。LPサイトなどのページ数がすくなくデザインが主体のサイトの場合はjQueryは現役です。またwebコンポーネント思想のライブラリは学習コストが高いため、デザイナーにとってはjQueryのほうが好ましかったりします。
Vueに入門しよう
前置きが長くなりましたが、ここからは実際のVueに入っていきます。
こちらがVueの公式サイトです。ありがたいことに、日本語に翻訳されています。学習においてはVueの公式サイトは、ある程度フロントエンドがわかる人向けに書かれているので、説明文が初学者にとっては難しくなっています。
こちらが公式チュートリアルです。オンライン上でチュートリアルを進められるようになっています。こちらも、説明文章が難しいと思います。
そこで、この記事でチュートリアルの各ページの追加解説を行います。公式チュートリアルの横に並べて、一緒に読んでください。
Step1 はじめに
リンク
Vueは1ファイル1コンポーネントの構成担っています。ファイルの拡張子は.vue
です。ここでのコンポーネントとは、とりあえずhtmlとjsとcssを画面上の部品単位(例えばヘッダーやボタンなど)で管理できるものと考えてください。Vueファイルの中身を見てみましょう。Vueファイルはhtmlのようなタグの構造になっています。
<template>
<h1>Hello World!</h1>
</template>
<style>
</style>
<script>
</script>
代表的なタグを3つ覚えてください。template
とstyle
とscript
です。これらはこの順番に記述する必要はないです。どの順番でも構いません。templateタグが最後でもいいのです。 また、チュートリアルにはstyle
とscript
タグが無いことに気づくかもしれません。基本的にtemplate
タグは必須ですが、他2つのタグは必要でなければ記述する必要はありません。
それぞれのタグの役割を説明してませんでした。template
タグにはhtmlを記述します。style
タグにはcssを記述します。script
タグにはjsを記述します。1ファイルにすべての要素(表示、スタイル、動き)がまとまっていて、見やすいですね。
template
タグは、N予備校1章で扱ったhtmlそのものです。今回のチュートリアルの場合は、h1
タグとテキスト(Hello World!)が入っているため、Hello Wolrd! というh1タイトルがプレビュー画面に表示されていることがわかります。
まずはここまで理解できればOKです。
課題: Hello Wolrd!の代わりに「こんにちは世界!」という文章を表示させましょう!↓答え
<template>
<h1>こんにちは世界!</h1>
</template>
Step2 宣言的レンダリング
突然難しい言葉がでてきました。宣言的レンダリング!ナンノコッチャ!
とりあえずこのチュートリアルでは「宣言的レンダリング」は無視してください。理解しなくてもいけます。
チュートリアルの言葉を解説します。
エディターに表示されているのは、Vue の単一ファイルコンポーネント(SFC)です。SFC は再利用可能な自己完結型のコードブロックであり、一緒に属する HTML、CSS、JavaScript をカプセル化して .vue ファイル内に記述します。
Vueは1ファイルに1コンポーネントを定義します。それをSFCと呼んでいます。拡張子は.vue
です。コンポーネント内のhtmlのタグ構造やcssのスタイルやjsの変数は、コンポーネントの外の世界には影響しません(グローバル変数じゃないよ)。
Vue の中核となる機能は宣言的レンダリングです。HTML を拡張したテンプレート構文を用いて、JavaScript の状態に基づいて HTML がどのように見えるかを記述することができます。状態が変更されると、HTML は自動的に更新されます。
変更されたときに更新のトリガーとなるような状態はリアクティブとみなされます。Vue では、リアクティブステートはコンポーネントに保持されます。
いまからこの文章の解説を始めますが、もし難しいと感じたら飛ばしましょう。
Vueの場合、データが変更されると、自動的に画面が更新されます。
例えば、フォームに入力されたら、入力した文章を下に表示するプログラムを書くときに、従来であれば、次のように書いていました。
<input id="input-text" />
<button id="submit-button">画面出力</button>
<div id="display-input"></div>
<script>
function displayInput() {
const inputForm = document.getElementById('input-text');
const text = inputForm.value;
console.log(text);
const displayTag = document.getElementById('display-input');
displayTag.innerHTML = text;
}
const button = document.getElementById('submit-button');
button.onclick = displayInput;
</script>
input
タグに文章を入れて、ボタンを押すと、displayInput
関数が実行されます。この関数の中で、明示的にdisplay-input
Idのついてタグのテキストを更新しました。
それに対して、Vueの場合です。
<template>
<div>
<input id="input-text" />
<button @click="displayInput">画面出力</button>
<div>{{ inputText }}</div>
</div>
</template>
<script>
export default {
data() {
return {
inputText: '未入力',
};
},
methods: {
displayInput() {
const inputForm = document.getElementById('input-text');
// 注目!!! data()で定義したinputTextに代入している。
this.inputText = inputForm.value;
},
},
};
</script>
ガラッとコードの書き方がかわりましたね。ボタンをクリックするとdisplayInput
関数が発火します。displayInput
関数の中では、先程同様にinput
タグを取得してその値を取得しています。しかし、ここで次のコードに注目してください。
// 注目!!! data()で定義したinputTextに代入している。
this.inputText = inputForm.value;
これはここで定義しています。
data() {
return {
inputText: '未入力',
};
},
実はVueはこのdata()
の返り値で定義している変数に変更が加わると、そのたびにtemplate
を描画し直すのです。template
をみてください。
<template>
<div>
<input id="input-text" />
<button @click="displayInput">画面出力</button>
<div>{{ inputText }}</div>
</div>
</template>
{{ inputText }}
という見たことのないhtmlっぽくないものがありますね。これはdata()
で定義したinputText
です。templte
において、{{ }}
のなかにdata()
で定義した変数を入れ込むと、自動的に値を埋め込んでくれます。
まとめます。
- Vueは
data()
の返り値であるinputText
という変数を 監視 している。 - Vueは監視している
inputText
に変更があるたびにtemplate
を描画しなおす。 -
inputText
を変更するには、displayInput
のように、クリックイベントなどに紐づく関数のなかで、this.inputText = ほげほげ
と代入するだけで良い。
長くなりましたが、これが宣言的レンダリングやリアクティブとよばれるものです。
ではチュートリアルをみてみましょう。次のようなVueファイルがあります。プレビューにはMake me dynamic!とだけ表示されています。
<script>
export default {
// ここにコンポーネントのいろんな設定をするよ
// ここにdata()をつかって、変数を監視してみて。
}
</script>
<template>
<h1>動的に描画してみて!</h1>
</template>
script
のexport default {}
内部に、次のようにdata()
関数を定義してみましょう。
data() {
return {
message: 'Hello World!'
}
}
つぎに、template
タグのh1
を次のように変更してみましょう。
<h1>{{ message }}</h1>
プレビューが変わったのがわかります。Hellow Worldというテキストを自分で変更してみましょう。変更するたびにレプビューの文字が変わるはずです。
また、{{}}
内部は通常のjsと同じようにかけます。次のようにmessage変数の文字列を逆順にして表示してみましょう。
<h1>{{ message.split('').reverse().join('') }}</h1>
step2は以上です。
Step3 属性バインディング
いままで動的にhtmlのタグ(例えばclassタグ)を変更したいとき、どううしていたでしょうか?おそらくgetElementById
でhtmlタグを取得して、.classList.add()
や.classList.remove()
を使っていたと思います。
<body>
<div id="display-text" class="text">aaa</div>
<button id="button">このテキストを隠す</button>
<style>
.text{
color: blue;
fontSize: 16px;
}
.hidden{
visibility: hidden;
}
</style>
<script>
function hideText () {
const textElement = document.getElementById("display-text");
textElement.classList.add("hidden");
}
const buttonElement = document.getElementById("button");
buttonElement.onclick = hideText;
</script>
</body>
Vueの場合はこのようにかけます。 :class="textClass"
の部分に注目してください。属性名の前にコロン(:)をつけることで、値としてdata()
で定義したリアクティブな値を指定できるようになります。つまり、textClass
という変数が変わると、自動的にclass
属性が変わってくれます。ただし、click
などのイベントリスナーの場合は、コロン(:)は使えず、代わりにアットマーク(@)を使用する必要があります。これは次のステップで詳しく扱います。
<template>
<div id="display-text" :class="textClass">aaa</div>
<button @click="hideText">このテキストを隠す</button>
</template>
<style>
.text{
color: blue;
fontSize: 16px;
}
.hidden{
visibility: hidden;
}
</style>
<script>
export default {
data(){
return {
textClass: 'text'
}
},
methods: {
hideText () {
const textElement = document.getElementById("display-text");
textElement.classList.add("hidden");
}
}
}
</script>
ではチュートリアルの課題に挑戦してみましょう。
<h1> に titleClass のデータプロパティ を値として動的の属性バインディングを追加してみましょう。正しくバインドできたら、文字が赤くなります。
これはh1タグのclass
属性とtitleClass
変数を結びつけてください、という問題です。属性バインディングをつかってうまく結びつけてみてください。
step3は以上です。
ながくなったので、記事を分割します。
Discussion