Scrollspy

スクロール位置に基づいてBootstrapのナビゲーションまたはリストグループコンポーネントを自動的に更新し、ビューポートで現在アクティブなリンクを示すようにします。

仕組み

v-b-scrollspyディレクティブが正常に機能するには、いくつかの要件があります。

  • 現在アクティブなリンクを示す<b-nav>または<b-list-group>コンポーネントが含まれている要素/コンポーネントに適用する必要があります。
  • Scrollspyは、監視対象の要素(通常は<body>)にposition: relative;を必要とします。
  • <body>以外の要素を監視する場合は、heightが設定され、overflow-y: scroll;が適用されていることを確認してください。
  • アンカー(<a><b-nav-item><b-dropdown-item><b-list-group-item>)は必須であり、監視対象のコンテナ内のそのidを持つ要素を指すhrefhrefまたはtoプロパティを介して)が必要です。toプロパティを使用する場合は、#id-of-elementで終わるpathを設定するか、locationプロパティhash#id-of-elementに設定します。

正常に実装されると、ナビゲーションまたはリストグループがそれに応じて更新され、関連付けられたターゲットに基づいて、ある項目から次の項目にactive状態が移動します。

ナビゲーションを使用した例

<b-nav>コンポーネントでv-b-scrollspyを使用して、<b-card-body>のスクロールを監視します。ナビバーの下の領域をスクロールして、アクティブクラスが変化するのを見てください。ドロップダウン項目も強調表示されます。

<template>
  <div>
    <b-card no-body>
      <b-nav pills card-header slot="header" v-b-scrollspy:nav-scroller>
        <b-nav-item href="#fat" @click="scrollIntoView">@fat</b-nav-item>
        <b-nav-item href="#mdo" @click="scrollIntoView">@mdo</b-nav-item>
        <b-nav-item-dropdown text="Dropdown 1,2,3" right-alignment>
          <b-dropdown-item href="#one" @click="scrollIntoView">one</b-dropdown-item>
          <b-dropdown-item href="#two" @click="scrollIntoView">two</b-dropdown-item>
          <b-dropdown-divider></b-dropdown-divider>
          <b-dropdown-item href="#three" @click="scrollIntoView">three</b-dropdown-item>
        </b-nav-item-dropdown>
        <b-nav-item href="#pi0" @click="scrollIntoView">@pi0</b-nav-item>
      </b-nav>

      <b-card-body
        id="nav-scroller"
        ref="content"
        style="position:relative; height:300px; overflow-y:scroll;"
      >
        <p>{{ text }}</p>
        <h4 id="fat">@fat</h4>
        <p v-for="i in 3">{{ text }}</p>
        <h4 id="mdo">@mdo</h4>
        <p v-for="i in 3">{{ text }}</p>
        <h4 id="one">one</h4>
        <p v-for="i in 2">{{ text }}</p>
        <h4 id="two">two</h4>
        <p>{{ text }}</p>
        <h4 id="three">three</h4>
        <p v-for="i in 2">{{ text }}</p>
        <h4 id="pi0">@pi0</h4>
        <p v-for="i in 3">{{ text }}</p>
      </b-card-body>
    </b-card>
  </div>
</template>

<script>
  export default {
    methods: {
      // Convenience method to scroll a heading into view.
      // Not required for scrollspy to work
      scrollIntoView(event) {
        event.preventDefault()
        const href = event.target.getAttribute('href')
        const el = href ? document.querySelector(href) : null
        if (el) {
          this.$refs.content.scrollTop = el.offsetTop
        }
      }
    },
    data() {
      return {
        text: `
          Quis magna Lorem anim amet ipsum do mollit sit cillum voluptate ex nulla
          tempor. Laborum consequat non elit enim exercitation cillum aliqua
          consequat id aliqua. Esse ex consectetur mollit voluptate est in duis
          laboris ad sit ipsum anim Lorem. Incididunt veniam velit elit elit veniam
          Lorem aliqua quis ullamco deserunt sit enim elit aliqua esse irure. Laborum
          nisi sit est tempor laborum mollit labore officia laborum excepteur
          commodo non commodo dolor excepteur commodo. Ipsum fugiat ex est consectetur
          ipsum commodo tempor sunt in proident.
        `
      }
    }
  }
</script>

<!-- b-scrollspy-nav.vue -->

ネストされたナビゲーションを使用した例

Scrollspyは、ネストされた<b-nav>でも機能します。ネストされた<b-nav-item>がアクティブな場合、その親もアクティブになります。ナビバーの横の領域をスクロールして、アクティブクラスが変化するのを見てください。

<template>
  <b-container fluid>
    <b-row>
      <b-col cols="4">
        <b-navbar v-b-scrollspy:scrollspy-nested class="flex-column">
          <b-navbar-brand href="#">Navbar</b-navbar-brand>
          <b-nav pills vertical>
            <b-nav-item href="#item-1">Item 1</b-nav-item>
            <b-nav pills vertical>
              <b-nav-item class="ml-3 my-1" href="#item-1-1">Item 1-1</b-nav-item>
              <b-nav-item class="ml-3 my-1" href="#item-1-2">Item 1-2</b-nav-item>
            </b-nav>
            <b-nav-item href="#item-2">Item 2</b-nav-item>
            <b-nav-item href="#item-3">Item 3</b-nav-item>
            <b-nav pills vertical>
              <b-nav-item class="ml-3 my-1" href="#item-3-1">Item 3-1</b-nav-item>
              <b-nav-item class="ml-3 my-1" href="#item-3-2">Item 3-2</b-nav-item>
            </b-nav>
          </b-nav>
        </b-navbar>
      </b-col>

      <b-col cols="8">
        <div id="scrollspy-nested" style="position:relative; height:350px; overflow-y:auto">
          <h4 id="item-1" style="">Item 1</h4>
          <p>{{ text }}</p>
          <h5 id="item-1-1" style="">Item 1-1</h5>
          <p>{{ text }}</p>
          <h5 id="item-1-2" style="">Item 2-2</h5>
          <p>{{ text }}</p>
          <h4 id="item-2" style="">Item 2</h4>
          <p>{{ text }}</p>
          <h4 id="item-3" style="">Item 3</h4>
          <p>{{ text }}</p>
          <h5 id="item-3-1" style="">Item 3-1</h5>
          <p>{{ text }}</p>
          <h5 id="item-3-2" style="">Item 3-2</h5>
          <p>{{ text }}</p>
        </div>
      </b-col>
    </b-row>
  </b-container>
</template>

<script>
  export default {
    data() {
      return {
        text: `
          Quis magna Lorem anim amet ipsum do mollit sit cillum voluptate ex nulla
          tempor. Laborum consequat non elit enim exercitation cillum aliqua
          consequat id aliqua. Esse ex consectetur mollit voluptate est in duis
          laboris ad sit ipsum anim Lorem. Incididunt veniam velit elit elit veniam
          Lorem aliqua quis ullamco deserunt sit enim elit aliqua esse irure. Laborum
          nisi sit est tempor laborum mollit labore officia laborum excepteur
          commodo non commodo dolor excepteur commodo. Ipsum fugiat ex est consectetur
          ipsum commodo tempor sunt in proident.
        `
      }
    }
  }
</script>

<!-- b-scrollspy-nested.vue -->

リストグループを使用した例

Scrollspyは、ローカルhrefまたはtoを持つ<b-list-group-item>が含まれている場合、<b-list-group>でも機能します。リストグループの横の領域をスクロールして、アクティブな状態が変化するのを見てください。

<template>
  <b-container fluid>
    <b-row>
      <b-col cols="4">
        <b-list-group v-b-scrollspy:listgroup-ex>
          <b-list-group-item href="#list-item-1">Item 1</b-list-group-item>
          <b-list-group-item href="#list-item-2">Item2</b-list-group-item>
          <b-list-group-item href="#list-item-3">Item 3</b-list-group-item>
          <b-list-group-item href="#list-item-4">Item 4</b-list-group-item>
          <b-list-group-item href="#list-item-5">Item 5</b-list-group-item>
        </b-list-group>
      </b-col>

      <b-col cols="8">
        <div id="listgroup-ex" style="position:relative; overflow-y:auto; height:300px">
          <h4 id="list-item-1">Item 1</h4>
          <p>{{ text }}</p>
          <h4 id="list-item-2">Item 2</h4>
          <p>{{ text }}</p>
          <h4 id="list-item-3">Item 3</h4>
          <p>{{ text }}</p>
          <h4 id="list-item-4">Item 4</h4>
          <p>{{ text }}</p>
          <h4 id="list-item-5">Item 5</h4>
          <p>{{ text }}</p>
        </div>
      </b-col>
    </b-row>
  </b-container>
</template>

<script>
  export default {
    data() {
      return {
        text: `
          Quis magna Lorem anim amet ipsum do mollit sit cillum voluptate ex nulla
          tempor. Laborum consequat non elit enim exercitation cillum aliqua
          consequat id aliqua. Esse ex consectetur mollit voluptate est in duis
          laboris ad sit ipsum anim Lorem. Incididunt veniam velit elit elit veniam
          Lorem aliqua quis ullamco deserunt sit enim elit aliqua esse irure. Laborum
          nisi sit est tempor laborum mollit labore officia laborum excepteur
          commodo non commodo dolor excepteur commodo. Ipsum fugiat ex est consectetur
          ipsum commodo tempor sunt in proident.
        `
      }
    }
  }
</script>

<!-- b-scrollspy-listgroup.vue -->

toプロパティを持つコンポーネントでScrollspyを使用する

Vue Router(またはNuxt.js)を使用しており、toプロパティでリンクを生成している場合は、次のいずれかの方法を使用して、レンダリングされたリンクに適切なhrefを生成します。

<!-- using a string path -->
<b-nav-item to="#id-of-element">link text</b-nav-item>

<!-- using a router `to` location object -->
<b-nav-item :to="{ hash: '#id-of-element' }">link text</b-nav-item>

Scrollspyは、生成されたURLが#id-of-elementで終わる限り、historyルーティングモードとhashルーティングモードの両方で機能します。

ディレクティブの構文と使い方

v-b-scrollspy:arg.mod1.mod2="option"

ここで

  • argは、スクロールを監視する要素のID(#を除く)です。オプション(デフォルトはbody)。optionでオーバーライドできます)
  • mod1mod2は、offsetの数値または文字列のmethodにすることができます(以下の設定オブジェクトを参照)。修飾子の順序は重要ではありません。どちらもオプションです
  • optionは、スクロールを監視するelementを識別する文字列、数値offset、または設定オブジェクト(下記参照)にすることができます。オプション

注:このディレクティブは、ネイティブのBootstrap v4とは逆方向に適用されます。BootstrapVueでは、v-b-scrollspyディレクティブは、アクティブ化されるリンクを持つターゲット要素に適用され、argまたはoptionは、スクロールを監視(スパイ)する要素を指定します。

このディレクティブは、<nav-item><b-dropdown-item><b-list-group-item>(または適切なクラスを持つ<a>タグ)を持つ任意のコンテナ要素またはコンポーネントに適用できます。スクロール要素内のそれぞれのidを持つ要素を指すhref属性がレンダリングされている限り。

設定オブジェクトのプロパティ

const config = {
  element: 'body',
  offset: 10,
  method: 'auto',
  throttle: 100
}
プロパティ タイプ デフォルト 説明
element 文字列または参照 'body' スクロールを監視する要素。ID(#foo)、CSSセレクター(#foo div)、または要素/コンポーネントノードへの参照にすることができます。CSS文字列の場合、最初に一致する要素が使用されます。IDを使用する場合は、#で始める必要があります。
offset 数値 10 アクティブ状態をトリガーする前の、スクロールビューポートの上部からのオフセット(ピクセル単位)。
method 文字列 'auto' positionは、スクロールコンテナに対するターゲットオフセットを計算します。offsetは、ウィンドウ/ビューポートの上部に対するターゲットオフセットを計算します。autoは、スクロール要素がbodyの場合はoffsetを選択し、それ以外の場合はpositionを選択します。
throttle 数値 100 オフセットを再計算する前に、リサイズイベントの発火を停止するまでのタイムアウト(ms単位)。

引数/修飾子と値(オブジェクトまたは数値)が渡された場合、値は引数と修飾子よりも優先されます。

オプションのいずれかが無効なタイプの場合、エラーがコンソールに書き込まれます。

設定に関する注意事項

  • スクロール要素が存在しない場合は、<body>でスクロールしていると見なします。
  • スクロール要素がCSSセレクターの場合、最初に見つかった要素が選択されます。
  • スクロール要素が見つからない場合、Scrollspyは何もせずにサイレントに実行されます。

重要!相対ポジショニングが必要です 実装方法に関係なく、scrollspyでは、スクロールしている要素にposition: relative;を使用する必要があります。ほとんどの場合、これは<body>です。<body>以外の要素でscrollspyingする場合は、CSSのheightが設定され、overflow-y: scroll;が適用されていることを確認してください。

ディレクティブの使用例

<body>がスクロール要素であり、デフォルトのオフセットを10ピクセルと仮定します。

<div>
  <b-nav v-b-scrollspy>
    <b-nav-item href="#bar">Foo</b-nav-item>
    <b-nav-item href="#baz">Bar</b-nav-item>
  </b-nav>
</div>

<body>がスクロール要素であり、オフセットを20ピクセルと仮定します。

<div>
  <b-nav v-b-scrollspy="20">
    <b-nav-item href="#bar">Foo</b-nav-item>
    <b-nav-item href="#baz">Bar</b-nav-item>
  </b-nav>
</div>

IDが#fooの要素がスクロール要素であり、デフォルトのオフセットを10ピクセルと仮定します。

<div>
  <b-nav v-b-scrollspy:foo>
    <b-nav-item href="#bar">Foo</b-nav-item>
    <b-nav-item href="#baz">Bar</b-nav-item>
  </b-nav>
</div>

要素#fooがスクロール要素であり、オフセットを20ピクセルと仮定します。

<div>
  <b-nav v-b-scrollspy:foo="20">
    <b-nav-item href="#bar">Foo</b-nav-item>
    <b-nav-item href="#baz">Bar</b-nav-item>
  </b-nav>
</div>

要素#fooがスクロール要素であり、オフセットを25ピクセルと仮定します。

<div>
  <b-nav v-b-scrollspy:foo.25>
    <b-nav-item href="#bar">Foo</b-nav-item>
    <b-nav-item href="#baz">Bar</b-nav-item>
  </b-nav>
</div>

要素#fooがスクロール要素であり、デフォルトのオフセットを10ピクセルと仮定します(値の周りの単一引用符に注意してください)。

<div>
  <b-nav v-b-scrollspy="'#foo'">
    <b-nav-item href="#bar">Foo</b-nav-item>
    <b-nav-item href="#baz">Bar</b-nav-item>
  </b-nav>
</div>

オブジェクトを設定として渡します。elementは、CSS ID(例:#foo)、CSSセレクター(例:body)、またはノード参照にすることができます。

<div>
  <b-nav v-b-scrollspy="{element: '#id', offset: 50}">
    <b-nav-item href="#bar">Foo</b-nav-item>
    <b-nav-item href="#baz">Bar</b-nav-item>
  </b-nav>
</div>

イベント

ターゲットがアクティブになるたびに、イベントbv:scrollspy::activate$root上で、ターゲットのIDを引数として(例:#bar)発行されます。

const app = new Vue({
  el: '#app',
  created() {
    this.$root.$on('bv::scrollspy::activate', this.onActivate)
  },
  methods: {
    onActivate(target) {
      console.log('Received event: "bv::scrollspy::activate" for target ', target)
    }
  }
})

ディレクティブリファレンス

個々のディレクティブのインポート

以下の名前付きエクスポートを使用して、個々のディレクティブをプロジェクトにインポートできます。

ディレクティブ
名前付きエクスポート
インポートパス
v-b-scrollspyVBScrollspybootstrap-vue

import { VBScrollspy } from 'bootstrap-vue'
// Note: Vue automatically prefixes the directive name with 'v-'
Vue.directive('b-scrollspy', VBScrollspy)

Vue.jsプラグインとしてのインポート

このプラグインには、上記にリストされたすべての個々のディレクティブが含まれています。

名前付きエクスポート
インポートパス
VBScrollspyPluginbootstrap-vue

import { VBScrollspyPlugin } from 'bootstrap-vue'
Vue.use(VBScrollspyPlugin)