vue中如何動態(tài)獲取剩余區(qū)域的滾動高度
vue動態(tài)獲取剩余區(qū)域的滾動高度
需求
通過獲取屏幕的高度,減去【固定】高度,剩下的高度為【內容】滾動高度。
我們通過下面代碼獲取屏幕高度:
document.documentElement.clientHeight || document.body.clientHeight;
所謂的固定高度,應該是一直停留在屏幕可見范圍中,不根據(jù)內容進行滾動。
如果這個固定高度是一些靜態(tài)資源時,我們只需通過設置 ref 獲取元素的高度。
<div class="index-banner-img"> ? <img :src="bannerImg" ref="imgSize" alt=""> </div>
let imgHeight = this.$refs['imgSize'].height
那么這樣就很容易的獲取到內容的滾動高度,代碼如下:
getScollerHeight() { ? setTimeout(() => { ? ? let clientHeight = document.documentElement.clientHeight || document.body.clientHeight; ? ? let imgHeight = this.$refs['imgSize'].height ? ? this.scrollHeight = (clientHeight - imgHeight) + 'px' ? }, 100) } mounted() { ? this.getScollerHeight() },
vue獲取元素高度總是不準確問題
打算用一個websocket寫一個簡易的聊天系統(tǒng)。
后端代碼很容易就寫好,但是前端是真的難搞,遇到一個很嚴重的問題:
當發(fā)送一條消息或者是收到一條消息,消息展示界面不能滑到最下面,展示最新消息,于是,經(jīng)過一段時間的修改,發(fā)送新消息時,滾動條雖然能下滑,但是滑不到最底部,于是我添加了一個按鈕,使用按鈕,將滾動條滑到最底部是可行的。又使用debug調試,發(fā)現(xiàn):vue會先執(zhí)行你的其它方法,再渲染頁面,導致總是只能滑到上一條消息展示的高度。
于是我再百度,發(fā)現(xiàn):重置數(shù)據(jù)后,獲取dom元素高時,dom元素還未渲染完畢,(可能這就是為什么只能滑到上一條消息展示的地方)
解決辦法
this.$nextTick()函數(shù) :在下次DOM更新循環(huán)結束之后執(zhí)行延遲回調
this.$nextTick(()=>{? ? ? ?this.goBottom(); // 滾動條滑到底部的方法 ? ?})
補充: 使用vue獲取一個指定的元素的高度,可以使用vue的ref
當ref加在普通的元素上,使用this.ref.name獲取到的是dom元素
下面是聊天的html代碼
<!DOCTYPE html> <html lang="en"> <head> ? ? <meta charset="UTF-8"> ? ? <title>微聊</title> ? ? <script src="../static/js/vue.js"></script> ? ? <style> ? ? ? ? .cheet-box{ ? ? ? ? ? ? width: 592px; ? ? ? ? ? ? height: 160px; ? ? ? ? } ? ? ? ? .box{ ? ? ? ? ? ? /*margin: 0 auto;*/ ? ? ? ? ? ? /*overflow:auto;*/ ? ? ? ? ? ? overflow-y: auto; ? ? ? ? ? ? overflow-x: hidden; ? ? ? ? ? ? font-family: "微軟雅黑 Light"; ? ? ? ? ? ? width: 600px; ? ? ? ? ? ? height: 300px; ? ? ? ? ? ? background-color: #ecece9; ? ? ? ? ? ? border: none; ? ? ? ? ? ? box-shadow: aliceblue; ? ? ? ? ? ? margin-bottom: 20px; ? ? ? ? ? ? padding: 50px; ? ? ? ? } ? ? ? ? .to,.me{ ? ? ? ? ? ? word-wrap:break-word; ? ? ? ? ? ? display: block; ? ? ? ? ? ? width: 50%; ? ? ? ? ? ? padding: 26px; ? ? ? ? ? ? border-radius: 10px; ? ? ? ? ? ? background-color: #fff; ? ? ? ? ? ? margin: 5px 0 10px 0; ? ? ? ? } ? ? ? ? .system-log{ ? ? ? ? ? ? padding: 5px 0; ? ? ? ? ? ? color: darkgrey; ? ? ? ? ? ? text-align: center; ? ? ? ? } ? ? ? ? .to{ ? ? ? ? ? ? float: left; ? ? ? ? } ? ? ? ? .me{ ? ? ? ? ? ? float: right; ? ? ? ? } ? ? </style> </head> <body onbeforeunload="checkLeave()"> ? ? <div id="app"> ? ? ? ? <div class="box" id="box" ref="getHeight"> ? ? ? ? ? ? <div v-for="item in messageArray"> <!-- ? ? ? ? ? ? ? ?<div class="system-log">連接成功...</div>--> ? ? ? ? ? ? ? ? <div class="to" v-if="item.username != message.username" v-text="item.text"> ? ? ? ? ? ? ? ? </div> ? ? ? ? ? ? ? ? <div class="me" v-else ?v-text="item.text"> ? ? ? ? ? ? ? ? ? ? aaaaaa ? ? ? ? ? ? ? ? </div> ? ? ? ? ? ? </div> ? ? ? ? </div> ? ? ? ? <div> ? ? ? ? ? ? <input type="text" v-model="message.username"> ? ? ? ? </div> ? ? ? ? <div> ? ? ? ? ? ? <textarea type="text" v-model="message.text" class="cheet-box"></textarea> ? ? ? ? ? ? <input @click="sendMessage()" type="button" value="發(fā)送"/> ? ? ? ? ? ? <input @click="goBottom()" type="button" value="底部"/> ? ? ? ? </div> ? ? </div> ? ? <script> ? ? ? ? function checkLeave(){ ? ? ? ? ? ? sessionStorage.setItem('key','hello'); ? ? ? ? ? ? localStorage.setItem('2','3') ? ? ? ? } ? ? ? ? var websocket ; ? ? ? ? var vm = new Vue({ ? ? ? ? ? ?el:'#app', ? ? ? ? ? ? created(){ ? ? ? ? ? ? ? ? this.initWebSocket(); ? ? ? ? ? ? }, ? ? ? ? ? ? data:{ ? ? ? ? ? ? ? ? ? ? message:{ ? ? ? ? ? ? ? ? ? ? ? ? username:'', ? ? ? ? ? ? ? ? ? ? ? ? text:'', ? ? ? ? ? ? ? ? ? ? }, ? ? ? ? ? ? ? ? messageArray:[ ? ? ? ? ? ? ? ? ], ? ? ? ? ? ? }, ? ? ? ? ? ? methods:{ ? ? ? ? ? ? ? ?initWebSocket(){ ? ? ? ? ? ? ? ? ? ?if (typeof (WebSocket)=="undefined"){ ? ? ? ? ? ? ? ? ? ? ? ?alert('瀏覽器不支持WebSocket') ? ? ? ? ? ? ? ? ? ?}else { ? ? ? ? ? ? ? ? ? ? ? ?console.log('瀏覽器支持websocket') ? ? ? ? ? ? ? ? ? ? ? ?websocket = new WebSocket("ws://localhost:8080/ws/asset"); ? ? ? ? ? ? ? ? ? ? ? ?//連接打開事件 ? ? ? ? ? ? ? ? ? ? ? ?websocket.onopen = function() { ? ? ? ? ? ? ? ? ? ? ? ? ? ?console.log("Socket 已打開"); ? ? ? ? ? ? ? ? ? ? ? ? ? ?var obj = { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?text:'', ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?username: '', ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?log:'連接成功!' ? ? ? ? ? ? ? ? ? ? ? ? ? ?} ? ? ? ? ? ? ? ? ? ? ? ? ? ?websocket.send(JSON.stringify(obj)); ? ? ? ? ? ? ? ? ? ? ? ?}; ? ? ? ? ? ? ? ? ? ? ? ?//收到消息事件 ? ? ? ? ? ? ? ? ? ? ? ?websocket.onmessage = function(msg) { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?vm.pushArray(msg.data) ? ? ? ? ? ? ? ? ? ? ? ?}; ? ? ? ? ? ? ? ? ? ? ? ? ? ?//連接關閉事件 ? ? ? ? ? ? ? ? ? ? ? ?websocket.onclose = function() { ? ? ? ? ? ? ? ? ? ? ? ? ? ?console.log("Socket已關閉"); ? ? ? ? ? ? ? ? ? ? ? ?}; ? ? ? ? ? ? ? ? ? ? ? ?//發(fā)生了錯誤事件 ? ? ? ? ? ? ? ? ? ? ? ?websocket.onerror = function() { ? ? ? ? ? ? ? ? ? ? ? ? ? ?alert("Socket發(fā)生了錯誤"); ? ? ? ? ? ? ? ? ? ? ? ?} ? ? ? ? ? ? ? ? ? ? ? ?//窗口關閉時,關閉連接 ? ? ? ? ? ? ? ? ? ? ? ?window.unload=function() { ? ? ? ? ? ? ? ? ? ? ? ? ? ?websocket.close(); ? ? ? ? ? ? ? ? ? ? ? ?}; ? ? ? ? ? ? ? ? ? ?} ? ? ? ? ? ? ? ?}, ? ? ? ? ? ? ? ? sendMessage(){ ? ? ? ? ? ? ? ? ? ? websocket.send(JSON.stringify(this.message)); ? ? ? ? ? ? ? ? ? ? this.message.text = '' ? ? ? ? ? ? ? ? }, ? ? ? ? ? ? ? ? pushArray(msg){ ? ? ? ? ? ? ? ? ? ? let message = JSON.parse(msg); ? ? ? ? ? ? ? ? ? ? console.log(message) ? ? ? ? ? ? ? ? ? ? if (message.username!='' && message.text!=''){ ? ? ? ? ? ? ? ? ? ? ? ? this.messageArray.push(message) ? ? ? ? ? ? ? ? ? ? ? ? this.$nextTick(()=>{ ? ? ? ? ? ? ? ? ? ? ? ? ? ? this.goBottom(); ? ? ? ? ? ? ? ? ? ? ? ? }) ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? }, ? ? ? ? ? ? ? ? goBottom(){ ? ? ? ? ? ? ? ? ? ? let box = document.getElementById('box'); ? ? ? ? ? ? ? ? ? ? box.getBoundingClientRect().height ? ? ? ? ? ? ? ? ? ? box.scrollTo(0,box.scrollHeight-box.clientHeight) ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? }) ? ? </script> </body> </html>
總結
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
vue使用多級彈窗(Dialog)出現(xiàn)蒙版遮罩問題及解決
這篇文章主要介紹了vue使用多級彈窗(Dialog)出現(xiàn)蒙版遮罩問題及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-02-02vue router導航守衛(wèi)(router.beforeEach())的使用詳解
導航守衛(wèi)主要用來通過跳轉或取消的方式守衛(wèi)導航。這篇文章主要介紹了vue-router導航守衛(wèi)(router.beforeEach())的使用,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-04-04Vue?+?SpringBoot?實現(xiàn)文件的斷點上傳、秒傳存儲到Minio的操作方法
這篇文章主要介紹了Vue?+?SpringBoot?實現(xiàn)文件的斷點上傳、秒傳存儲到Minio的操作方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧2024-06-06vue3.0語法糖內的defineProps及defineEmits解析
這篇文章主要介紹了vue3.0語法糖內的defineProps及defineEmits解析,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-04-04