Skip to content

Commit

Permalink
allow child VMs $data to be swapped
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed Dec 24, 2013
1 parent 7c1d196 commit a1582e4
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 22 deletions.
2 changes: 0 additions & 2 deletions examples/todomvc/js/app.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
Vue.config({debug:true})

var filters = {
all: function () { return true },
active: function (completed) { return !completed },
Expand Down
35 changes: 21 additions & 14 deletions src/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ function Compiler (vm, options) {
var data = compiler.data = options.data || {}
utils.processOptions(options)
extend(compiler, options.compilerOptions)
extend(vm, options.data, true)
extend(vm, data, true)
extend(vm, options.methods, true)

// initialize element
Expand All @@ -44,7 +44,6 @@ function Compiler (vm, options) {
compiler.vm = vm
def(vm, '$', makeHash())
def(vm, '$el', el)
def(vm, '$data', data)
def(vm, '$compiler', compiler)

// keep track of directives and expressions
Expand Down Expand Up @@ -83,15 +82,13 @@ function Compiler (vm, options) {

// setup observer
compiler.setupObserver()

// beforeCompile hook
compiler.execHook('beforeCompile', 'created')
// the user might have set some props on the vm
// so copy it back to the data...
extend(data, vm)
// observe the data
Observer.observe(data, '', compiler.observer)

// for repeated items, create an index binding
// which should be inenumerable but configurable
if (compiler.repeat) {
Expand All @@ -100,16 +97,27 @@ function Compiler (vm, options) {
compiler.createBinding('$index')
}

Object.defineProperty(vm, '$data', {
enumerable: false,
get: function () {
return compiler.data
},
set: function (newData) {
var oldData = compiler.data
Observer.unobserve(oldData, '', compiler.observer)
compiler.data = newData
Observer.copyPaths(newData, oldData)
Observer.observe(newData, '', compiler.observer)
}
})

// now parse the DOM, during which we will create necessary bindings
// and bind the parsed directives
compiler.compile(el, true)

// extract dependencies for computed properties
if (computed.length) DepsParser.parse(computed)

// done!
compiler.init = false

// post compile / ready hook
compiler.execHook('afterCompile', 'ready')
}
Expand Down Expand Up @@ -409,7 +417,6 @@ CompilerProto.bindDirective = function (directive) {
CompilerProto.createBinding = function (key, isExp, isFn) {

var compiler = this,
data = compiler.data,
bindings = compiler.bindings,
binding = new Binding(compiler, key, isExp, isFn)

Expand All @@ -435,7 +442,7 @@ CompilerProto.createBinding = function (key, isExp, isFn) {
compiler.define(key, binding)
} else {
// ensure path in data so it can be observed
Observer.ensurePath(data, key)
Observer.ensurePath(compiler.data, key)
var parentKey = key.slice(0, key.lastIndexOf('.'))
if (!hasOwn.call(bindings, parentKey)) {
// this is a nested value binding, but the binding for its parent
Expand Down Expand Up @@ -477,19 +484,19 @@ CompilerProto.define = function (key, binding) {
Object.defineProperty(vm, key, {
get: binding.isComputed
? function () {
return data[key].$get()
return compiler.data[key].$get()
}
: function () {
return data[key]
return compiler.data[key]
},
set: binding.isComputed
? function (val) {
if (data[key].$set) {
data[key].$set(val)
if (compiler.data[key].$set) {
compiler.data[key].$set(val)
}
}
: function (val) {
data[key] = val
compiler.data[key] = val
}
})
}
Expand Down
2 changes: 1 addition & 1 deletion src/directives/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ module.exports = {
if (!this.component) {
this.build(value)
} else {
this.component.model = value
this.component.$data = value
}
},

Expand Down
6 changes: 3 additions & 3 deletions src/observer.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ function isWatchable (obj) {
*/
function emitSet (obj) {
var type = typeOf(obj),
emitter = obj.__observer__
emitter = obj && obj.__observer__
if (type === ARRAY) {
emitter.emit('set', 'length', obj.length)
} else if (type === OBJECT) {
Expand Down Expand Up @@ -292,7 +292,7 @@ function observe (obj, rawPath, observer) {
*/
function unobserve (obj, path, observer) {
if (!obj || !obj.__observer__) return
path = path + '.'
path = path ? path + '.' : ''
var proxies = observer.proxies[path]
if (!proxies) return
obj.__observer__
Expand All @@ -307,6 +307,6 @@ module.exports = {
unobserve : unobserve,
ensurePath : ensurePath,
convert : convert,
// used in v-repeat
copyPaths : copyPaths,
watchArray : watchArray,
}
2 changes: 1 addition & 1 deletion test/functional/fixtures/extend.html
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
log.textContent += ' C ready'
}
})
new T({
var test = new T({
el: '#test',
data: {
dirMsg: 'directive',
Expand Down
11 changes: 10 additions & 1 deletion test/functional/specs/extend.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
casper.test.begin('Encapsulation & Inheritance', 7, function (test) {
casper.test.begin('Encapsulation & Inheritance', 8, function (test) {

casper
.start('./fixtures/extend.html', function () {
Expand All @@ -11,6 +11,15 @@ casper.test.begin('Encapsulation & Inheritance', 7, function (test) {

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')

this.evaluate(function () {
test.vmData = {
selfMsg: 'replacing $data ',
msg: 'also works'
}
})

test.assertSelectorHasText('.vm-w-model', 'replacing $data also works')
})
.run(function () {
test.done()
Expand Down

0 comments on commit a1582e4

Please sign in to comment.