基于Vue2.0 + Element 锚点双向绑定实现

实现背景
基于开发功能需求,实现页面数据太多展示加入锚点,点击跳转到相应位置,滚动页面锚点选中变化。当前系统基于Element组件库不支持此功能,若引入Ant-Design组件库可能会引起全局样式等相关问题。
环境搭建
开发工具:Visual Studio Code
软件环境:Node.js搭建Vue.js的开发环境

主要代码
dom部分
<div class="container">
<div class="leftContent">

<div class="anchor" id="fan"></div>
<div class="anchor" id="twoTicket"></div>
<div class="anchor" id="wind"></div>
<div class="anchor" id="examine"></div>
</div>
<div class="rightContent">

<div class="leftBor" :style="{transform:'translateY('+ sectionIndex * 40 +'px' }">
<div class="scrollbar"></div>
</div>
<div class="sliderCon">
<div class="right">
<div
class="item"
v-for="(item,index) in tabList"
:key="item.id"
:class="item.id == sectionId ? 'active': ''"
@click="change(item.id,index)"
>
<span>{{ item.name }}</span>
</div>
</div>
</div>
</div>
</div>
js部分
<script>
export default {
data() {
return {
// 标题列表
tabList: [
{
name: '风机运行情况',
id: 'fan'
},
{
name: '两票统计情况',
id: 'twoTicket'
},
{
name: '风场主要故障统计',
id: 'wind'
},
{
name: '两个细则考核情况',
id: 'examine'
}
],
// 当前的下标属性
sectionId: 'fan',
// 当前的下标位置
sectionIndex: 0,
// 记住当前滚动距离,缓存进来回到原位置
pageScrollTop: '0'
}
},
methods: {
// 点击某个锚点
change(node, index) {
// 记录当前锚点下标值
this.sectionIndex = index
var target = document.getElementById(node)
// 获取父级节点(外层滚动层)
var parentNode = document.getElementById('anchorContent')
// 滚动距离设置 = 目标dom距离顶部距离-外层滚动层距离顶部距离
parentNode.scrollTop = target.offsetTop - parentNode.offsetTop
},
// 滚动触发方法
scrollEvent(e) {
const { tabList } = this
let contents = document.querySelectorAll('.anchor')
let nowTop = e.target.scrollTop // 滚动条目前的滚动距离
// 记录已滚动的距离 用于页面缓存定位
this.pageScrollTop = nowTop
let firstTop = contents[0].offsetTop // 第一个的顶部位置
let idx = null
try {
// forEach循环只能通过抛出异常的方式终止
tabList.forEach((section, index) => {
let contentTop = contents[index].offsetTop // 第index个的顶部位置
let scrollDistance = contentTop - firstTop // 从第一个到第index个的滚动距离
if (nowTop < scrollDistance) {
// 滚动条已滚动的距离少于第index个需要的滚动距离,说明当前处于第(index-1)的
idx = Math.max(0, index - 1)
throw new Error(find sectionId:${this.sectionId})
}
})
} catch (e) {}
// 滚动到最后一个(该高度超过容器)时,滚动条的滚动距离超过所有需要的滚动距离
this.sectionId = idx === null ? tabList[tabList.length - 1].id : tabList[idx].id
this.sectionIndex = idx === null ? tabList.length - 1 : idx
if (e.srcElement.scrollTop + e.srcElement.offsetHeight === e.srcElement.scrollHeight) {
// 若是滚动距离 + 组件可视高度 = 滚动所需的撑开高度 那么就代表滚动条触底,处于最后一个
this.sectionId = tabList[tabList.length - 1].id
this.sectionIndex = tabList.length - 1
}
},
},
// 若当前页面需缓存,二次进入回到离开页面时滚动距离,加入延时是为了解决页面进入,滚动距离设置偏差
activated() {
setTimeout(() => {
var parentNode = document.getElementById('anchorContent')
parentNode.scrollTop = this.pageScrollTop
}, 80)
},
}
</script>
css部分
.container {
height: calc(100vh - 220px) !important;
padding: 0 17px 20px 20px;
border-radius: 0px 0px 8px 8px;
display: flex;
.leftContent {
height: 100%;
overflow-y: auto;
width: 87.5%;
/* 这个地方将左侧滚动条隐藏起来 /
&::-webkit-scrollbar {
width: 0px !important;
}
}
.rightContent {
width: 9.5%;
margin-left: 3%;
display: flex;
align-items: flex-start;
padding-top: 20px;
.leftBor {
height: 40px;
width: 4px;
transition: all 0.5s ease 0s;
display: flex;
align-items: center;
justify-content: center;
position: relative;
left: 3px;
.scrollbar {
height: 20px;
width: 4px;
background: #2574fc;
border-radius: 2px;
}
}
.sliderCon {
border-left: 1px solid #eff1f4;
width: 100%;
.item {
/
这里的高度与锚点滚动对应 */
height: 40px;
width: 100%;
position: relative;
display: flex;
align-items: center;
cursor: pointer;
}

  .active {
    color: #2574fc;
    transition: all 0.5s ease 0s;
  }
  span {
    position: absolute;
    left: 20px;
  }
}

}
}

踩坑点
1.相应页面需要加入页面缓存,加入缓存后,选中的下标值sectionIndex未刷新,但是页面重新进入会自动回到顶部,所以在滚动页面时需记录父级滚动距离,再次进入时为父级设置滚动距离。

2.页面缓存进入时,parentNode.scrollTop方法直接使用会导致页面的滚动距离减少,加入延时处理,滚动距离设置正常。
实现意义
目前所参与开发的系统都是基于Element组件库进行开发,遇到页面数据过多,交互需要锚点双向绑定可进行参照使用。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容