微信公众号:前端程序猿之路
关注可了解更多的前端知识,反馈问题或建议,请公众号留言。
如果你觉得公众号内容对你有帮助,欢迎关注并转载
element-ui 封装页面步骤导航定位条
最近在用element-ui
组件开发项目,项目页面中,由于页面比较长,所以页面右侧设计了步骤导航定位条,滚动页面后,右侧步骤条跟着滚动,并且右侧同步显示页面滚动到哪个模块上,查看了element-ui组件库,发现并没有现成的组件,所以自己封装了一个,便于项目中其它页面使用。
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就可以设置那个是激活的步骤了。
完成滚动变化右侧步骤条以后,还有一个要求是点击右侧步骤条也跳转到相应的模块,这个就简单了就用锚点即可
<span class="stepIndex" v-for="(item,index) in stepId" :key="item" @click="jump(item)" :class="'step'+index"> </span>
每点击一次就滚动到相应模块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文件夹里面,起一个通俗易懂的名字即可。
为了避免每个用到的页面都得引用组件的麻烦,我直接在全局引用了组件,这样项目里面的页面直接用即可。
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"> </span>
</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 = -S
window.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