欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vue3 實(shí)現(xiàn)雙盒子定位Overlay的示例

 更新時(shí)間:2020年12月22日 09:11:55   作者:helloCat  
這篇文章主要介紹了Vue3 實(shí)現(xiàn)雙盒子定位Overlay的示例,幫助大家更好的理解和使用vue,感興趣的朋友可以了解下

在 Vue 3 中,使用 <Teleport> 可以很優(yōu)雅的把某個(gè)組件渲染到根節(jié)點(diǎn)之外的節(jié)點(diǎn),同時(shí)使其渲染的內(nèi)容不喪失響應(yīng)式和對(duì)應(yīng)的生命周期函數(shù)調(diào)用。那么基于此,用 <Teleport> 實(shí)現(xiàn)相對(duì)于某一元素的 Overlay 。 實(shí)際上,這篇文章跟 Vue3 的關(guān)系不大,只是通過(guò) Vue3 講解一類 Overlay 的設(shè)計(jì)方法。

原理

要實(shí)現(xiàn)相對(duì)于某一元素的 Overlay 需要依靠?jī)蓚€(gè)元素,Origin 和 Panel,Origin 表示相對(duì)于的元素,而 Panel 表示 Overlay 本身,實(shí)現(xiàn)方法主要有兩種。

文本流定位法,基于 position 的 absolute 和 relative 特性,將 Panel 形成相對(duì)于 Origin 的位置來(lái)定位的方式。
Overlay 基于 Origin 做固定偏移的雙盒子定位法,也就是本文需要講解的方法。
實(shí)現(xiàn) 首先,通過(guò)<Teleport>,能夠建立頂層 Overlay,也就是在根節(jié)點(diǎn)創(chuàng)建一個(gè)新的節(jié)點(diǎn)。

setup(_, ctx) {
 const originRef = ref<HTMLElement>();
 const panelRef = ref<HTMLElement>();
 const panelStyle = ref<CSSProperties>({ position: 'absolute' });
 // ...
 return () => (
  <>
   <div ref={originRef}>origin</div>

   <Teleport to="#cdk-overlay-anchor">
     <div style={{ position: 'fixed', top: 0, left: 0, right: 0, bottom: 0, height: '100vh', width: '100vw' pointerEvents: 'none'}}>
      <div ref={panelRef} style={panelStyle.value}>
       <div style={{height: '100px', width: '100px' border: '1px solid black'}} />
      </div>
     </div>
   </Teleport>
  </>
 );
}

拿到這兩者的 dom ref 后,需要通過(guò)實(shí)時(shí)計(jì)算 Origin 的盒子的大小和位置,來(lái)獲得 Panel 的相對(duì)偏移。在 Vue 中,元素只有在 mounted 后才能獲取得到,所以可以通過(guò) composition-api 的 onMouted 來(lái)獲取具體元素。然后再在 生命周期中 進(jìn)行計(jì)算。

計(jì)算兩個(gè)盒子的相對(duì)位置

如何計(jì)算 Origin 的大小和位置,以及獲取其變化后的監(jiān)聽(tīng)。Origin 的大小和位置,通過(guò) getBoundingClientRect 這一 API 來(lái)獲取,這一就可以開(kāi)始計(jì)算 Overlay 的相對(duì)位置。假設(shè)我們要把 Overlay 放在 Origin 的正下方,計(jì)算函數(shù)應(yīng)該是這樣的。

const panelStyle = ref<CSSProperties>({ position: 'absolute' });

onMounted(() => {
 const origin = originRef.value;
 const panel = panelRef.value;
 if (!origin || !panel) {
  return ;
 }

 const calculate = () => {
  const rect = origin.getBoundingClientRect();
  // 原點(diǎn)為 origin 元素的底邊中央正下方
  const originX = rect.left + (rect.width / 2);
  const originY = rect.bottom;

  // panel的坐標(biāo)為到原點(diǎn)的偏移
  const panelRect = panel.getBoundingClientRect();
  const panelX = originX - panelRect.width / 2;
  const panelY = originY;

  // 設(shè)置 panel 數(shù)據(jù),觸發(fā)節(jié)點(diǎn)變更
  panelStyle.value.left = `${panelX}px`;
  panelStyle.value.top = `${panelY}px`;
 };
});

當(dāng)然,你還可以計(jì)算各個(gè)不同方向的 Panel 坐標(biāo)(比如,正左、正上、正下等),排列組合一下,一共有種27不同的情況(每個(gè)點(diǎn)依賴于兩個(gè)變量 X 和 Y;每個(gè)變量有三種不同的情況,左、中、右,或者,上、中、下)。

監(jiān)聽(tīng)盒子的變化

在這里,我們將使用瀏覽器自帶的API 來(lái)對(duì)他們進(jìn)行監(jiān)聽(tīng)。通過(guò) MutationObserver 和 ResizeObserver,可以很輕松的監(jiān)聽(tīng) Origin 和 Panel 的大小和位置變化。

首先是監(jiān)聽(tīng) Origin 的大小和位置變化,這里采用的是 MutationObserver,因?yàn)閷?dǎo)致位置變化的原因只能是 style,所以只需要監(jiān)聽(tīng) style 的變化即可。

const origin$ = new MutationObserver(calculate);
origin$.observe(origin, {
 // 只需要拿到 attribute 的 style 的變化即可
 attributeFilter: ['style'],
});

Panel 只需要監(jiān)聽(tīng)其大小的變化,大小變化有一個(gè)更加完美的API, ResizeObserver。

const panel$ = new ResizeObserver(calculate);
panel$.observe(panel);

然后,需要在dom銷(xiāo)毀前取消監(jiān)聽(tīng)。

// dom銷(xiāo)毀前取消監(jiān)聽(tīng)
onBeforeUnmount(() => {
 origin$.disconnect();
 panel$.disconnect();
});

監(jiān)聽(tīng)窗口事件

為了能夠正確的獲取變化,我們需要監(jiān)聽(tīng)兩個(gè)事件:resize 和 scroll.

// 為了能夠在滾動(dòng)事件捕獲前進(jìn)行計(jì)算,帶有滾動(dòng)條的子元素也會(huì)因此觸發(fā)計(jì)算
window.addEventListener('scroll', calculate, true);
window.addEventListener('resize', calculate);
最后,仍然要在銷(xiāo)毀前取消事件。

// dom銷(xiāo)毀前取消監(jiān)聽(tīng)
onBeforeUnmount(() => {
 window.removeEventListener('scroll', calculate, true);
 window.removeEventListener('resize', calculate);
});

至此,已經(jīng)完成基本的雙盒子定位法的 Overlay 的設(shè)計(jì)。

小結(jié)

通過(guò)雙盒子定位來(lái)構(gòu)建的 Overlay 能夠有效規(guī)避 CSS 帶來(lái)的問(wèn)題 zindex 等一系列相關(guān)的問(wèn)題,只用通過(guò)計(jì)算盒子之間的相對(duì)偏移,就能讓 Panel 附著于 Origin 上,這樣,實(shí)現(xiàn)類似下拉或者 Tooltip 等功能的時(shí)候,就會(huì)非常有用。同時(shí),附上一個(gè)簡(jiǎn)單例子,希望能帶來(lái)一些啟發(fā)。

以上就是Vue3 實(shí)現(xiàn)雙盒子定位Overlay的示例的詳細(xì)內(nèi)容,更多關(guān)于vue3 實(shí)現(xiàn)Overlay的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • vue整合百度地圖顯示指定地點(diǎn)信息

    vue整合百度地圖顯示指定地點(diǎn)信息

    本文主要介紹了vue整合百度地圖顯示指定地點(diǎn)信息,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • vue+animation實(shí)現(xiàn)翻頁(yè)動(dòng)畫(huà)

    vue+animation實(shí)現(xiàn)翻頁(yè)動(dòng)畫(huà)

    這篇文章主要為大家詳細(xì)介紹了vue+animation實(shí)現(xiàn)翻頁(yè)動(dòng)畫(huà),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-06-06
  • vue中this.$refs的坑及解決

    vue中this.$refs的坑及解決

    這篇文章主要介紹了vue中this.$refs的坑及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • 最細(xì)致的vue.js基礎(chǔ)語(yǔ)法 值得收藏!

    最細(xì)致的vue.js基礎(chǔ)語(yǔ)法 值得收藏!

    這篇文章主要為大家推薦了一篇值得收藏和學(xué)習(xí)的vue.js最細(xì)致的基礎(chǔ)語(yǔ)法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • Vue組件的Prop命名約定詳解

    Vue組件的Prop命名約定詳解

    這篇文章主要為大家介紹了Vue組件的Prop命名約定詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • Vue父子組件通訊方式及實(shí)現(xiàn)方法

    Vue父子組件通訊方式及實(shí)現(xiàn)方法

    這篇文章主要介紹了Vue父子組件通訊方式及實(shí)現(xiàn)方法,文中通過(guò)代碼示例介紹的非常詳細(xì),對(duì)我們的學(xué)習(xí)或工作有一定的幫助,感興趣的同學(xué)可以參考閱讀下
    2023-06-06
  • vue分類篩選filter方法簡(jiǎn)單實(shí)例

    vue分類篩選filter方法簡(jiǎn)單實(shí)例

    這篇文章主要介紹了vue分類篩選filter方法的簡(jiǎn)單實(shí)例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • vue 項(xiàng)目中使用Loading組件的示例代碼

    vue 項(xiàng)目中使用Loading組件的示例代碼

    這篇文章主要介紹了vue 項(xiàng)目中使用Loading組件的示例代碼,使用 loding 過(guò)渡數(shù)據(jù)的加載時(shí)間
    2018-08-08
  • Element-ui DatePicker顯示周數(shù)的方法示例

    Element-ui DatePicker顯示周數(shù)的方法示例

    這篇文章主要介紹了Element-ui DatePicker顯示周數(shù)的方法示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • 詳解從vue的組件傳值著手觀察者模式

    詳解從vue的組件傳值著手觀察者模式

    本文詳細(xì)介紹了從vue的組件傳值著手觀察者模式,感興趣的同學(xué),可以參考下,理解其原理。
    2021-06-06

最新評(píng)論