-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
fix directives aren't cleaned up when component unmounts #5166
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
@vueuse/components
@vueuse/core
@vueuse/electron
@vueuse/firebase
@vueuse/integrations
@vueuse/math
@vueuse/metadata
@vueuse/nuxt
@vueuse/router
@vueuse/rxjs
@vueuse/shared
commit: |
| }, | ||
| unmounted(el) { | ||
| vElementHoverScopes.get(el)?.stop() | ||
| vElementHoverScopes.delete(el) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we could create an intentional factory function to generate the directive with mount/unmount hooks that have a more friendly way to register the clean up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think so, too
I think it can be like this. What do you think
creatFunc :
function createDirectiveHooks(
cleanupOnUnmount = false,
options?: {
mountedCallback?: (el: HTMLElement, binding: DirectiveBinding) => void
unmountedCallback?: (el: HTMLElement) => void
},
) {
const isFunc = (fn: unknown) => {
return typeof fn === 'function'
}
const { mountedCallback, unmountedCallback } = options ?? {}
const vDirectiveScopes = new WeakMap<HTMLElement, EffectScope>()
return {
mounted(el: HTMLElement, binding: DirectiveBinding) {
if (!cleanupOnUnmount) {
if (isFunc(mountedCallback))
mountedCallback(el, binding)
return
}
const scope = vDirectiveScopes.get(el) ?? effectScope()
vDirectiveScopes.set(el, scope)
scope.run(() => {
if (isFunc(mountedCallback))
mountedCallback(el, binding)
})
},
unmounted(el: HTMLElement) {
if (cleanupOnUnmount) {
vDirectiveScopes.get(el)?.stop()
vDirectiveScopes.delete(el)
}
if (isFunc(unmountedCallback))
unmountedCallback(el)
},
}
}use:
export const vElementHover: ObjectDirective<
HTMLElement,
BindingValueFunction | [handler: BindingValueFunction, options: UseElementHoverOptions]
> = {
// mounted(el, binding) {
// const scope = vElementHoverScopes.get(el) ?? effectScope()
// vElementHoverScopes.set(el, scope)
// scope.run(() => {
// const value = binding.value
// if (typeof value === 'function') {
// const isHovered = useElementHover(el)
// watch(isHovered, v => value(v))
// }
// else {
// const [handler, options] = value
// const isHovered = useElementHover(el, options)
// watch(isHovered, v => handler(v))
// }
// })
// },
// unmounted(el) {
// vElementHoverScopes.get(el)?.stop()
// vElementHoverScopes.delete(el)
// },
...createDirectiveHooks(
true,
{
mountedCallback: (el, binding) => {
const value = binding.value
if (typeof value === 'function') {
const isHovered = useElementHover(el)
watch(isHovered, v => value(v))
}
else {
const [handler, options] = value
const isHovered = useElementHover(el, options)
watch(isHovered, v => handler(v))
}
},
},
),
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had this idea before, but considering that all the modifications would turn into one submission
Before submitting the PR, please make sure you do the following
fixes #123).Description
resolve #5001
Additional context