Vue.js コンポーネントの中のテンプレートで配列のオブジェクトのリンクを表示する

以前、Vue.jsを使って、下記のようなことをしましたが、「早いもんだぜ」でもう1年が経ちました。

私ってめちゃくちゃ忘れっぽいんですよ。健康だってことですかね?つまり、Vueのことについてカケラも覚えていませんでした…。

特に時間がかかったのが、
「リンクを作る」
ところです。

「エッツ そんなのちょちょいとできないの?」

と思われると思いますが、できなかったんですよ。

前置き長いですが、本題に入ります。ちなみに、この度のケースでは、Nuxtとかで使っているわけではなく、Vueをパーツで使っています。Routerとかを使うわけではありません。

今回はVue.jsでリンク、つまり<a>タグの”href”属性を作ることをやります。

下記は、まだリンクがありません。

<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <script src="https://unpkg.com/vue@2.5.17"></script>
</head>

<body>

<div id="fruits-component">
  <ol>
    <fruits-component v-for="eachFruit in fruitsItems" :key="eachFruit.name" :fantastic-fruit="eachFruit">     	
    </fruits-component>
  </ol>
</div>

<script>

let fruitsItems= [
    {name:'りんご', id:'101'}, {name:'バナナ',id:'102'}, {name:'なし',id:'103'}
  ];


let fruitsComponent = Vue.component('fruitsComponent',{
		props: {
			  'fantasticFruit': { 
			      type: Object, 
			      required: true 
			    }
			  },

		template: ' <li>{{fantasticFruit.name}}</li>',
});

new Vue({
	
  el: '#fruits-component',
  data: { fruitsItems  },
  components: {
	    'fruitsComponent': fruitsComponent,
	  }
  
})

</script>
</body>

上記の解説です。

①データは [{name:’りんご’, id:’101′}, {name:’バナナ’,id:’102′}, {name:’なし’,id:’103′}] となっています。3つのオブジェクトが一つの配列に入っています。

②コンポーネントという仕組みを使っています。
HTMLタグでは<fruits-component> </fruits-component>で表現されるところがコンポーネントの中身になります。
わかりにくい部分なんですが

<fruits-component v-for="eachFruit in fruitsItems" :key="eachFruit.name" :fantastic-fruit="eachFruit">         
</fruits-component>

ってなっている、:fantastic-fruit=”eachFruit” が、v-forで回しているeachFruitを fruits-component コンポーネントのfantastic-fruitに結びつけています。データバインディングのディレクティブというやつです。
:fantastic-fruit

v-bind:fantastic-fruit
の略です。詳しくは、本家サイトをご覧ください。

https://v1-jp.vuejs.org/guide/syntax.html

③ fruits-component コンポーネントのfantastic-fruitに結び付いたデータを、コンポーネント内のテンプレート構文で出力します。
template: ‘ {{fantasticFruit.name}}’ の部分ですね。

正直なところ、同じデータの参照を、いろいろな名前で呼んでいるので、わかりにく…って思います。(もっとスッキリするやり方があれば教えてください。)

さてさて、本題の<a>リンクの出力に行きます。

コンポーネントのテンプレート部分だけ変更します。

let fruitsComponent = Vue.component('fruitsComponent',{
		props: {
			  'fantasticFruit': { 
			      type: Object, 
			      required: true 
			    }
			  },

		template: '<li><a href="{{fantasticFruit.id}}.html">{{fantasticFruit.name}}</a></li>',
});

これで<a>リンクができたように見えますが、実はできてません。出力されたHTMLを見ると、下記のようになっています。

<a href="{{fantasticFruit.id}}.html">りんご</a>

ふぇぇ~なんで~(>_<)

となりますが、XSSを防ぐために、このようになっているようです。(すみません、Vue関連のどっかのサイトで見た気がするのですが、リファレンスがわからなくなってしまいました…。)

一つの手段は、computed という機能を使うことです。fruitsComponentの中身だけ、次のように書き換えます。

let fruitsComponent = Vue.component('fruitsComponent',{
		props: {
			  'fantasticFruit': { 
			      type: Object, 
			      required: true 
			    }
			  },

		template: '<li><a :href="fruitURL">{{fantasticFruit.name}}</a></li>',
		computed:    {
			  fruitURL: function () {
			      return this.fantasticFruit.id + ".html";
	    	  }
		}
});

:href=”fruitURL” とやっているところで、hrefという属性に、fruitURLを紐づけています。前述もしました、データバインディングです。

computedの中から、popsにあるデータにアクセスするときは

this.fantasticFruit.id

.html の部分が必要なければ単純に、テンプレートの中身を

template:'{{fantasticFruit.name}}',

としてもできます。が、この中にjavascriptの文字列が書けるようなので、+”html” とかで行けそうですが、何かと面倒そうだったのでやめました…。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です