Skip to content

Commit ff50e8d

Browse files
authoredMay 27, 2021
fix(runtime-core): should disable tracking inside directive lifecycle hooks (#3699)
1 parent 9f24195 commit ff50e8d

File tree

2 files changed

+33
-0
lines changed

2 files changed

+33
-0
lines changed
 

‎packages/runtime-core/__tests__/directives.spec.ts

+28
Original file line numberDiff line numberDiff line change
@@ -367,4 +367,32 @@ describe('directives', () => {
367367
expect(d1.mounted).toHaveBeenCalled()
368368
expect(d2.mounted).toHaveBeenCalled()
369369
})
370+
371+
test('should disable tracking inside directive lifecycle hooks', async () => {
372+
const count = ref(0)
373+
const text = ref('')
374+
const beforeUpdate = jest.fn(() => count.value++)
375+
376+
const App = {
377+
render() {
378+
return withDirectives(h('p', text.value), [
379+
[
380+
{
381+
beforeUpdate
382+
}
383+
]
384+
])
385+
}
386+
}
387+
388+
const root = nodeOps.createElement('div')
389+
render(h(App), root)
390+
expect(beforeUpdate).toHaveBeenCalledTimes(0)
391+
expect(count.value).toBe(0)
392+
393+
text.value = 'foo'
394+
await nextTick()
395+
expect(beforeUpdate).toHaveBeenCalledTimes(1)
396+
expect(count.value).toBe(1)
397+
})
370398
})

‎packages/runtime-core/src/directives.ts

+5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { currentRenderingInstance } from './componentRenderContext'
1919
import { callWithAsyncErrorHandling, ErrorCodes } from './errorHandling'
2020
import { ComponentPublicInstance } from './componentPublicInstance'
2121
import { mapCompatDirectiveHook } from './compat/customDirective'
22+
import { pauseTracking, resetTracking } from '@vue/reactivity'
2223

2324
export interface DirectiveBinding<V = any> {
2425
instance: ComponentPublicInstance | null
@@ -130,12 +131,16 @@ export function invokeDirectiveHook(
130131
hook = mapCompatDirectiveHook(name, binding.dir, instance)
131132
}
132133
if (hook) {
134+
// disable tracking inside all lifecycle hooks
135+
// since they can potentially be called inside effects.
136+
pauseTracking()
133137
callWithAsyncErrorHandling(hook, instance, ErrorCodes.DIRECTIVE_HOOK, [
134138
vnode.el,
135139
binding,
136140
vnode,
137141
prevVNode
138142
])
143+
resetTracking()
139144
}
140145
}
141146
}

0 commit comments

Comments
 (0)