概要
- v-onceディレクティブ
- v-preディレクティブ
- v-htmlディレクティブ
- v-cloakディレクティブ
- v-textディレクティブ
- Javascript式
- v-bindの省略記法
様々なテンプレート制御ディレクティブを使う
- ディレクティブはプログラミングにおける「指示」を指す
色んな例
- v-once
→初回だけバインディング - v-pre
→要素とすべての子要素のコンパイルをスキップ - v-html
→プレーンなHTMLを挿入 - v-cloak
→インスタンスの準備が終わると取り除かれる - v-text
→マスタッシュ構文の代わりに
v-onceディレクティブ
- 初回だけテンプレートを評価し、それ以降は静的なコンテンツとして扱いたい
- つまり初回だけテキストバインディングを行いたい
→v-onceディレクティブを利用
例えば…
- API呼び出しなどを画面がロードされた時に行いたいが、それ以降結果は変わらないので最初の1回だけで良い、などの状況
- ページ更新のパフォーマンス向上
実際のコード
いったんボタンを押すとテキストが反転する処理を実装
<div id="app">
<p>{{ message }}</p>
<button v-on:click="clickHandler">
Click!
</button>
</div>
const app = Vue.createApp({
data: () => ({
message: 'Hello Vue.js!'
}),
methods:{
clickHandler: function(event){
this.message = this.message.split('').reverse().join('')
}
}
})
app.mount('#app')
- ボタンを押すとテキストが反転
-
this.message.split('').reverse().join('')
→反転する処理は素のjavascriptで書いている -
split('')
で各文字を分離して、それを配列に変換 -
reverse()
では配列を受けとり、その要素を逆にする -
join('')
はその配列を受け取り、その中の要素を逆にする - 文字列を反転するにはこの流れなんだな、くらいの理解でよい
p要素にv-onceディレクティブを設定する
<div id="app">
<p v-once>{{ message }}</p>
<button v-on:click="clickHandler">
Click!
</button>
</div>
- pタグに
v-once
を設定 - ページは通常通り表示される
- ボタンを押しても文字は反転しない
- クリックをしてもデータバインディングが行われない
- v-onceディレクティブは初回だけテンプレートを評価して、それ以降は静的なコンテンツとして扱うため
- 処理を減らして描画更新のパフォーマンスを上げたい時に利用できる
v-preディレクティブ
- 要素とすべての子要素のコンパイルをスキップしたい
→v-preディレクティブを使用
例など
- 生のマスタッシュ タグを表示したいとき
- ディレクティブのない大量のノードをスキップすることで、コンパイルのスピードを上げる
<div id="app">
<p v-pre>{{ message }}</p>
</div>
const app = Vue.createApp({
data: () => ({
message: 'Hello Vue,js!'
})
})
app.mount('#app')
- ↑↑↑通常であればこのように表示される
↑↑↑v-preディレクティブを追加するとこのようにマスタッシュ構文をそのまま表示できる
v-htmlディレクティブ
- プレーンなHTMLを挿入したい
→v-htmlを使用 - 指定した要素のinnerHTMLを更新できる
前提
- マスタッシュタグを使った描画ではクロスサイトスクリプティング対策としてデータオブジェクトにHTMLを入れてもHTMLとは評価されず、タグがテキストとして表示される。
- クロスサイトスクリプティング
→脆弱性のあるウェブサイトにユーザーを誘導することによりユーザー環境で不正スクリプトを実行させることができてしまうもの
通常の状態
<div id="app">
<p>{{ message }}</p>
</div>
const app = Vue.createApp({
data: () => ({
message: 'Hello <span style="color:red;">Vue,js!</span>'
})
})
app.mount('#app')
- js側にspanタグでスタイル指定したがそのままテキストで表示されている
v-htmlを使用
<div id="app">
<p>{{ message }}</p>
<p v-html="message"></p>
</div>
const app = Vue.createApp({
data: () => ({
message: 'Hello <span style="color:red;">Vue,js!</span>'
})
})
app.mount('#app')
- v-htmlを使用した箇所は色が変更されて表示されている
- v-htmlは主にサーバーサイドから取得したHTMLを表示するときに使う
注意点
- クロスサイトスクリプティング脆弱性を引き起こす可能性あり、慎重に使用する
- v-htmlディレクティブで使用するデータやテンプレートは信頼できるデータのみ使用する
- サービスを利用するユーザーが入力したコンテンツには絶対使用しない
v-cloakディレクティブ
- cloak→覆い隠すという意味
- ページを表示開始してから、インスタンスの作成が終わるまでの間に、マスタッシュタグなど、コンパイル前のテンプレートが表示されてしまうのを防ぎたい
- ページを更新したときなどに一瞬コンパイル前のマスタッシュ構文の状態がページにチラ見えしてしまう状態
<div id="app">
<p v-cloak>{{ message }}</p>
</div>
const app = Vue.createApp({
data: () => ({
message: 'Hello Vue,js!'
})
})
app.mount('#app')
[v-cloak]{
display: none;
}
- index.html側にはv-clockを指定
- cssでv-cloakを非表示にする
- こちらでちらつきはなくなる
v-textディレクティブ
- マスタッシュの代わりに、ディレクティブを使いたい
→v-textディレクティブを使用
通常
<div id="app">
<h2>Mustache</h2>
<p>{{ message }}</p>
</div>
const app = Vue.createApp({
data: () => ({
message: 'Hello Vue,js!'
})
})
app.mount('#app')
v-textを利用して同じ状態を再現する
<div id="app">
<h2>Mustache</h2>
<p>{{ message }}</p>
<h2>v-text</h2>
<p v-text="message"></p>
</div>
const app = Vue.createApp({
data: () => ({
message: 'Hello Vue,js!'
})
})
app.mount('#app')
- マスタッシュ構文と、v-textディレクティブで記述した内容が同じ表示状態
マスタッシュ構文とv-textディレクティブどちらを使うべき?
- 基本的にはどちらでもOK
- マスタッシュ構文に統一するのがおすすめ
- v-textディレクティブでは、配下のテキストをまるごと置き換えるため、テキストの一部を書き換えたい場合はマスタッシュ構文を利用する必要があるため
Javascript式を使う
- これまでのテンプレート内では単純なプロパティキーだけしようしていた
→{{ message }}
Vue.jsではデータバインディング内部でJavascript式を利用することができる
→{{ number + 1 }}
<div id="app">
<p>{{ message }}</p>
<p>{{ number + 1 }}</p>
<p>{{ message.split('').reverse().join('') }}</p>
<p>{{ ok ? 'YES' : 'NO' }}</p>
</div>
const app = Vue.createApp({
data: () => ({
message: 'Hello Vue,js!',
number: 100,
ok: true
})
})
app.mount('#app')
注意点
- 各バインディング式は単一式のみを含むことができる
- 下記はエラーとなる
<p>{{ let x = 1 }}</p>
<p>{{ if(ok){return message} }}</p>