Vue.jsで組み込みおよびカスタムディレクティブを使用する方法

提供:Dev Guides
移動先:案内検索

著者は、 Write for DOnations プログラムの一環として、 Open Sourcing MentalIllnessを選択して寄付を受け取りました。

序章

フロントエンドフレームワークとして、Vue.jsReactAngularの混合物と考えることができます。 VueはReactのprop主導のアプローチを採用していますが、Angularによって普及したディレクティブも使用しています。 このコンテキストでは、ディレクティブは、開発者がHTMLテンプレート内で使用できるコードまたはロジックの再利用可能なチャンクです。 これらを使用すると、要素を条件付きでレンダリングしたり、イベントを要素に接続したり、Vueコードに依存する動的属性を作成したりするなど、さまざまな方法でHTMLを操作できます。

このチュートリアルでは、v-ifv-showv-onv-bind、[ X136X] 、およびv-html。 これらの最初のセクションでは、チュートリアルで、VueシングルファイルコンポーネントプレイグラウンドなどのオンラインVueプレイグラウンドで実行できる例を紹介します。 これに加えて、新しいVueプロジェクトを作成して、追加機能のためにHTML要素に追加できるカスタムディレクティブを試してみます。

前提条件

v-ifv-else、およびv-else-ifディレクティブの使用

Vue.jsには、開発者がフレームワーク内で作業するときに一般的に使用するいくつかのディレクティブがあらかじめパッケージ化されています。 v-ifv-showv-onv-modelv-bindv-htmlなどのディレクティブがすべて提供されますすぐに使えるあなたのために。 これらの提供されるディレクティブはすべて、v-で始まります。

v-ifv-else、およびv-else-ifディレクティブを使用すると、条件付きでレンダリングされたHTML要素を作成でき、JavaScriptの if、else if、else条件と同様に機能します。 。 JavaScriptのようにHTMLまたはコードを返す代わりに、Vueはそのコードブロックを条件付きでレンダリングします。

Vueディレクティブを適用するには、Vue単一ファイルコンポーネントtemplateセクションのHTML要素に追加します。 たとえば、v-ifディレクティブを段落要素に追加する場合は、次の構文を使用します。

<p v-if="condition"></p>

この場合、強調表示されたconditionは、段落要素がレンダリングされるかどうかを決定するブール式のプレースホルダーです。

v-ifディレクティブが実際の状況でどのように機能するかを説明するために、ユーザーウェルカムページ用に次のコードを作成します。

<template>
  <p v-if="user.firstName && user.lastName">
    Welcome, {{ user.firstName }} {{ user.lastName }}!
  </p>
  <p v-else-if="user.username">
    Welcome, {{ user.username }}!
  </p>
  <div v-else>
    <button>Login</button>
    <button>Create Account</button>
  </div>
</template>

<script setup>
    const user = {
    firstName: 'Sammy',
    lastName: 'Shark',
    username: 'sammyDO'
  }
</script>

このコードには、2つの<p>タグと2つのボタンを持つ<div>タグを含む、多数のHTML要素があります。 ただし、このコードがブラウザーで実行されると、trueと評価される条件に応じて、これらのコードのチャンクの1つだけがレンダリングされます。 false条件のHTMLは、DOM(Document Object Model)ではレンダリングされません。

現在のように、firstNamelastNameの両方が<script>タグに値を持っているため、式user.firstName && user.lastNametrueと評価されます。ブラウザが段落をレンダリングします。 これは、ブラウザで次の画像のようになります。

firstNameまたはlastNameのいずれかが定義されていない場合、条件はfalseと評価され、Vueはv-else-ifディレクティブに移動します。 このディレクティブはuser.username式に付加されているため、これがtrueと評価されると、付加された段落要素がレンダリングされます。 これを試すには、<script>タグのfirstNameを削除します。

...
<script setup>
    const user = {
    lastName: 'Shark',
    username: 'sammyDO'
  }
</script>

条件user.firstName && user.lastNamefalseと評価されますが、user.usernametrueと評価されるため、代わりにユーザー名がレンダリングされます。 これを次の画像に示します。

最後に、すべての条件がfalseと評価された場合、制御はv-elseディレクティブに渡されます。このディレクティブは、ログインまたはアカウントを作成するための2つのボタンをレンダリングします。 これを試すには、script要素のusernameデータを削除します。

...
<script setup>
    const user = {
    lastName: 'Shark',
  }
</script>

これで、ブラウザに表示されるデフォルトのボタンが見つかります。

v-else-ifまたはv-elseディレクティブの直前に、v-ifディレクティブを持つ要素が必要であることに注意してください。 そうしないと動作しません。

例として、次のコードスニペットは無効と見なされ、ブラウザのコンソールでエラーが発生します。

<template>
  <p v-if="user.firstName && user.lastName">
    Welcome, {{ user.firstName }} {{ user.lastName }}!
  </p>
  <p v-else-if="user.username">
    Welcome, {{ user.username }}!
  </p>
  <h1>Some Title</h1>
  <div v-else>
    <button>Login</button>
    <button>Create Account</button>
  </div>
</template>

<script setup>
    const user = {
    firstName: 'Sammy',
    lastName: 'Shark',
    username: 'sammyDO'
  }
</script>

v-else-ifディレクティブのある段落の後の<h1>要素にはディレクティブがないため、このコードはレンダリングに失敗し、次の構文エラーが発生します。

OutputSyntaxError: v-else/v-else-if has no adjacent v-if.

このv-ifの要約をカバーしたので、HTML要素を条件付きで表示する別の方法であるv-showディレクティブを試すことができます。

v-showディレクティブの使用

v-if関連のディレクティブの他に、条件に基づいてHTML要素を表示するために使用できる別のディレクティブがあります。 そのディレクティブはv-showです。 v-ifに似ていますが、else-ifelseに対応するものがなく、要素が条件付きでレンダリングされるのではなく、条件付きで表示される点が異なります。

前のセクションと同様の状況に対処する次のコードを見てください。

<template>
  <div v-show="!userIsLoggedIn">
    <button>Login</button>
    <button>Create Account</button>
  </div>
  <div v-show="userIsLoggedIn">
    <p>Welcome!</p>
  </div>
</template>

<script setup>
    const userIsLoggedIn = true
</script>

このコードでは、条件式とともにv-showを2つの<div>にアタッチしています。 v-showは、引用符で囲まれた条件が満たされた場合に、添付されたHTMLを表示します。 この例では、userIsLoggedIntrueと評価されるため、ブラウザは[X103X]とWelcome!段落を表示します。

次に、userIsLoggedInの値をfalseに変更します。

...
<script setup>
    const userIsLoggedIn = false
</script>

ログインボタンが再び表示されます。

v-ifv-showの違いを強調する価値があります。 v-ifは条件付きでHTMLをレンダリングします。 条件式がfalseと評価された場合、DOMにはそれがまったく含まれません。 一方、v-showは、常にDOMでHTMLをレンダリングします。 ただし、要素はdisplay: none CSS スタイルで非表示になるため、ブラウザには表示されません。

条件付きのv-ifおよびv-showディレクティブがカバーされているので、v-onディレクティブに移動して、イベントをHTML要素に関連付けることができます。

v-onディレクティブの使用

v-onディレクティブは、特定のイベントで関数を実行します。 これは、カスタムイベント、またはclickhovermouseenterなどの標準のJavaScriptイベントにすることができます。 v-onディレクティブを使用する場合は、コロン(:)の後にイベントタイプと実行する関数を指定する必要があります。 コンポーネントの関数名は、引用符の間にあります。

この例として、次の強調表示されたコードを調べます。

<template>
  <button v-on:click="handleClick">Click Me</button>
</template>

<script setup>
    function handleClick() {
    alert('You clicked the button!')
  }
</script>

この例では、ユーザーがディレクティブがアタッチされている<button>要素をクリックすると、コンポーネント関数handleClickが実行されます。 このコードを実行してボタンをクリックすると、ボタンをクリックしました!というアラートが表示されます。

v-onディレクティブを使用するイベントでは、イベント修飾子をイベント自体にチェーンすることもできます。 これらのイベント修飾子は、イベントの実行方法を変更でき、通常はJavaScriptの複数行を必要とする機能を作成する際の時間を節約できます。 Vueが提供するいくつかの修飾子は次のとおりです。

  • once:イベントが1回だけ発生するように制限します。
  • self:イベントは、イベントターゲットがディレクティブを保持する要素と同じである場合にのみトリガーされます。
  • prevent:イベントの発生を停止します。
  • stop:イベントの伝播を停止します。

次に、onceイベント修飾子の例を実行して、構文を試します。 次の強調表示されたコードを前のスニペットに追加します。

<template>
  <button v-on:click.once="handleClick">Click Me</button>
</template>
...

.once修飾子を使用すると、関数handleClickは1回だけ実行されます。 Click Me ボタンをクリックしてみると、アラートがポップアップ表示されます。 アラートをクリアしてから、もう一度クリックします。 イベントはすでに1回発生しているため、発生しません。

v-onディレクティブにも省略構文があります。 省略構文を使用するには、v-on:@に置き換えます。

<template>
  <button @click.once="handleClick">Click Me</button>
</template>
...

これにより、v-on:click.onceと同じ動作になります。

イベントがv-onで対処されたので、v-bindおよびv-modelを使用してデータをテンプレート要素にバインドすることに進むことができます。

v-bindおよびv-modelディレクティブの使用

Vue.jsはModel-View-ViewModel(MVVM)フレームワークです。つまり、個別のデータ(モデル)がHTML(ビュー)を更新し、ビューがモデルを更新します。 この分離は、ビュー、またはブラウザーでレンダリングされるものが、データ処理とは独立して動作できることを意味します。

MVVMアプローチを制定するために、Vueは、データ、小道具、および計算されたプロパティをVueコンポーネントに渡す方法を提供します。 これは、双方向データバインディングを使用して実行されます。これにより、ビューとモデルが相互に対話できるようになります。

次のコードでは、データ値に応じて変化する動的コンテンツを持つ<p>要素があります。

<template>
  <p>I am from {{ city }}.</p>
</template>

<script setup>
    const city = 'Cincinnati'
</script>

このスニペットでは、テンプレート:Cityは、その後の<script>要素のcity定数へのデータ参照です。 現在のように、テンプレート:Cityは文字列"Cincinnati"に評価され、 I am fromCincinnatiという単語を含む段落要素がブラウザに表示されます。 CincinnatiSeattleに変更すると、それに応じてテンプレートのテンプレート:Cityが更新されます。

この動的コンテンツの場合、ディレクティブを使用する必要はありません。テンプレートはcity定数に自動的にアクセスできます。 ただし、<script>データを参照してHTML属性を動的にする場合は、データをv-bindで明示的にバインドする必要があります。

これを説明するために、テンプレート:Cityプレースホルダーをリンク(<a>)タグで囲み、city定数。 まず、テンプレート:City<a>タグでラップして、ユーザーがそれをクリックして都市自体の詳細情報を取得できるようにします。 その後、wikipediaLinkという計算プロパティを作成し、適切なURLを返すようにします。 強調表示されたコードを追加します。

<template>
  <p>I am from <a href="">{{ city }}</a>.</p>
</template>

<script setup>
  import { computed } from 'vue'
  
    const city = 'Cincinnati'
  const wikipediaLink = computed(() =>`https://en.wikipedia.org/wiki/${city}`)
</script>

<script>要素で、Vueライブラリからcomputed関数をインポートし、それを使用してwikipediaLinkにURLを割り当てました。 URL文字列は、テンプレートリテラルを使用して、cityの値に応じて変更します。

ウィキペディアのリンクができたので、先に進んで、計算されたプロパティ名を、前に追加したアンカータグのhref属性に追加します。

<template>
  <p>I am from <a href="wikipediaLink">{{ city }}</a>.</p>
</template>
...

この時点でこれをブラウザで表示すると、コンソールエラーが発生します。 これは、現在Vue.jsがwikipediaLinkを文字列リテラルと見なしているためです。これは有効なURLではありません。

wikipediaLink計算プロパティの戻り値を使用するようにVue.jsに指示するには、v-bindディレクティブを使用する必要があります。 これにより、次のように、テンプレート内の参照が計算されたプロパティにバインドされます。

<template>
  <p>I am from <a v-bind:href="wikipediaLink">{{ city }}</a>.</p>
</template>
...

これで、hrefの値がシンシナティウィキペディアページのURLになります。 このURLは、cityプロパティがシアトルなどの別の都市に変更された場合に更新されます。

v-onと同様に、v-bindにも、使用することを選択できる省略形があります。 省略形を使用するには、次のように、v-bind::に置き換えます。

<template>
  <p>I am from <a :href="wikipediaLink">{{ city }}</a>.</p>
</template>

Vue.jsには、値をdataプロパティにバインドするために使用される別のディレクティブがあります。 ただし、このディレクティブはinputタグに対してのみ機能します。

<template>
  <input v-model="city" type="text" />
</template>

<script setup>
  const city = 'Cincinnati'
</script>

v-modelディレクティブを使用する場合、入力フィールドvalue属性を引用符で囲まれたデータプロパティにバインドします。 フォーム<input />タグには、v-bindではなくv-modelディレクティブを使用することをお勧めします。

このVueコンポーネントは、次の画像に示すように、デフォルトのテキストCincinnatiでテキスト入力ボックスをレンダリングします。

このセクションでは、HTML属性を変数データまたは計算データにバインドするさまざまな方法について説明しました。 次に、v-htmlディレクティブを使用して、テンプレートにHTMLを挿入します。

v-htmlディレクティブの使用

このチュートリアルで取り上げる最後のパッケージ済みディレクティブはv-htmlです。 このディレクティブは、文字列リテラル内のHTMLをブラウザが読み取るための生のHTMLに変換します。これにより、HTMLの作成方法と適用方法をより柔軟に設定できます。

この架空のコンポーネントには、dataプロパティを値として持つv-htmlディレクティブを持つ<div>があります。

<template>
  <div v-html="someHtmlCode" />
</template>

<script setup>
  const someHtmlCode = `<p>Some <span>HTML</span> in this string</p>`
</script>

v-htmlディレクティブは、someHtmlCodeデータ参照の文字列をテンプレートの<div />に挿入するようにVue.jsに指示しています。 Vueでコンパイルすると、DOMに次のように表示されます。

<div>
  <p>Some <span>HTML</span> in this string</p>
</div>

HTMLはブラウザでもレンダリングされます。

このディレクティブは、RESTAPIサービスからのHTMLまたは外部JavaScriptファイルからの大きなHTMLをレンダリングする必要がある場合に役立ちます。

チュートリアルのこの時点で、Vue.jsによって提供されるディレクティブを試しました。 ただし、Vueが提供しないディレクティブが必要になる場合があります。 このような場合、HTMLテンプレートの特定のロジックを処理するカスタムディレクティブを作成できます。

カスタムディレクティブの作成

Vue.jsフレームワークでは、プロジェクトの個々のニーズに合わせてカスタムディレクティブを作成することができます。 たとえば、このセクションでは、テンプレートの要素に特定のスタイルを適用するv-themeディレクティブを作成します。

この時点までは、スタンドアロンのVueプロジェクトをフォローする必要はありませんでした。 ただし、このセクションでは、VueCLIから生成された新しいプロジェクトを作成します。

ターミナルを開き、次のコマンドを使用して新しいプロジェクトを生成します。 このプロジェクトの名前はcustom-directiveになります。これは、ルートディレクトリの名前にもなります。

vue create custom-directive

このチュートリアルでは、Choose Vue Versionに対してVue 3xを選択します。 アプリが作成されたら、選択したテキストエディタで生成されたプロジェクトを開きます。 次に、srcディレクトリにあるmain.jsファイルを開きます。

まず、このファイルを設定します。 createApp(App)constに保存して、後で参照できるようにします。

custom-directive / src / main.js

import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App)

app.mount('#app')

これで、createApp関数が独自のconstに組み込まれたので、ディレクティブを追加してこのアプリを拡張できます。

custom-directive / src / main.js

import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App)

app.directive("theme", {})

app.mount('#app')

このコードでは、Vueインスタンスのdirective()関数を利用しています。 この関数は、ディレクティブ名(この場合はtheme)とライフサイクルフックを持つオブジェクトの2つの引数を受け入れます。

このコードは、コンポーネントがmountedのときに実行されるように設定します。 このマウントされたフックは、HTML要素であるelと、ディレクティブに渡される値であるbindingの2つの引数を受け入れます。 この情報を使用して、以下を作成できます。

custom-directive / src / main.js

const app = createApp(App)

app.directive("theme", {
  mounted(el, binding) {

  }
})

app.mount('#app')

このthemeディレクティブでは、要素のスタイルを決定するために文字列を渡します。 この文字列は、primarysecondary、またはtertiaryのいずれかになり、それぞれが仮想のカラースキームの色に対応します。

ディレクティブコードが配置されたので、ロジックを追加できます。 ディレクティブのクォータマーク内の値にアクセスするには、binding.valueを使用できます。 要素のテキストの色を変更するには、JavaScriptを使用してelプロパティにアクセスします。

custom-directive / src / main.js

const app = createApp(App)

app.directive("theme", {
  mounted(el, binding) {
    if (binding.value === 'primary') {
      el.style.color = 'red'
    } else if (binding.value === 'secondary') {
      el.style.color = 'green'
    } else if (binding.value === 'tertiary') {
      el.style.color = 'blue'
    } else {
      el.style.color = 'black'
    }
  }
})

app.mount('#app')

このスニペットで強調表示されているセクションは、一連のif /elseステートメントです。 ディレクティブに渡される値がprimaryの場合、テキストの色はredsecondarygreentertiaryblueであり、デフォルトのblackに戻る値はありません。

main.jsファイルを閉じて保存します。

この時点で、Vue.jsアプリケーションで使用できるカスタムディレクティブを作成しました。 Vueはディレクティブ名の前にv-を自動的に付けるため、テンプレートはv-themeとしてディレクティブにアクセスできます。

選択したテキストエディタでApp.vueファイルを開きます。 テンプレートに、テキストを含む<p>タグを追加します。

custom-directive / src / App.vue

<template>
  <p>This text will change color based on the directive value!</p>
</template>

このファイルを保存し、npm run serveでアプリケーションを起動します。 これにより、localhost:8080ポートでプロジェクトが実行されます。

npm run serve

生成されたプロジェクトを表示するには、選択したブラウザを開き、URLバーのlocalhost:8080にアクセスします。 段落要素が黒でレンダリングされています。

次に、ディレクティブをHTMLに追加して、色を変更します。

custom-directive / src / App.vue

<template>
  <p v-theme="`primary`">This text will change color based on the directive value!</p>
</template>

このファイルを保存して、Webブラウザで開きます。 引用符内の値は生の値であり、自動的にVueにバインドされるため、引用符内では、バックティックを使用してprimaryをラップして文字列に変換する必要があります。

ファイルを保存すると、レンダリングされたサイトのテキストが赤に変わります。

ディレクティブはbindingオブジェクトの値を読み取り、それに応じてコードを実行します。 値がprimaryであるため、JavaScriptはテキストの色を赤に変更します。

このセクションでは、カスタムディレクティブを作成して登録し、そのロジックを実行しました。 また、新しいカスタムディレクティブを追加し、それをテンプレートのHTML要素に割り当てました。

結論

このチュートリアルでは、演習を実行して、ディレクティブとは何か、およびそれらの使用方法をテストしました。 具体的には、v-ifv-onv-showv-htmlなどの最も一般的な組み込みディレクティブを使用しました。 これに加えて、独自のカスタムディレクティブを登録して作成しました。 このディレクティブv-themeは、JavaScript関数を実行するために任意のHTML要素で使用できるようになりました。

いくつかのディレクティブを確認しましたが、Vue.jsによってさらに多くのディレクティブが利用可能になりました。 ディレクティブの詳細については、公式のVue.jsドキュメントを確認することをお勧めします。 Vueのその他のチュートリアルについては、Vue.jsシリーズページを使用してWebサイトを開発する方法を確認してください。