以前、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” とかで行けそうですが、何かと面倒そうだったのでやめました…。