やりたいこと
コンポーネントを作っていく時に、DOMの組み立て方から、 <div>
として振舞ってほしかったり <span>
として振舞って欲しかったりと、HTMLタグのみ変えたいという事が希にあります。
同じように、同じ見た目だけど見出し要素のレベルだけ変えたい( <h1>
にしたり <h3>
にしたり)という事もあります。
これを実現するために、以下の機能を持った <HeadText>
コンポーネントを用意します。
- 使う側から見出しのテキストを指定できる
- 使う側から見出しレベルを指定できる
- 指定された見出しレベルに応じて、見出し要素
<h1>
とか<h2>
とか... が出力される
利用するもの
Vue で予約されている <component>要素
と、その is属性
を利用した、 動的コンポーネントの機能 を使います。
is属性
はコンポーネントの切り替えの例をよく見ていましたが、 <h1>
<h2>
... といったHTMLの要素も利用できるようです。
今回は、 headTagByHeadLebel()
という関数を作り、受け取った値を h
の後に文字列連結する事で、見出し要素を柔軟に出し分けられるようにしました。
※このサンプルではTypeScriptを利用しています
作ったコンポーネント
<template>
<component
:is="headTagByHeadLevel({level})"
>
{{ text }}
</component>
</template>
<script lang="ts">
import { Vue, Component, Prop } from "vue-property-decorator";
export interface HeadTextProps {
text: string;
level?: string;
}
@Component
export default class HeadText<HeadTextProps> extends Vue {
@Prop()
public text!: string;
@Prop({
default: '1'
})
public level?: string;
public headTagByHeadLevel({ level }) {
return `h${level}`;
}
}
</script>
上記にstyleを書いてあげれば、コンポーネントとしては完成です。
こうすることで、このコンポーネントを使う側(親)は以下のようなシンプルな記述でこのコンポーネントを利用して、要素を切り替えられます。
<template>
<div class="container">
<section>
<h1>HeadTextコンポーネント</h1>
<HeadText text="ここはh1で指定" level="1" />
<HeadText text="ここはh2で指定" level="2" />
<HeadText text="ここはh3で指定" level="3" />
<HeadText text="ここはh4で指定" level="4" />
<HeadText text="ここはh5で指定" level="5" />
<HeadText text="ここは指定なし" />
</section>
</div>
</template>
<script lang="ts">
import { Vue, Component } from "vue-property-decorator";
import HeadText from '../components/HeadText.vue';
@Component({
components: {
HeadText
}
})
export default class indexPage extends Vue {}
</script>
スタイルを設定し、表示確認をしてみます。
見た目は同じで、きちんとHTMLタグが切り替わっている事が確認できました。(見出しを h1
にしちゃったので h1
が2つという状態になってますが...)
さいごに
今回は見出し要素の出し分けでしたが、冒頭のような <div>
<span>
の切り替えであれば、同じようにそれぞれ動的にバインドされた関数で、判定してあげて要素を返してあげるとよさそうです。
今回試したものについて、 github に置きましたので、載せておきます。
https://github.com/aktuehr/learn-nuxt