Browse Source

hook inheritance

Evan You 12 years ago
parent
commit
ea34d5692a
3 changed files with 56 additions and 9 deletions
  1. 28 7
      src/main.js
  2. 22 0
      test/functional/fixtures/extend.html
  3. 6 2
      test/functional/specs/extend.js

+ 28 - 7
src/main.js

@@ -74,9 +74,11 @@ function extend (options) {
     options = inheritOptions(options, ParentVM.options, true)
     utils.processOptions(options)
 
-    var ExtendedVM = function (opts) {
-        opts = inheritOptions(opts, options, true)
-        ParentVM.call(this, opts)
+    var ExtendedVM = function (opts, asParent) {
+        if (!asParent) {
+            opts = inheritOptions(opts, options, true)
+        }
+        ParentVM.call(this, opts, true)
     }
 
     // inherit prototype props
@@ -118,15 +120,34 @@ function inheritOptions (child, parent, topLevel) {
     if (!parent) return child
     for (var key in parent) {
         if (key === 'el' || key === 'proto') continue
-        if (!child[key]) { // child has priority
-            child[key] = parent[key]
-        } else if (topLevel && utils.typeOf(child[key]) === 'Object') {
-            inheritOptions(child[key], parent[key], false)
+        var val = child[key],
+            parentVal = parent[key],
+            type = utils.typeOf(val)
+        if (topLevel && type === 'Function' && parentVal) {
+            // merge hook functions
+            child[key] = mergeHook(val, parentVal)
+        } else if (topLevel && type === 'Object') {
+            // merge toplevel object options
+            inheritOptions(val, parentVal)
+        } else if (val === undefined) {
+            // inherit if child doesn't override
+            child[key] = parentVal
         }
     }
     return child
 }
 
+/**
+ *  Merge hook functions
+ *  so parent hooks also get called
+ */
+function mergeHook (fn, parentFn) {
+    return function (opts) {
+        parentFn.call(this, opts)
+        fn.call(this, opts)
+    }
+}
+
 /**
  *  Update prefix for some special directives
  *  that are used in compilation.

+ 22 - 0
test/functional/fixtures/encapsulation.html → test/functional/fixtures/extend.html

@@ -6,6 +6,7 @@
         <script src="../../../dist/vue.js"></script>
     </head>
     <body>
+        <div id="log"></div>
         <div id="test">
             <div class="dir" v-hola="dirMsg"></div>
             <div class="filter">{{filterMsg | nodigits}}</div>
@@ -13,8 +14,18 @@
             <div class="vm" v-component="vm-test">{{vmMsg}}</div>
             <div class="vm-w-model" v-component="vm-w-model:vmData">{{msg + model.msg}}</div>
         </div>
+        <div id="child">
+            <div class="cvm" v-component="vm-test">{{vmMsg}}</div>
+        </div>
         <script>
+            var log = document.getElementById('log')
             var T = Vue.extend({
+                created: function () {
+                    log.textContent += ' T created'  
+                },
+                ready: function () {
+                    log.textContent += ' T ready'
+                },
                 components: {
                     'vm-test': {
                         scope: {
@@ -41,6 +52,14 @@
                     }
                 }
             })
+            var C = T.extend({
+                created: function () {
+                    log.textContent += ' C created'  
+                },
+                ready: function () {
+                    log.textContent += ' C ready'
+                }
+            })
             new T({
                 el: '#test',
                 scope: {
@@ -52,6 +71,9 @@
                     }
                 }
             })
+            new C({
+                el: '#child'
+            })
         </script>
     </body>
 </html>

+ 6 - 2
test/functional/specs/encapsulation.js → test/functional/specs/extend.js

@@ -1,12 +1,16 @@
-casper.test.begin('Component Encapsulation', 5, function (test) {
+casper.test.begin('Encapsulation & Inheritance', 7, function (test) {
     
     casper
-    .start('./fixtures/encapsulation.html', function () {
+    .start('./fixtures/extend.html', function () {
+
         test.assertSelectorHasText('.dir', 'directive works')
         test.assertSelectorHasText('.filter', 'filter works')
         test.assertSelectorHasText('.partial', 'partial works')
         test.assertSelectorHasText('.vm', 'component works')
         test.assertSelectorHasText('.vm-w-model', 'component with model works')
+
+        test.assertSelectorHasText('#log', 'T created T ready T created C created T ready C ready', 'hook inheritance works')
+        test.assertSelectorHasText('.cvm', 'component works', 'Child should have access to Parent options')
     })
     .run(function () {
         test.done()