こんにちは。備忘録です。
ページ内にたくさんの記事があるとします。1ページに表示されている記事数は5つ。ところが一番下にある「もっと読む」というボタンをクリックすると、新たに5記事が表示される。そんな動きをしたいとします。
ところがアンカーリンクを設定しなければ、「もっと読む」をクリックしたときにページのトップに連れて行かれてしまいます。UX的には、「もっと読む」をクリックしたときは、トップに飛ばされないまま、続く5つの記事が見たいです。
こんなとき、vue.jsではscroll behaviorという機能を使って、トップに連れて行かれないよう調整することができます。
(下に来る例が上にくる例と違うので紛らわしいのですが、、、)
Step 1. RouterのJSファイルをいじる。
const router = new Router({
mode: "history",
scrollBehavior(to, from, savedPosition) { //ここでscrollを調整する。ここにはto, from, savedPositionの三つの引数が入ります。
if (savedPosition) {
return savedPosition; //戻る(👈)もしくは進む(👉)ボタンを操作したときは、デフォルトのpositionでロードしてください。
} else { //そのほかの場合はこのpositionを効かせてちょうだい。
const position = {};
if (to.hash) { //hashがあれば……
position.selector = to.hash; //positionはhashが指定したところだよ。
if (to.hash === "#animal") { //hashがanimalというidを指定しているのであれば
position.offset = { y: 200 }; //offsetを効かせてください。※ここはoffsetを効かせていますが、なんでも指定できます。
}
if (document.querySelector(to.hash)) {
return position;//hashがあれば、そのpositionを教えてください。
}
return false; //そもそもhashがなければ、デフォルトの操作をしてください。
}
}
},
routes: [
{
path: "/",
name: "Home",
component: Home,
props: true
}
});
Step 2. Scroll behavior を効かせたい instance/componentをいじる。
<section class="zoo-information">
<h1>Our Zoo</h1>
<p>{{zoo.description}}</p>
</section>
<section class="animals">
<h2>I think {{ animal.name }} is the best</h2>
<div class="cards" id="animal">
<div v-for="animal in animals" :key="animal.slug" class="card">
<router-link
:to="{
name: 'animalDetails',
params: { animalSlug: animal.slug},
hash: '#animal'
}"
> //ここにクリックしたとき、トップに行かず、#animalのところで位置をキープしたい
<img :src="require(`@/assets/${animal.image}`)" :alt="animal.name" />
<span class="card__text">{{ animal.name }}</span>
</router-link>
</div>
</div>
<router-view :key="$route.path" />
</section>
何も設定しなければ、router-link
のリンクをクリックしたとき、.zoo-information
がトップにくるようページが表示されるでしょう。でも、せっかくrouter-link
をクリックしているので、UX的にもrouter-link
をクリックしたときはrouter-link
の中身がページのトップにくるよう表示したいです。
そこでto.hash
をrouter.jsで指定しておくと、router-link
をクリックしたときにid="animal"
と書かれた部分がページのトップにくるよう位置を指定できるのです。
なかなかのツワモノです。