I'm trying to turn some code into a reusable directive, but I'm getting errors when I load the page that contains it.
This is the file with the directive:
// I also tried "import type"
import { Directive } from "vue"
export const ViewedListener: Directive = {
mounted(el: HTMLElement, binding) {
const watcher = document.createElement("span")
watcher.style.position = "absolute"
watcher.style.pointerEvents = "none"
watcher.style.top = (binding.arg || "50") + "%"
el.style.position = "relative"
el.parentElement?.insertBefore(watcher, el)
const hook: IntersectionObserverCallback = (entries, observer) => {
if (!entries[0].isIntersecting)
return
binding.value(entries, observer)
observer.disconnect()
}
const observer = new IntersectionObserver(hook)
observer.observe(el)
},
}
This is a component where I use it:
<template>
<div v-html="dynamicallyLoadedContent" v-viewed-listener:75="viewHook" />
</template>
<script setup>
import { ViewedListener as vViewedListener } from "@/directives/viewed-listener"
const dynamicallyLoadedContent = "some long html"
</script>
When I load the page with the component, I get a bunch of errors:
[Vue warn]: Failed to resolve directive: viewed-listener
[Vue warn]: Unhandled error during execution of scheduler flush. This is likely a Vue internals bug.
Uncaught (in promise) TypeError: can't access property "created", binding.dir is undefined
This is an essentially useless error message, it's so vague that it's unusable. I wish they'd improve it and I'd even open an issue about it, but they make it so hard that I lose all motivation to do so as soon as I try to use their playground to make a reproducible example.
Note that the "scheduled flush" error also occurs in another unsolved problem I have. Maybe comparing the two can help find the point of failure.
What am I doing wrong, if anything? I've followed the short notes on the script setup proposal's example and I don't think I need to register the directive in main.ts (wouldn't that defeat the purpose of using the composition API?)