可以分成两步来实现:

  1. 首先实现el-steps的点击事件,这个组件是不能点击的,但是我们可以获取dom元素,自己来设置点击事件,并获取到相应的索引;对于有滚动条的盒子,我们把里面的每个盒子距离顶部的高度全部放到一个数组里,然后通过点击el-steps获得的索引在数组中找出对应的盒子距离顶部的高度,把这个值设置给scrollTop,就可以达到点击哪个el-step,滚动内容就定位到那里了
  2. 给有滚动条的盒子设置一个滚动事件,通过拿到的scrollTop的值来判断当前位于哪个盒子中,以此来获取索引赋值给el-step,那么就可以实现对应的el-step高亮了;

先把el-steps作为一个组件拆分出来:

<template>
  <div class="step">
    <el-steps direction="vertical">
      <el-step
        :title="item"
        v-for="(item, index) in titleList"
        :key="item"
        :status="active == index ? 'finish' : 'wait'"
      ></el-step>
    </el-steps>
  </div>
</template>

<script>
export default {
  props: {
    titleList: {
      type: Array,
      default: []
    },
    index: {
      type: Number,
      default: 0
    }
  },
  watch: {
    index(val) {
      this.active = val
    }
  },
  data() {
    return {
      active: 0
    }
  },
  mounted() {
    let that = this
    // 注册点击事件,获取索引
    const stepItem = document.getElementsByClassName('el-step__icon')
    for (let i = 0; i < stepItem.length; i++) {
      stepItem[i].addEventListener('click', function (e) {
        that.active = i
        that.$emit('onBack', i)
      })
    }
  }
}
</script>

<style lang="scss" scoped>
.step {
  height: 80%;
  // width: 10px;
  position: fixed;
  top: 50%;
  right: 10px;
  transform: translate(0, -50%);
  ::v-deep .el-step__icon {
    cursor: pointer;
  }
}
</style>

然后在引入到父组件中使用:

<template>
  <div class="container">
    <div class="main">
      <el-scrollbar ref="scrollbar">
        <div
          class="item"
          v-for="(item, index) in itemList"
          :key="index"
          :style="`background:${item.color};`"
        >
          {{ item.title }}
        </div>
      </el-scrollbar>
    </div>
    <Step :titleList="titleList" @onBack="onBack" :index="index"></Step>
  </div>
</template>

<script>
import Step from '@/components/step.vue'
export default {
  components: {
    Step
  },
  data() {
    return {
      titleList: ["标题1", "标题2", "标题3", "标题4", "标题5", "标题6"],
      itemList: [
        { color: 'red', title: '标题1' },
        { color: 'blue', title: '标题2' },
        { color: 'green', title: '标题3' },
        { color: 'purple', title: '标题4' },
        { color: 'khaki', title: '标题5' },
        { color: 'skyblue', title: '标题6' }
      ],
      scrollBox: {},
      offsetTop: [],
      index: 0
    }
  },
  mounted() {
    // 获取有滚动条盒子的对象
    this.scrollBox = this.$refs.scrollbar.$refs.wrap
    // 获取滚动内的每个盒子距离顶部的距离
    const dom = document.getElementsByClassName('item')
    for (let i = 0; i < dom.length; i++) {
      this.offsetTop.push(dom[i].offsetTop)
    }

    // 侦听滚动
    this.scrollBox.addEventListener('scroll', () => {
      this.offsetTop.forEach((item, index, arr) => {
        if (this.scrollBox.scrollTop >= item - 1 && this.scrollBox.scrollTop < arr[index + 1]) {
          this.index = index
        }
      })
    })
  },
  methods: {
    onBack(index) {
      this.scrollBox.scrollTop = this.offsetTop[index]
    }
  }
}
</script>

<style lang="scss" scoped>
.main {
  width: 80%;
  height: 700px; // 建议设置父级元素的高度,这样div.el-scrollbar就可以通过%来设置高度
  padding: 0;
  overflow: hidden;
  border: 1px solid #ccc;
  .el-scrollbar {
    width: 100%; // 宽度可以设置也可以不设置 因为宽度默认就是填充满父级元素的内容区
    height: 100%; // 必须设置el-scrollbar的高度
    ::v-deep .el-scrollbar__wrap {
      // 实际上我们的内容是放在这个div下面的
      // height: 100%; // 渲染出来的div.el-scrollbar__wrap默认会添加height:100%的属性。我们可以设置为105%来隐藏元素水平滚动条
      height: 100%;
      overflow: scroll;
      overflow-x: auto;
    }
  }
}
.item {
  height: 400px;
  color: #000;
  font-size: 20px;
  font-weight: bold;
}
</style>

注:上面的if判断里面的item-1是因为有可能是计算存在一些误差,需要微微调整(因为点击el-step的同时也会执行if判断,得确保执行的是对应的if判断,不然两边会冲突)
效果如下:
在这里插入图片描述

GitHub 加速计划 / eleme / element
10
1
下载
A Vue.js 2.0 UI Toolkit for Web
最近提交(Master分支:4 个月前 )
c345bb45 8 个月前
a07f3a59 * Update transition.md * Update table.md * Update transition.md * Update table.md * Update transition.md * Update table.md * Update table.md * Update transition.md * Update popover.md 8 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐