Vue.js を Angular と比較しながら学ぶメモ
目的:Vue.js (v3) のドキュメントを読みながら構文を理解する。
もともとAngularは使ったことがあるので、Angularと比較しながら理解を深めていきたいと思います。
テンプレート構文
テキスト展開
変数をHTML内で展開するためには、2重中括弧{{}}
を利用する。
<span>Message: {{ msg }}</span>
Angularの場合
Angularでも同様。
<h3>Current customer: {{ currentCustomer }}</h3>
生のHTML
プレーンテキストではなくHTMLとして出力したい場合はv-html
ディレクティブを利用する。
<p>Using v-html directive: <span v-html="rawHtml"></span></p>
XSS脆弱性の危険があるため、信頼できるコンテンツにのみ利用し、ユーザーが生成したコンテンツでは決して利用しないこと。
Angularの場合
プロパティバインディングを用いてinnerHTML
プロパティに値をセットする。
<p [innerHTML]="rawHtml"></p>
属性バインディング
v-bind
ディレクティブを用いてHTML要素の属性とバインディングする。
<div v-bind:id="dynamicId"></div>
省略記法
<div :id="dynamicId"></div>
バインディングされた値がnull
orundefind
の場合、属性はレンダリングから外れる。
Angularの場合
プロパティバインディングでattr.
という接頭辞をつける
<div [attr.id]="dynamicId"></div>
ディレクティブ
v-
という接頭辞を持つ特別な属性のこと。Vue.js で用意されている組み込みディレクティブは以下。
例:v-bind
, v-html
, v-on
など。
名前、引数、修飾子、値からなる。
<名前>:<引数>.<修飾子>=<値>
v-on:submit.prevent="onSubmit"
Angularの場合
ngClass
, ngStyle
, ngModel
, *ngIf
, *ngFor
など。
組み込みディレクティブは以下。
自分でディレクティブを定義することができる。
リアクティビティーの基礎
2つのAPIタイプが存在し、コードの記述方法が異なる。
- Options API
- コンポーネントのインスタンスを中心とした記述方法
- 記述方法がシンプルで初心者にとって分かりやすい
- Composition API
- リアクティブな状態変数を宣言し、複数の関数の組み合わせによって複雑な処理を行う、という考え方
- 自由度が高いが、どのような仕組みで動いているか理解する必要がある
Angularの場合
Angularはコードの記述方法は統一されている。
Vue.jsのComposition APIは RxJS
と同じようなもの(だと思われる)
まずは、Options API のスタイルで学ぼうと思います。
リアクティブな状態の宣言
data
オプションを用いて、コンポーネントのリアクティブな状態(変数)を宣言します。
export default {
data() {
return {
count: 1
}
},
// `mounted` は、後で説明するライフサイクルフックです。
mounted() {
// `this` は、コンポーネントのインスタンスを指します。
console.log(this.count) // => 1
// データは、変化することがある。
this.count = 2
}
}
data
オプションが返すオブジェクトに状態を含めることで、リアクティブな処理を行うことができる。
インスタンスが生成されたときにのみ追加されるので、必要ならばnull
やundefind
を用いてまだ利用できない状態を宣言する。
Angularの場合
コンポーネントクラスのプロパティとして定義すれば良い。
@Component({
selector: 'app-hero-list',
templateUrl: './hero-list.component.html',
providers: [ HeroService ]
})
export class HeroListComponent {
heroes: Hero[] = [];
selectedHero: Hero | undefined;
}
メソッドの宣言
methods
オプションを利用して、インスタンスにメソッドを追加する。
export default {
data() {
return {
count: 0
}
},
methods: {
increment() {
this.count++
}
},
mounted() {
// メソッドは、ライフサイクルフックで呼び出すこともできますし、他のメソッドでも呼び出せます!
this.increment()
}
}
methods
のthis
は自動的にコンポーネントインスタンスを参照する。よって、methods
を定義する際にアロー関数を用いてはならない。
export default {
methods: {
increment: () => {
// BAD: ここでは `this` アクセスができません!
}
}
}
コンポーネントのテンプレート内からアクセスすることができる。
<button @click="increment">{{ count }}</button>
Angularの場合
こちらもComponentクラス内で宣言すれば良い
@Component({
selector: 'app-hero-list',
templateUrl: './hero-list.component.html',
providers: [ HeroService ]
})
export class HeroListComponent {
heroes: Hero[] = [];
selectedHero: Hero | undefined;
selectHero(hero: Hero) { this.selectedHero = hero; }
}