ソースを参照

fix(core): skip mixins and extends if child is already merged (#8870)

fix #8865
Kael 7 年 前
コミット
80f17fa498
2 ファイル変更33 行追加7 行削除
  1. 14 7
      src/core/util/options.js
  2. 19 0
      test/unit/features/global-api/extend.spec.js

+ 14 - 7
src/core/util/options.js

@@ -378,15 +378,22 @@ export function mergeOptions (
   normalizeProps(child, vm)
   normalizeInject(child, vm)
   normalizeDirectives(child)
-  const extendsFrom = child.extends
-  if (extendsFrom) {
-    parent = mergeOptions(parent, extendsFrom, vm)
-  }
-  if (child.mixins) {
-    for (let i = 0, l = child.mixins.length; i < l; i++) {
-      parent = mergeOptions(parent, child.mixins[i], vm)
+  
+  // Apply extends and mixins on the child options,
+  // but only if it is a raw options object that isn't
+  // the result of another mergeOptions call.
+  // Only merged options has the _base property.
+  if (!child._base) {
+    if (child.extends) {
+      parent = mergeOptions(parent, child.extends, vm)
+    }
+    if (child.mixins) {
+      for (let i = 0, l = child.mixins.length; i < l; i++) {
+        parent = mergeOptions(parent, child.mixins[i], vm)
+      }
     }
   }
+
   const options = {}
   let key
   for (key in parent) {

+ 19 - 0
test/unit/features/global-api/extend.spec.js

@@ -71,6 +71,25 @@ describe('Global API: extend', () => {
     expect(calls).toEqual([1, 2, 3])
   })
 
+  it('should not merge nested mixins created with Vue.extend', () => {
+    const A = Vue.extend({
+      created: () => {}
+    })
+    const B = Vue.extend({
+      mixins: [A],
+      created: () => {}
+    })
+    const C = Vue.extend({
+      extends: B,
+      created: () => {}
+    })
+    const D = Vue.extend({
+      mixins: [C],
+      created: () => {}
+    })
+    expect(D.options.created.length).toBe(4)
+  })
+
   it('should merge methods', () => {
     const A = Vue.extend({
       methods: {