1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Vue+Vuetify+αで実装するSEOに適した無限スクロールの作り方

Last updated at Posted at 2021-08-17

はじめに

無限スクロールとは、TwitterやPinterestなどのSNSに代表されるような、ユーザーのスクロールに応じて続きのコンテンツが読み込まれ、ページ遷移を行わせることなくコンテンツを次々と表示させる技術ですが、Googleによれば無限スクロールはSEOやユーザービリティ対策として、ページの分割が可能なような仕様になるように推奨されています。

すなわち
http://example.com/?page=1
http://example.com/?page=2
などといった具合に分割して複数のページに分けることを出来るようにすることがよいというわけです。

実際無限スクロールを運用するに当たってはAjaxで一定の項目毎に取得すると思いますが、その取得するタイミングをページと見立て、読み込みが終わったタイミングで「History API」の pushState() や replaceState()を使ってURLを書き換えるのが一番簡単です。

しかし、項目の読み込みが遅い等の理由で無限スクロールのライブラリの発火ポイントを前めにするとURLの書き換えが早すぎたり、ページをバックしててURLが書き込まれないなどの不都合があります。
最初はスクロールした位置を取得してどうにかしようと悪戦苦闘をしましたが上手くいかずに、intersection-observerを活用するようにしました。

#実装

See the Pen Vue+Vuetify+αで実装するSEOに適した無限スクロールの作り方 by emesh (@emesh) on CodePen.

まず、上をご覧下さい。jsfiddleの仕様ではURLは変更できないのでヘッダーにページ数が出ていますが、ある程度ページが進むとページ数が変わっているのがおわかりかと思います。なお、無限スクロールにはVueの定番ライブラリのvue-infinite-loadingを、UIフレームワークとしてVuetyfyを採用しています。

##しくみ

  <div :data-src = "index" v-intersect="onIntersect"></div>

まずこのコードでJavaScriptに現在の位置を教えるコードになっています。私はVuetifyのIntersection Observer APIを使用しており、これはv-intersect="実行したい関数"を書くと容易にビューポート内に要素が来たときに発火するコードが実現可能です。リンク先のサンプルをみたら解るとおり、赤い点をスクロールするとビューポート内にカードが来たら色が緑に変更になる様子が見て取れます。

なお、v-for="(res,index) in items"のようにv-forには必ず配列のインデックスを加えてください。

onIntersect.js
//ページの取得
onIntersect (entries, observer) {
    let res = {
            'ratio' : entries[0].intersectionRatio > 0,
            'dataSet': Number(entries[0].target.attributes['data-src'].value),
        }

    if(res.ratio && res.dataSet){
        //ページを算定
        let nowPage = Math.floor(res.dataSet / this.display) + 1 + this.firstPage

        //URLを取得
        let url_path = new URL(location.href);
        
        //1ページ以内ならpageを消す
        if(nowPage > 1){
            url_path.searchParams.set("page", nowPage)
        }else{
            url_path.searchParams.delete("page")
        }
        //WebApiに代入
        history.replaceState(null,null,url_path.toString());     
    }
},

次にJavaScript内ですが、res引数でintersectからの情報を引き出します。res.dataSetで配列のインデックスを取得しており、必ず数字形に変換し計算で現在のページを求め、それをURLクエリパラメーターに代入しreplaceStateを行っております。

注意点

今回は省きましたが、途中のページから読み取る実装の場合にはページ数を設定数する項目でthis.firstPage変数で初期のページ数を記憶させる必要があります。

おわりに

以上簡単にSEO対策をした無限スクロールを紹介しました。多くの作例もありますが、リスト形式ではないグリッドのような複雑な無限スクロールだと高さが動的に変化することもあり、数日思案しておりましたがこのような比較的シンプルな作りにたどり着いたのは大変良かったと思います。皆様のご参考になれば幸いです。

参考文献

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?