微信公众号:前端程序猿之路
关注可了解更多的前端知识,反馈问题或建议,请公众号留言。如果你觉得公众号内容对你有帮助,欢迎关注并转载

element-ui 封装页面步骤导航定位条

最近在用element-ui组件开发项目,项目页面中,由于页面比较长,所以页面右侧设计了步骤导航定位条,滚动页面后,右侧步骤条跟着滚动,并且右侧同步显示页面滚动到哪个模块上,查看了element-ui组件库,发现并没有现成的组件,所以自己封装了一个,便于项目中其它页面使用。

8b0e460762d063e8b469030e7c91b345.png
  mounted() {
    window.addEventListener('scroll', this.getScrollId);
  },
  destroyed(){
    window.removeEventListener('scroll', this.getScrollId);
  },

组件中在进入页面的时候就开始监听滚动事件并调用getScrollId方法,在页面销毁以后去掉监听。

  stepId: {
      type: Array,
      default: ""
    },

props中,stepId是从父组件中传过来的每个模块的id,类似于锚点,给每个模块添加一个id,便于判断。

getScrollId(){
      let height = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
      let docHeight = [];
      this.stepId.forEach(data=>{
        let s = document.getElementById(data);
        let domHeight = s.offsetTop+60;
        let S = Math.abs(Number(height) - Number(domHeight));
        docHeight.push(S);
      })
      let minIndex = docHeight.indexOf(Math.min.apply(null, docHeight));
      let dom = this.stepId[minIndex];
      this.current = minIndex;
    },

height返回当前页面相对于窗口显示区左上角的 Y 位置,domHeight返回每个模块距离页面上方的距离+60px。
两者做减法然后取绝对值存进docHeight数组中,并且找到数组中最小值的索引,这样就可以拿到距离页面顶部最近的一个模块id值了。
另外,这里还用到了element-ui组件中steps步骤条组件

<el-steps :active="active" finish-status="success">
    <el-step title="步骤 1">el-step>
    <el-step title="步骤 2">el-step>
    <el-step title="步骤 3">el-step>
el-steps>

组件中的active属性,接受一个Number,表明步骤的 index,从 0 开始,这时我们把上面找到的最小值的索引赋值给active就可以设置那个是激活的步骤了。
完成滚动变化右侧步骤条以后,还有一个要求是点击右侧步骤条也跳转到相应的模块,这个就简单了就用锚点即可

 class="stepIndex" v-for="(item,index) in stepId" :key="item" @click="jump(item)" :class="'step'+index">&nbsp

每点击一次就滚动到相应模块id位置,这样就完成了组件功能的实现。

 jump(domId){
      // 当前窗口正中心位置到指定dom位置的距离
      //页面滚动了的距离
      let height = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;      
      //指定dom到页面顶端的距离
      let dom = document.getElementById(domId);
      let domHeight = dom.offsetTop+60;      
      //滚动距离计算
      var S = Number(height) - Number(domHeight);
      //判断上滚还是下滚
      if(S<0){
        //下滚
        S = Math.abs(S);
        window.scrollBy({ top: S, behavior: "smooth" });
      }else if(S==0){
        //不滚
        window.scrollBy({ top: 0, behavior: "smooth" });
      }else{
        //上滚
        S = -S
        window.scrollBy({ top: S, behavior: "smooth" });
      }
    },

把组件封装之后放到工程专门放组件的位置,我是放到了工程componnets文件夹里面,起一个通俗易懂的名字即可。

5c2ec4a66c6630d0c9bb52caa0868a5f.png

为了避免每个用到的页面都得引用组件的麻烦,我直接在全局引用了组件,这样项目里面的页面直接用即可。
import commonStep from "@/components/step/index.vue";

父组件中:
页面引用的时候只需


<common-step :title="stepTitle" :stepId="stepId">common-step>

在父组件data里面定义一下用到的属性stepTitle是步骤条中文,stepId对应模块的id,两者是对应的

子组件(直接上完整代码):

<template>
  <el-aside width="160px">
    <div style="position:fixed" class="step" :title="title" :stepId="stepId">
      <div style="height: 300px;">
        <el-steps direction="vertical" :active="current" style="position: relative;">                
          <el-step :title="item"  v-for="item in title" :key="item">el-step>
        el-steps>
        <span class="stepIndex" v-for="(item,index) in stepId" :key="item" @click="jump(item)" :class="'step'+index">&nbspspan>
      div>
  div>
  el-aside>
template>

<script>export default {name: "common-step",props: {title: {type: Array,default: ""
    },stepId: {type: Array,default: ""
    },
  },
  data() {return {current: 0,
    };
  },watch: {
  },
  mounted() {window.addEventListener('scroll', this.getScrollId);
  },
  destroyed(){window.removeEventListener('scroll', this.getScrollId);
  },methods: {
    jump(domId){// 当前窗口正中心位置到指定dom位置的距离//页面滚动了的距离let height = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;      //指定dom到页面顶端的距离let dom = document.getElementById(domId);let domHeight = dom.offsetTop+60;      //滚动距离计算var S = Number(height) - Number(domHeight);//判断上滚还是下滚if(S<0){//下滚
        S = Math.abs(S);window.scrollBy({ top: S, behavior: "smooth" });
      }else if(S==0){//不滚window.scrollBy({ top: 0, behavior: "smooth" });
      }else{//上滚
        S = -Swindow.scrollBy({ top: S, behavior: "smooth" });
      }
    },
    getScrollId(){let height = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;let docHeight = [];this.stepId.forEach(data=>{let s = document.getElementById(data);let domHeight = s.offsetTop+60;let S = Math.abs(Number(height) - Number(domHeight));
        docHeight.push(S);
      })let minIndex = docHeight.indexOf(Math.min.apply(null, docHeight));let dom = this.stepId[minIndex];this.current = minIndex;
    },
  }
};script>

<style lang="scss" scoped>
.hidden {
  ::v-deep .el-dialog__body {
    padding: 0;
  }
}
.btnColor{
  color: #1890ff;
  border-color: #badeff;
  background-color: #e8f4ff;
}
.stepIndex{
  position: absolute;
  z-index: 3;
  width: 100%;
  height: 28px;
}
>>> .el-step.is-vertical .el-step__title{
  line-height: 32px;
}
>>> .el-step.is-vertical .el-step__line{
  top: 6px;
}
>>> .el-step__main{
  height: 50px;
}
>>> .el-steps--vertical{
  height: 0;
}
.step0{
  top: 2px;
}
.step1{
  top: 53px;
}
.step2{
  top: 103px;
}
.step3{
  top: 152px;
}
.step4{
  top: 204px;
}
.step5{
  top: 253px;
}style>

上面步骤做完以后运行即可,是不是很简单
以上就是所有,文中部分内容进行了参考,下面有参考链接,如果写的有什么问题烦请各位大佬指正,我会虚心修改。

参考链接:
https://www.w3school.com.cn/jsref/prop_style_lineheight.asp
https://blog.csdn.net/weixin_39327044/article/details/90545902

1a4ddbef3c2640e3e9e514fc8d0581a2.png
Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐