expect(d1.mounted).toHaveBeenCalled()
expect(d2.mounted).toHaveBeenCalled()
})
+
+ test('should disable tracking inside directive lifecycle hooks', async () => {
+ const count = ref(0)
+ const text = ref('')
+ const beforeUpdate = jest.fn(() => count.value++)
+
+ const App = {
+ render() {
+ return withDirectives(h('p', text.value), [
+ [
+ {
+ beforeUpdate
+ }
+ ]
+ ])
+ }
+ }
+
+ const root = nodeOps.createElement('div')
+ render(h(App), root)
+ expect(beforeUpdate).toHaveBeenCalledTimes(0)
+ expect(count.value).toBe(0)
+
+ text.value = 'foo'
+ await nextTick()
+ expect(beforeUpdate).toHaveBeenCalledTimes(1)
+ expect(count.value).toBe(1)
+ })
})
import { callWithAsyncErrorHandling, ErrorCodes } from './errorHandling'
import { ComponentPublicInstance } from './componentPublicInstance'
import { mapCompatDirectiveHook } from './compat/customDirective'
+import { pauseTracking, resetTracking } from '@vue/reactivity'
export interface DirectiveBinding<V = any> {
instance: ComponentPublicInstance | null
hook = mapCompatDirectiveHook(name, binding.dir, instance)
}
if (hook) {
+ // disable tracking inside all lifecycle hooks
+ // since they can potentially be called inside effects.
+ pauseTracking()
callWithAsyncErrorHandling(hook, instance, ErrorCodes.DIRECTIVE_HOOK, [
vnode.el,
binding,
vnode,
prevVNode
])
+ resetTracking()
}
}
}