js中可以給window去綁定縮放事件,從而去監(jiān)聽窗口大小的變化:
window.addEventListener('resize', () => {})
但是有時候窗口的大小并不會變化,變的是元素的大小,好像是沒有方法是可以直接監(jiān)聽元素的大小變化的,那如果有這個需求呢?
這次超人鴨也從一個真實需求講解,如何去監(jiān)聽一個元素的寬高變化,看圖:

image.png
在切換側(cè)邊欄的收縮時,右邊的內(nèi)容的寬度就會變化,此時我右邊是echart,echarts在初始化畫完之后,當(dāng)容器改變大小的時候,echart并不會響應(yīng)式的重新畫圖,需要我們手動去調(diào)用繪制echart的方法,所以,監(jiān)聽元素的寬度變化是關(guān)鍵。
- 下面超人鴨介紹使用自定義指令的方式,去監(jiān)聽元素的寬高變化:
directives: { // 使用局部注冊指令的方式
resize: { // 指令的名稱
bind(el, binding) { // el為綁定的元素,binding為綁定給指令的對象
let width = '', height = '';
function isReize() {
const style = document.defaultView.getComputedStyle(el);
if (width !== style.width || height !== style.height) {
binding.value(); // 關(guān)鍵
}
width = style.width;
height = style.height;
}
el.__vueSetInterval__ = setInterval(isReize, 300);
},
unbind(el) {
clearInterval(el.__vueSetInterval__);
}
}
}
//然后在html中
<div v-resize="resize"></div> // 綁定的resize是一個函數(shù)
//在methods中
resize() { // 當(dāng)寬高變化時就會執(zhí)行
//執(zhí)行某些操作
}
- 上面就是實現(xiàn)的方法,下面講一下這個自定義指令的實現(xiàn):
- 首先我采用局部注冊的方法,然后操作基本都放到bind這個鉤子函數(shù)中,看一下官方的解釋:bind:只調(diào)用一次,指令第一次綁定到元素時調(diào)用。在這里可以進行一次性的初始化設(shè)置。這個鉤子函數(shù)只會執(zhí)行一次,我們這個例子沒有涉及到數(shù)據(jù)的變化,如果有涉及到數(shù)據(jù)的變化,就應(yīng)該使用update:所在組件的 VNode 更新時調(diào)用
- 然后我定義兩個變量用來存儲寬高,并在isReize這個方法中去獲取寬高,這里用到document.defaultView.getComputedStyle(el),這個方法可以獲取元素的樣式,不局限寫在行內(nèi)的style。然后去跟原來的寬高比較,如果不同就執(zhí)行下面的 binding.value();
- binding.value就是我們在html中綁定給指令的值,<div v-resize="resize"></div>也就是resize,是個函數(shù)。這里很容易以為只能綁定字符串變量,但其實自定義指令的綁定值很強大,可以玩很多種花樣,大家可以看看官方文檔:自定義指令
- 最后我再下面賦值了定時器,每300毫秒去執(zhí)行一次,在unbind這個鉤子函數(shù)中清除定時器
到這里就實現(xiàn)了監(jiān)聽一個元素的寬高變化,并執(zhí)行相應(yīng)的操作,但如果是針對于echart,還需要在echart實例添加一個方法:
const myChart = echarts.init(document.getElementById(id))
****
myChart.resize()
超人鴨也是第一次嘗試vue中的自定義指令,如果有更好的解決方法歡迎指教哦。