ホームページ  >  記事  >  ウェブフロントエンド  >  vue3 フックが DataV の全画面コンテナ コンポーネントを再構築する方法

vue3 フックが DataV の全画面コンテナ コンポーネントを再構築する方法

王林
王林転載
2023-05-16 14:43:061010ブラウズ

実装

コンポーネントの作成

fullScreenContainer.vue

<template>
  <div id="dv-full-screen-container" :ref="autoBindRef">
    <slot></slot>
  </div>
</template>
<script setup lang="ts">
import { useAutoResize } from &#39;@/hooks/useAutoResize&#39;
const { autoBindRef } = useAutoResize()
</script>

フックをカスタマイズし、autoBindRefバインディングrefをエクスポートします

カスタムフックファイル

useAutoResize.ts

import { ref } from &#39;vue&#39;;
export function useAutoResize() {
    let domRef = ref<HTMLElement | null>();
    function autoBindRef() {
    }
    return {
        autoBindRef
    }
}

1. domRef のバインド

ロジックを続行する前に、必ず最初に dom 要素を取得してください。

正しい dom 要素を検出して取得する関数を作成します

function getRefDom(ref: HTMLElement | ComponentPublicInstance): HTMLElement | null {
  // ref指向dom,则返回ref
  // isElement检查指定的值是否为DOM元素
  if (isElement(ref)) {
    return ref as HTMLElement
  }
  // 若ref指向组件实例,通过$el获取dom元素
  if (isElement((ref as ComponentPublicInstance).$el)) {
    return (ref as ComponentPublicInstance).$el
  }
  return null
}

コンポーネント domRef

export function useAutoResize() {
    let domRef = ref<HTMLElement | null>();
    const autoBindRef = once((ref: HTMLElement | ComponentPublicInstance) =>  {
        const  dom = getRefDom(ref);
        if(!dom) {
            console.warn("绑定组件domRef失败!")
            return;
        }
        domRef.value = dom;
    })
    return {
        autoBindRef
    }
}

2 を自動的にバインドします。初期化

export function useAutoResize() {
    onMounted(() => {
        initDom(domRef.value)
        initConifg(domRef.value)
    })
}

マウントされた期間、 DOM はマウントされているため、このサイクル中に DOM 要素を取得する必要があります。

2.1. domの初期化
function initDom(dom:HTMLElement) {
    const { clientWidth = 0, clientHeight = 0 } = dom || {}
    if(!dom) {
        console.warn("获取dom节点失败,组件渲染可能异常!")
        return
    } else if(!clientWidth || !clientHeight) {
        console.warn("组件宽度或高度为0px,可能会出现渲染异常!")
        return
    }
    // 设置缩放比例
    if(typeof setAppSacle === &#39;function&#39;) setAppScale(dom)
}
2.2. デバイスの初期化

domを取得したら、取得したデバイスの画面解像度の幅と高さをdomに設定します。

function initConfig(dom:HTMLElement) {
    const { width, height } = screen || {}
    dom.style.width = `${width}px`;
    dom.style.height = `${height}px`;
}
2.3. ズーム効果の設定
function setAppScale(dom:HTMLElement){
    const currentWidth = document.body.clientWidth;
    const { width } = screen || {};
    dom.style.transform = `scale(${currentWidth / width})`;
}

この関数は、dom 要素が変更されたとき、またはウィンドウ サイズが変更されたときにトリガーされます。

3. イベントのリッスン/削除

dom 要素とウィンドウ サイズの変更を同時に監視する必要がある

Dom 要素の監視

ここで使用しますMutationObserverdom 要素の変更を監視するには

function observerDomResize(dom: HTMLElement, callback: () => void) {
    const observer = new MutationObserver(callback);
    observer.observe(dom, {
        attributes: true,
        attributeFilter: [&#39;style&#39;],
        attributeOldValue: true,
    })
    return observer
}

マウントされたサイクル中に監視を設定します

export function useAutoResize() {
    const handleInitDom = () => {
        initDom(domRef.value)
    }
    onMounted(() => {
        initDom(domRef.value)
        initConifg(domRef.value)
        observerDomResize(domRef.value, handleInitDom)
        window.removeEventListener(&#39;resize&#39;, handleInitDom);
    })
}

しかし、このように直接記述すると、handleInitDom 関数が頻繁に呼び出されることになります。無駄なので、イベント処理関数 handleInitDom を呼び出す前に手ぶれ補正機能を使ってラップしてください。

export function useAutoResize() {
    const domSizeEffectDisposer: (() => void)[] = [];
    const debounceInitDomFun = debounce(handleInitDom, 300)
    onMounted(() => {
        initDom(domRef.value)
        initConifg(domRef.value)
        observerDomResize(domRef.value, debounceInitDomFun)
        window.removeEventListener(&#39;resize&#39;, debounceInitDomFun);
        domSizeEffectDisposer.push(
          () => {
            if (!observer) return
            observer.disconnect();
            observer.takeRecords();
            observer = null;
          },
          () => {
            window.removeEventListener(&#39;resize&#39;, debounceInitDomFun);
          }
        );
    })
}

イベントをリッスンする場合は、コンポーネントがアンインストールされるときにイベントをクリアする必要があります

onUnmounted(() => {
    domSizeEffectDisposer.forEach(disposer => disposer())
  })

以上がvue3 フックが DataV の全画面コンテナ コンポーネントを再構築する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。