Home > Web Front-end > Vue.js > How vue3 hook reconstructs DataV's full-screen container component

How vue3 hook reconstructs DataV's full-screen container component

王林
Release: 2023-05-16 14:43:06
forward
1094 people have browsed it

Implementation

Create component

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>
Copy after login

Customize a hook and export an autoBindRef binding ref

Custom hook file

useAutoResize.ts

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

1. Bind domRef

Make sure to get the dom element first before the logic can continue.

Create a function to detect and obtain the correct dom element

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
}
Copy after login

Automatically bind the component 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
    }
}
Copy after login

2. Initialization

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

mounted period, The DOM has been mounted, so the DOM elements need to be obtained during this cycle.

2.1. Initialize 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)
}
Copy after login
2.2. Initialize device

After obtaining the dom, set the obtained device screen resolution width and height to the dom.

function initConfig(dom:HTMLElement) {
    const { width, height } = screen || {}
    dom.style.width = `${width}px`;
    dom.style.height = `${height}px`;
}
Copy after login
2.3. Set the zoom effect
function setAppScale(dom:HTMLElement){
    const currentWidth = document.body.clientWidth;
    const { width } = screen || {};
    dom.style.transform = `scale(${currentWidth / width})`;
}
Copy after login

This function is triggered when the dom element changes/the window size changes.

3. Listening/removal events

Need to monitor changes in dom elements and window sizes at the same time

Dom element monitoring

Here we use MutationObserverTo monitor changes in dom elements

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

Set monitoring during the mounted cycle

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);
    })
}
Copy after login

But if we write it directly like this, it will frequently call the handleInitDom function, causing performance It's wasteful, so use the anti-shake function to wrap the event processing function handleInitDom before calling it.

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);
          }
        );
    })
}
Copy after login

If you listen to the event, you must clear it when the component is uninstalled

onUnmounted(() => {
    domSizeEffectDisposer.forEach(disposer => disposer())
  })
Copy after login

The above is the detailed content of How vue3 hook reconstructs DataV's full-screen container component. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:yisu.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template