滚动间谍

根据滚动位置自动更新 Bootstrap 导航或列表组组件,以指示当前视口中哪个链接处于活动状态。

工作原理

v-b-scrollspy 指令有一些正常运行的要求

  • 它必须应用于包含 <b-nav><b-list-group> 组件的元素/组件,您希望在其中指示哪个链接当前处于活动状态。
  • Scrollspy 要求在您正在监视的元素上使用 position: relative;,通常是 <body>
  • 当监视 <body> 以外的元素时,请确保设置 height 并应用 overflow-y: scroll;
  • 锚点 (<a><b-nav-item><b-dropdown-item><b-list-group-item>) 是必需的,并且必须具有 href(通过 hrefto 道具),指向您正在监视的容器中具有该 id 的元素。在使用 to 道具时,可以设置以 #id-of-element 结尾的 path,或者将位置属性 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 包含具有本地 hrefto<b-list-group-item> 时,Scrollspy 也适用于 <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 路由器(或 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 既适用于 history 路由模式,也适用于 hash 路由模式,只要生成的 URL 以 #id-of-element 结尾即可。

指令语法和用法

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 将选择 offset(如果滚动元素是 body),否则方法为 position
节流 数字 100 调整大小事件在重新计算偏移量之前停止触发的 ms 中的超时。

如果传递了参数/修饰符和值(对象或数字),则该值优先于参数和修饰符。

如果任何选项都是无效类型,则会将错误写入控制台。

配置说明

  • 如果滚动元素不存在,则我们假设在 <body> 上滚动
  • 如果滚动元素是 CSS 选择器,则选择第一个找到的元素
  • 如果未找到滚动元素,则 Scrollspy 不会执行任何操作

重要!需要相对定位无论采用哪种实现方法,Scrollspy 都要求在滚动所在的元素上使用 position: relative;。在大多数情况下,这是 <body>。在除 <body> 之外的元素上执行 Scrollspy 时,请确保设置了 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)