]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(runtime-core): should disable tracking inside directive lifecycle hooks (#3699)
authorHcySunYang <HcySunYang@outlook.com>
Thu, 27 May 2021 20:53:19 +0000 (04:53 +0800)
committerGitHub <noreply@github.com>
Thu, 27 May 2021 20:53:19 +0000 (16:53 -0400)
packages/runtime-core/__tests__/directives.spec.ts
packages/runtime-core/src/directives.ts

index 3bca7c4e8d6c8e17ac21d2d1e98a16c175ccb54a..02d24711804773df53c3386024706cfaa7029bfe 100644 (file)
@@ -367,4 +367,32 @@ describe('directives', () => {
     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)
+  })
 })
index a19879081e12eceb779af0fe278edb086b3d8461..a82a9c7dec5d9855b1a86f87d5a0f495deae730c 100644 (file)
@@ -19,6 +19,7 @@ import { currentRenderingInstance } from './componentRenderContext'
 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
@@ -130,12 +131,16 @@ export function invokeDirectiveHook(
       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()
     }
   }
 }