hook inheritance

This commit is contained in:
Evan You 2013-12-19 00:20:00 -05:00
parent fede1eb80e
commit ea34d5692a
3 changed files with 56 additions and 9 deletions

View File

@ -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.

View File

@ -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>

View File

@ -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()