]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(runtime-core): properly call lifecycle hooks in chained mixins & extends (#1974)
authorHcySunYang <HcySunYang@outlook.com>
Wed, 26 Aug 2020 14:31:23 +0000 (22:31 +0800)
committerGitHub <noreply@github.com>
Wed, 26 Aug 2020 14:31:23 +0000 (10:31 -0400)
fix #1973

packages/runtime-core/__tests__/apiOptions.spec.ts
packages/runtime-core/src/componentOptions.ts

index d61d46be363dc1bb5a46e25b24053ebec080d68f..e3151fbfa420783139dc02a7e292bfc162323fd4 100644 (file)
@@ -633,6 +633,71 @@ describe('api: options', () => {
     expect(calls).toEqual(['base', 'mixin', 'comp'])
   })
 
+  test('beforeCreate/created in extends and mixins', () => {
+    const calls: string[] = []
+    const BaseA = {
+      beforeCreate() {
+        calls.push('beforeCreateA')
+      },
+      created() {
+        calls.push('createdA')
+      }
+    }
+    const BaseB = {
+      extends: BaseA,
+      beforeCreate() {
+        calls.push('beforeCreateB')
+      },
+      created() {
+        calls.push('createdB')
+      }
+    }
+
+    const MixinA = {
+      beforeCreate() {
+        calls.push('beforeCreateC')
+      },
+      created() {
+        calls.push('createdC')
+      }
+    }
+    const MixinB = {
+      mixins: [MixinA],
+      beforeCreate() {
+        calls.push('beforeCreateD')
+      },
+      created() {
+        calls.push('createdD')
+      }
+    }
+
+    const Comp = {
+      extends: BaseB,
+      mixins: [MixinB],
+      beforeCreate() {
+        calls.push('selfBeforeCreate')
+      },
+      created() {
+        calls.push('selfCreated')
+      },
+      render() {}
+    }
+
+    renderToString(h(Comp))
+    expect(calls).toEqual([
+      'beforeCreateA',
+      'beforeCreateB',
+      'beforeCreateC',
+      'beforeCreateD',
+      'selfBeforeCreate',
+      'createdA',
+      'createdB',
+      'createdC',
+      'createdD',
+      'selfCreated'
+    ])
+  })
+
   test('accessing setup() state from options', async () => {
     const Comp = defineComponent({
       setup() {
index ff3927004ed57fda3e6bcd44f584a06ef4edb3c3..facca201d9e39ea338c3d58045cd21efec03dc68 100644 (file)
@@ -614,11 +614,11 @@ function callSyncHook(
   globalMixins: ComponentOptions[]
 ) {
   callHookFromMixins(name, globalMixins, ctx)
-  const baseHook = options.extends && options.extends[name]
-  if (baseHook) {
-    baseHook.call(ctx)
+
+  const { extends: base, mixins } = options
+  if (base) {
+    callHookFromExtends(name, base, ctx)
   }
-  const mixins = options.mixins
   if (mixins) {
     callHookFromMixins(name, mixins, ctx)
   }
@@ -628,12 +628,30 @@ function callSyncHook(
   }
 }
 
+function callHookFromExtends(
+  name: 'beforeCreate' | 'created',
+  base: ComponentOptions,
+  ctx: ComponentPublicInstance
+) {
+  if (base.extends) {
+    callHookFromExtends(name, base.extends, ctx)
+  }
+  const baseHook = base[name]
+  if (baseHook) {
+    baseHook.call(ctx)
+  }
+}
+
 function callHookFromMixins(
   name: 'beforeCreate' | 'created',
   mixins: ComponentOptions[],
   ctx: ComponentPublicInstance
 ) {
   for (let i = 0; i < mixins.length; i++) {
+    const chainedMixins = mixins[i].mixins
+    if (chainedMixins) {
+      callHookFromMixins(name, chainedMixins, ctx)
+    }
     const fn = mixins[i][name]
     if (fn) {
       fn.call(ctx)