一、場景
這是一個常規的後臺管理系統的網站界面:
(orz……怎麼拉伸成這個樣子……)
我個人看這種界面的時候,是非常不喜歡豎向出現滾動條的,像搜索區域、工具欄這種固定的區域我希望是不動的,只需要拖拽表格的滾動條就可以看其他數據(就像上面的截圖)。
二、解決思路:
- header、麪包屑、頁碼器 的高度是固定的;
- 工具欄和搜索區域是不固定的,因爲具欄在一個操作權限都沒有的時候是看不到的,搜索條件每個界面是不固定的。
- this.$refs.ref.offsetHeight可以獲取到元素的高度。
- 當界面大小改變時,有window.onresize事件可以監聽,在監聽事件裏重新設置表格的高度即可;
綜合以上四個線索,很容易的就想到了
table height = window.innerHeight - 搜索區域高度 - 固定高度(header+麪包屑) - 工具欄高度;
其實!
沒錯!
就是這個思路!
但是有一些需要注意的地方:
- mounted節點確實可以獲取到dom元素了,但是並不是最終在界面上的準確佈局(位置,大小),所以要獲取 搜索區域和工具欄的高度的話,需要使用vue提供的this.$nextTick函數,它接受一個函數,在dom渲染完之後執行;
- 當用戶調整窗口大小的時候,是不是可以設置一個防抖的加強,防止過於頻繁的觸發 onresize事件;
- destroyed節點中要將onresize事件置爲空,防止內存泄漏,雖然現在大多數瀏覽器已經支持當元素移除的時候自動清除事件,但是扛不住有的奇葩遠古瀏覽器,比如IE6……
三、代碼:
1. 工具欄的高度:
因爲我的工具欄是包裝成組件的,所以props裏有一個屬性就是指定工具欄的高度:
提供一個獲取高度的方法給父組件調用:
這裏主要是判斷是否要顯示,因爲有的人可能一個操作的權限都沒有。
2. 包裝防抖函數,設置高度函數:
// 防抖
export const debounce = function(func, wait = 150) {
let timer = 0;
let self = this;
return function(...args) {
if (timer) {
// 如果在指定時間間隔內又再次觸發,則繼續延時
clearTimeout(timer);
}
// 重點:使用$nextTick函數
self.$nextTick(() => {
timer = setTimeout(() => {
func.apply(self, args);
}, wait);
});
};
};
export const resize = function () {
return debounce.call(this, function () {
// 190是固定高度的總和
this.tableOpts.height = window.innerHeight - this.$refs.searchDiv.offsetHeight - 190 - this.$refs.toolbar.getHeight();
});
};
父組件:
mounted() {
this.getTableData();
// 將vm實例通過call綁定,傳遞給resize函數
let func = this.$resize.call(this);
window.onresize = func;
func();
},
destroyed() {
// 移除事件監聽,防止內存泄漏
window.onresize = null;
}
這裏使用 this.$resize是因爲在main.js中,我將resize函數添加到Vue的原型對象上了,方便在任何地方都可以使用this訪問,不需要import;