因公司后台管理系统很多功能技术老旧,最近在用vue重构公司的后台管理系统,在做商品管理添加商品这一块,借鉴淘宝的添加商品的交互,需要实现一个简单的吸顶、锚点和滚动高亮按钮的效果。
需求
- 滚动页面到顶部,实现某元素固定到顶部效果
- 点击某个按钮,页面滚动到相应的位置
- 滚动页面,当到达某个位置时,高亮对应的相关按钮
元素吸顶实现方式
关于元素吸顶效果,通过查阅相关资料和相关测试,有三种方式(还有一种是jquery的方法,这里就不介绍了)
一、使用position:sticky
1. 什么是position:sticky"htmlcode">
3.兼容性 通过查看can i use 可以看到相关的兼容性: 可以看出这个属性的兼容性不是那么好,如果项目需要兼容到ie11等的话,就不是那么适用了 二、使用offsetTop** HTMLElement.offsetTop 为只读属性,它返回当前元素相对于其 offsetParent 元素的顶部内边距的距离。因此我们需要注意的是,在监听页面滚动的过程中,需要将定位父级元素的偏移量也计算在内,可以如下写法: 通过在vue的mounted生命周期函数中添加监听事件滚动的事件: 同时如果这种吸顶方式在项目中会多次用到,就可以封装成组件的形式 三、使用getBoundingClientRect().top** 还有一种更为直接的方式,可以实现吸顶效果,就是使用getBoundingClientRect().top来获取元素相对于视口(浏览器窗口)的位置,相对于offsetTop,该方法不用考虑到吸顶元素的父级元素和页面滚动条的高度,直接对该元素进行处理即可,实现如下: 锚点定位 点击相应的按钮,页面滚动到相应的位置,目前我知道实现该功能的方式有两种: 1. 使用a标签定位 2. 使用js模拟锚点定位 使用a标签定位 这是一种常见的定位方式,它有两种实现方式: 1. 通过href属性链接到指定元素的id 2.另一种是添加一个 a 标签,再将 href 属性链接到这个 a 标签的 name 属性 这种定位方式很简单,支持任意标签的定位,但是a标签的定位会改变路由的hash,如果有相关路由会进行路由跳转 使用js模拟锚点定位 通过js获取元素的scrollTop值,使其滚动到指定的位置,就能实现锚点定位效果,这里的tab切换选项,用到是的element-ui的el-tabs组件,具体实现如下: 不得不提的一个方法就是scrollIntoView,Element.scrollIntoView() 方法让当前的元素滚动到浏览器窗口的可视区域内,同时还支持动态效果,但是不支持配置滚动到距离顶部的距离,会出现遮罩现象,但是很适合做会到顶部的功能 滚动高亮按钮 当用户滚动内容区时,高亮距离按钮组件最近的那个元素所对应的按钮。 通过监听滚动事件,获取当前选中的tab的offsetTop值和当前页面的scrollTop值,判断向上或者向下滚动,做出不同的处理,具体如下: 性能优化 页面中读取属性会导致页面reflow(下次会对导致页面reflow和repaint 的操作做一个总结),过度的reflow会导致页面性能下降,所以我们应该尽量减少reflow的次数,以便给用户更好的体验。 如果产品可以接受效果有延迟,就可以使用节流函数控制在一定时间内只执行一次函数(节流函数可以使用lodash.js 封装好的 throttle 方法) 总结 写到这里,需求中的三个功能都已经实现,也许还存在更好的方案,但是通过这次实现这三个需求,如果大家有其他更好的方法,欢迎留言补充,但我也从中学习到了一些东西 1.position:sticky的用法和使用条件 2.scrollTop、offsetTop等元素的相关属性、getBoundingClientRect()用法和 scrollTo、scrollIntoView的用法 3.锚点时间和滚动高亮事件导致的冲突处理等 以上所述是小编给大家介绍的vue实现吸顶、锚点和滚动高亮按钮效果,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!
.sticky-box{
position: sticky;
position: -webkit-sticky;
top: 60px; //可通过js动态设置
}
//获取当前元素的offsetTop
getOffsetTop(obj) {
let offsetTop = 0;
while (obj != window.document.body && obj != null) {
offsetTop += obj.offsetTop;
obj = obj.offsetParent;
}
return offsetTop;
}
mounted() {
/**通过给变成固定定位的元素添加一个同等高度的父元素,防止该元素变成固定定位时,脱离文档流导致的页面抖动 */
this.tabsHeight = this.$refs.elTabs.offsetHeight;
window.addEventListener("scroll", this.handleScroll);
},
destroyed() {
//离开该页面需要移除这个监听的事件
window.removeEventListener("scroll", this.handleScroll);
},
methods: {
/**滚动事件 */
handleScroll() {
//获取页面滚动条的高度
let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
let offsetTop = this.getOffsetTop(this.$refs.elTabs);
this.isFixed = scrollTop > offsetTop;
}
}
/* 滚动事件 / handleScroll() { / * getBoundingClientRect().top
获取某元素距离浏览器顶部的高度,不包含滚动的距离 */ let tabOffsetTop = this.$refs.stickyBox.getBoundingClientRect().top; this.isFixed = tabOffsetTop < this.offsetTop }
/**滚动事件 */
handleScroll() {
/**
* getBoundingClientRect().top 获取某元素距离浏览器顶部的高度,不包含滚动的距离
this.offsetTop 表示的是吸顶元素距离顶部的条件值(一般项目需求是0)
*/
let tabOffsetTop = this.$refs.stickyBox.getBoundingClientRect().top;
this.isFixed = tabOffsetTop < this.offsetTop
}
<a href="#view1">按钮1</a>
<a href="#view2">按钮1</a>
<div id="view1">视图1</div>
<div><a name="view2">视图2</a></div>
<!-- html -->
<el-tabs v-model="activeName" type="card" @tab-click="tabClick">
<el-tab-pane :label="item.name" :name="item.key" v-for="item in tabList" :key="item.key"></el-tab-pane>
</el-tabs>
<!-- js -->
methods:{
//获取当前元素的offsetTop
getOffsetTop(obj) {
let offsetTop = 0;
while (obj != window.document.body && obj != null) {
offsetTop += obj.offsetTop;
obj = obj.offsetParent;
}
return offsetTop;
},
<!--锚点点击事件-->
<!--fixedHeight 滚动的位置上方固定的高度-->
tabClick(e) {
let _this = this;
//获取当前选中的index以便后面滚动高亮
this.index = parseInt(e.index);
//给定一个标识,锚点事件不触发滚动
this.isScroll = false;
this.isChange = false;
//获取当前选中元素的top值(给元素绑定对应的ref值)
let offsetTop = this.getOffsetTop(this.$refs[this.activeName]);
let scrollTop = offsetTop - this.fixedHeight;
window.scrollTo({
top: scrollTop
});
}
//页面滚动要做的事情
handleScroll() {
let scrollTop =
window.pageYOffset ||
document.documentElement.scrollTop ||
document.body.scrollTop;
this.scrollTop = scrollTop;
<!--isScroll 用于避免锚点事件触发页面滚动-->
if (!this.isScroll) return;
/**
* scrollTop 页面的滚动条的高度
* offsetTop 当前选中的tab元素的offsetTop
* offsetHeight 当前选中元素的高度
*/
let offsetTop = this.getOffsetTop(this.$refs[this.activeName]);
let offsetHeight = this.$refs[this.activeName].offsetHeight;
let actuaTop = scrollTop + this.fixedHeight;
let length = this.tabList.length;
/**
* 页面滚动中根据相应位置变换选中tab
*/
if (actuaTop < offsetTop && this.index > 0) {
this.index = this.index - 1;
this.activeName = this.tabList[this.index].key;
} else if (this.index < length && actuaTop > offsetTop + offsetHeight) {
this.index = this.index + 1;
this.activeName = this.tabList[this.index].key;
}
}
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!
昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。
这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。
而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?
更新日志
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]