MENU
- 前言
- 效果图
- Web前端原生实现
- Vue框架实现
- scrollTop实现置顶置底(方式一)
- scrollIntoView实现置顶置底(方式二)
- 区别
- 功能
- 语法
- 工作原理
- 兼容性
- 使用场景
- 实用代码
- 推荐
- 总结
前言
在项目中遇到聊天功能,功能涉及置顶和置底知识,由此记录一下实现思路和过程。
效果图
Web前端原生实现
Html
<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>移动随机元素至可视区域</title><linkrel="stylesheet"href="./index.css"></head><body><divclass="box"><divclass="item_box"id="idItemBox"></div><divclass="btn"onclick="fnRandomShift()">移动随机元素至可视区域</div></div><scriptsrc="./index.js"></script></body></html>JavaScript
// 根据长度生成随机下标constrandIndex=(val=0)=>Math.floor(Math.random()*val);// 根据父元素id获取所有item子元素(不包括后代元素)constgetItemAll=()=>idItemBox.children;// 定义长度(可换成数组长度)constlen=68;// 执行初始化init();/** * 初始化 */functioninit(){createItem(()=>fnRandomShift());}/** * 创建item元素 * @param {*} fn */functioncreateItem(fn=()=>{}){// 创建item元素for(leti=0;i<len;i++){letn=i+1;constdiv=document.createElement('div');div.className='item';div.id=`${'id_'+n}`;// | bind第一个参数传入值 | 意义 | 场景 |// | :-- | :-- | :-- |// | null/undefined | 忽略this,函数内部不依赖this | 最常见,也是最安全 |// | 某个对象 | 将该对象作为this | 函数内部需要使用this,如调用对象方法等 |// | div元素本身 | this指向当前绑定事件的DOM元素 | 在函数中需要访问当前元素,如`this.innerHTML`等 |div.onclick=fnClickItemDom.bind(undefined,i);n=n<10?'0'+n:n;div.textContent=`第${n}项`;idItemBox.appendChild(div);}fn();}/** * 点击对应项实现移动和高亮功能 * @param {*} index */functionfnClickItemDom(index=0){setScrollIntoView(index);}/** * 随机移动元素(生成随机数,按钮) */functionfnRandomShift(){letindex=randIndex(len);setScrollIntoView(index);}/** * 移动随机元素至可视区域 * @param {*} index */functionsetScrollIntoView(index=0){letdomItemAll=getItemAll();letdomItem=domItemAll[index];// 移除所有元素上的激活类for(leti=0;i<domItemAll.length;i++){constdomItem=domItemAll[i];// 移除激活类domItem.classList.remove('active');}// 添加指定元素激活类domItem.classList.add('active');// 设置元素移动domItem.scrollIntoView({block:"center",behavior:'smooth'});}Style(scss)
*{margin:0px;padding:0px;box-sizing:border-box;}div{box-sizing:border-box;}::-webkit-scrollbar{display:none;}.active{background-color:#efefef!important;color:#409eff!important;}body{background-color:#333333;.box{width:100vw;height:100vh;display:flex;flex-direction:column;justify-content:center;align-items:center;.item_box{width:90%;height:500px;padding:8px;text-align:center;overflow-y:auto;background-color:#ffffff;.item{background-color:#dfdfdf;border-radius:4px;color:#333333;white-space:nowrap;font-size:28px;cursor:pointer;}.item:not(:first-child){margin-top:8px;}}.btn{margin-top:68px;background-color:#409eff;padding:6px 8px;border-radius:4px;color:#ffffff;font-size:28px;cursor:pointer;}}}Vue框架实现
Html
<divclass="p_b_36"id="idTop"><div><divv-for="item in arr":key="item.id">{{ item.value }}</div><divid="idBottom"><inputv-model="value"type="text"placeholder="请输入内容..."/><spanclass="padding_6 m_l_8 bac_eee bor_rad_2"@click="sending">发 送</span></div></div><divclass="pf cp right_26 bottom_100"@click="setTop">置顶</div><divclass="pf cp right_26 bottom_50"@click="setBottom">置底</div></div>JavaScript
exportdefault{name:'HelloWorld',props:{msg:String},data(){return{arr:[],value:''}},created(){this.init();},methods:{// 发送asyncsending(){letarrLen=this.arr.length,value=this.value;awaitthis.arr.push({id:`id${arrLen+1}`,value:value});this.setBottom();},// 置底setBottom(){// // 方式一 vue3无响应// let scrollTop = document.body.scrollHeight;// document.documentElement.scrollTop = scrollTop;// 方式二 把该元素的最底部内容显示在可视区域的最底部letidBottom=document.getElementById("idBottom");idBottom.scrollIntoView({block:"end"});},// 置顶setTop(){// 方式一 vue3无响应// document.documentElement.scrollTop = 0;// 方式二 把该元素的最顶部内容显示在可视区域的最顶部letidTop=document.getElementById("idTop");idTop.scrollIntoView({block:"start"});},// 初始化init(){letarr=[];for(leti=0;i<86;i++)arr.push({id:`id${i+1}`,value:`${i+1}`});this.arr=arr;}}}Style
.pf{position:fixed;}.cp{cursor:pointer;}.right_26{right:26px;}.padding_6{padding:6px;}.bottom_100{bottom:100px;}.bottom_50{bottom:50px;}.p_b_36{padding-bottom:36px;}.m_l_8{margin-left:8px;}.bac_eee{background-color:#eeeeee;}.bor_rad_2{border-radius:2px;}scrollTop实现置顶置底(方式一)
基本介绍
Element.scrollTop属性可以获取或设置一个元素的内容垂直滚动的像素数。
一个元素的scrollTop值是这个元素的内容顶部到它的视口可见内容的距离的度量。当一个元素的内容没有产生垂直方向的滚动条,那么它的scrollTop值为0。
在使用显示比例缩放的系统上,scrollTop可能会提供一个小数值。设置值规范
如果一个元素不能被滚动,scrollTop将被设置为0。
设置scrollTop的值小于0,scrollTop被设为0。
如果设置了超出这个容器可滚动的值,scrollTop会被设为最大值。
scrollIntoView实现置顶置底(方式二)
简单介绍
Element接口的scrollIntoView()方法会滚动元素的父容器,使被调用scrollIntoView()的元素对用户可见。参数
布尔值
如果为true,元素的顶端将和其所在滚动区的可视区域的顶端对齐,等价于{ block: "start", inline: "nearest" },这是这个参数的默认值。
如果为false,元素的底端将和其所在滚动区的可视区域的底端对齐,等价于{ block: "end", inline: "nearest" }。
属性对象behavior定义动画过渡效果,auto或smooth之一,默认为auto。block定义垂直方向的对齐,start、center、end或nearest之一,默认为start。inline定义水平方向的对齐,start、center、end或nearest之一,默认为nearest。注意
此元素可能不会完全滚动到顶端或底端,这取决于其他元素的布局情况。
区别
功能
功能 scrollTop scrollIntoView 作用 获取或设置元素的垂直滚动位置(单位:像素) 滚动元素使其进入可视区域 支持方向 仅垂直滚动(配合scrollLeft可做水平) 垂直和水平都支持 滚动目标 父容器元素 元素自身 常见用法 精确控制滚动位置,例如滚动条动画、滚动到某位置 使某个DOM元素自动出现在用户视野中
语法
scrollTop(数值型属性)
constcontainer=document.getElementById('container');// 读取当前滚动值lettop=container.scrollTop;// 设置滚动位置container.scrollTop=200;
需要知道元素当前的位置或计算出偏移量,才知道要滚多少。scrollIntoView(方法)
constitem=document.querySelector('.item');// 滚动元素进入可视区域(默认顶部对齐)item.scrollIntoView();// 更加精准的参数形式item.scrollIntoView({// 滚动动画,可选'auto'、'smooth'behavior:'smooth',// 垂直对齐方式:start、center、end、nearestblock:'center',// 水平对齐方式:start、center、end、nearestinline:'nearest'});
工作原理
对比点 scrollTop scrollIntoView 控制级别 更底层,控制滚动条位置 更高层,自动计算滚动位置并触发滚动 需要计算 需要自己计算偏移量(如offsetTop) 不需要计算位置 自动判断容器 ❌只能用于设置某个滚动容器 ✅自动判断元素在可滚动容器中的位置 是否动画支持 ❌没有动画(除非你自己用setInterval实现) ✅支持平滑动画
兼容性
特性 scrollTop scrollIntoView 支持度 非常广泛,所有浏览器都支持 现代浏览器普遍支持;IE及老版本不支持参数对象 动画兼容性 不支持,需要手动动画 behavior: 'smooth’兼容较好(不支持IE)
使用场景
场景 推荐方法 理由说明 聊天窗口始终滚动到底部 scrollTop 知道内容高度,可以设置为scrollTop = scrollHeight 点击菜单跳转到页面某一部分 scrollIntoView 自动滚动,使用方便 歌曲播放随机滚动到视图中 scrollIntoView 元素可变,自动滚动更简单,避免手动计算 制作滚动条组件、精细动画控制 scrollTop 可以控制每像素的滚动位置 多个列表中某项高亮并滚动到视图中 scrollIntoView 自动完成,省心
实用代码
scrollTop实现滚动到某个元素
functionscrollToElement(el){constcontainer=document.getElementById('musicListBox');// 必须计算元素在容器内的位置consttop=el.offsetTop;container.scrollTop=top;}scrollIntoView实现滚动到某个元素
functionscrollToElement(el){el.scrollIntoView({behavior:'smooth',block:'center'});}
推荐
对比点 推荐 想精确控制位置 用scrollTop 想让某个元素进入视野 用scrollIntoView(简单又可靠) 是否自动定位元素 scrollIntoView✅自动 是否需要计算位置 scrollTop❌需要手动计算
总结
1、方式一在
vue3中无响应,不报错,功能也没有实现。
2、方式二可能在某些场景不适用,但兼容性会比方式一好一些。
3、以上两种方式属于原生方法和属性,所以不区分框架与原生情况。
4、置底功能适用于聊天页面,置顶功能适用于有滚动条需要返回顶部的功能。
5、方式一使用设置滚动条的方式实现;方式二使用锚点的方式实现。