使用Vue3的composition API是否可以为方法中传递的元素制作可组合的元素?

xe55xuns  于 2023-04-21  发布在  Vue.js
关注(0)|答案(1)|浏览(164)

是否有可能将HTMLElement传递到可组合对象中?如果有,正确的方法是什么?
在学习了Vue关于可组合的示例之后,我想创建一个与他们的鼠标位置示例类似的示例,除了将其限制为在可组合函数中传递的元素。
我遇到的问题是,在onMounted生命周期方法之前传递对元素的引用意味着传递了null。此外,如果我调用父组件中的onMounted,则组合组件中的onMounted方法不会运行。
我真的不知道如何开始一个例子,因为我已经尝试了这么多的东西。有这样的例子吗?我已经检查了文档,我没有看到任何与组合和元素。也许这不是他们应该如何使用?
我理想的最终结果如下:(这不是工作代码)
mouse.ts

import { ref, watchEffect, onMounted, onUnmounted } from "vue"
import type { Ref } from "vue"

interface Coordinate {
    x: Ref
    y: Ref
}

export function useMouseIn(element: HTMLElement | null): Coordinate {
    const x = ref(0)
    const y = ref(0)

    if (!element) {
        return { x , y }
    }

    function update(event: MouseEvent) {
        if (!element) {
            return { x, y }
        }

        const rect = element.getBoundingClientRect()
        x.value = Math.ceil(event.clientX - rect.left)
        y.value = Math.ceil(event.clientY - rect.top)

        x.value = x.value < 0 ? x.value = 0 : x.value
        y.value = y.value < 0 ? y.value = 0 : y.value
    }

    onMounted(() => element.removeEventListener("mousemove", update))
    onUnmounted(() => element.removeEventListener("mousemove", update))

    return { x, y }
}

Panel.vue

<script setup lang="ts">
    import { ref } from "vue"
    import { useMouseIn } from "../composables/mouse"

    const panel = ref(null)
    const { x, y } = useMouseIn(panel.value)
</script>

<template>
    <div
        ref="panel"
        class="panel"
    >
    {{ x }}, {{ y }}
    </div>
</template>

<style scoped>
    .panel {
        width: 200px;
        height: 200px;
        background-color: grey;
    }
</style>

App.vue

<script setup lang="ts">
    import Panel from "./components/Panel.vue"
</script>

<template>
    <div>
        <Panel />
    </div>
</template>

我在Vue文档中似乎找不到这样的例子,但也许有一个库可以让我找到一些想法。

2w2cym1i

2w2cym1i1#

是的,你可以传入元素,如果你把它们作为引用传入,你可以让它成为动态的。设置会有一点变化,因为我们必须在每次元素改变时删除和添加事件监听器:

import { ref, isRef, unref, watch, onUnmounted } from "vue"

export function useMouseIn(element) {
    const x = ref(0)
    const y = ref(0)

    function setMouseListeners(){
      unref(element)?.addEventListener("mousemove", update)
    }

    function updateMouseListeners(newElement, oldElement){
      unref(oldElement)?.removeEventListener("mousemove", update)
      setMouseListeners()
    }

    function update(event) {
        const rect = this.getBoundingClientRect();
        x.value = event.clientX - rect.left;
        y.value = event.clientY - rect.top;
    }

    if (isRef(element)) { 
      watch(element, updateMouseListeners, {immediate: true})
    } else {
      setMouseListeners()
    }

    onUnmounted(() => unref(element)?.removeEventListener("mousemove", update))

    return { x, y }
}

下面是基于您的示例的sandbox

相关问题