Vueでアクセス制限をかけるコンポーネントを実装
Vueで実装しているページにアクセス制限をかけたくなったことはありませんか?
閲覧するのにユーザーの権限が必要なページ、非公開コンテンツのページなど通常見せてはいけないページにアクセスされた場合は何らかの対応が必要ですね。
エラー画面に遷移させる、違うコンテンツを表示するなど画面にアクセスしたときに特定の処理を挟むためにはどうすればいいのか。
今回はVueでそんな場合のアクセス制限をかける方法を紹介します。
slotを使う方法
まずはslotを使いアクセスに可能な場合にはv-ifをtrueにすることで要素を表示できるようにする方法です。
アクセス判定に必要なpropsを受け取り、アクセス可能かどうかcomputedで返しています。
computedの値はslotを囲うdivにつけて内容が見えないようにします。
<template>
<div v-if="isPermit">
<slot/>
</div>
</template>
<script>
export default {
props: {
example: {
// サンプル用のprops
type: Object
}
},
computed: {
isPermit() {
return false;
}
}
};
</script>
この方法はslotを囲むためのdivが必要になります。
ほとんどのアプリケーションでは問題ないと思いますが、もしもdivが増えるのが困る場合は後に紹介するFunctionalオプションを使う方法を試してみてください。
アクセス可能時とコンテンツを出し分ける
もしアクセス可能ではない場合にはv-ifで出し分けます。
アクセス許可されていない場合はslotのコンテンツではなく独自のコンテンツを表示することで、ユーザーに状態を伝えることができます。
<template>
<div>
<div v-if="isPermit">
<slot/>
</div>
<div v-if="!isPermit">
コンテンツにアクセスする権限がありません。
</div>
</div>
</template>
アクセス不可能な場合にリダイレクトする
場合によってはコンテンツを表示しない、違うコンテンツを表示する以外にもリダイレクトしたいという場合もあると思います。
その時はmountedでアクセス許可されていない場合にlocationやvue-routerを使っている場合は$routerを使って任意のURLに遷移させます。
mounted() {
if (!this.isPermit) {
location.href = 'リダイレクト先'
}
}
Functionalオプションを使う方法
Vueではtemplateタグを使ってテンプレートを記述するのが一般的ですが、render関数を使ってjsxのように記述できます。
functionalコンポーネントについて説明すると、長くなってしまうので今回は詳細な説明はしません。
もし気になる人はvueの公式ドキュメントを見てみてください。
render関数を使ってアクセス制限するメリット
vueの一般的な記述であるslotを使ってアクセス制限できるなら、わざわざrender関数を使う必要はないんじゃないのか?と思います。
ですがrender関数を使うと嬉しいメリットがあります。
それは余計なdivで囲む必要がなくなるということです。
まずはrender関数を使ってアクセス制限するコードは下記です。
<script>
export default {
functional: true,
props: {
example: {
// サンプル用のprops
type: Object
}
},
render(h, context) {
// context.propsを使いアクセス可能か判定
if (true) {
return context.children;
} else {
// アクセスを弾く処理
}
}
};
</script>
rebder内のcontext.childrenがtemplateで言うところのslotのようなものです。
Reactをやったことある人はchildrenは馴染みがあるかもしれません。
context.childrenをrenderでreturnすることでtemplateではできなかったslotのあたる部分だけをレンダリングできるようになっています。
TypeScriptを使う場合はVNodeをreturnする
TypeScriptでのrender関数の返り値はVNodeです。(VNode[]
も可能)
ですがrender内でリダイレクトしようとした場合には型ではundefinedが返却されることになります。
その際にコンパイルエラーが発生してしまうので、リダイレクト後に空のdivを返却することで回避できます。
render(h, context): VNode[] | VNode {
if (true) {
return context.children;
} else {
location.href = 'リダイレクト先'
return h('div')
}
}
location.hrefなどリダイレクト処理の後にh('div')
というのが空divを生成するコードです。
まとめ
Vueでアクセス制限をかける方法を紹介しました。
アプリケーションを実装する中でアクセス制限をかけたい機会は少なくないと思います。
今回紹介した方法をベースに実装をするとコンテンツの出し分けやリダイレクトなど、アクセスを許可しない場合の処理も動作させることができます。
CodeSandboxに紹介したコードを使った実装例を置いているので、よければ合わせてご覧ください。
Discussion