Просмотр исходного кода

allow child VMs $data to be swapped

Evan You 12 лет назад
Родитель
Сommit
a1582e4904

+ 0 - 2
examples/todomvc/js/app.js

@@ -1,5 +1,3 @@
-Vue.config({debug:true})
-
 var filters = {
 var filters = {
     all: function () { return true },
     all: function () { return true },
     active: function (completed) { return !completed },
     active: function (completed) { return !completed },

+ 21 - 14
src/compiler.js

@@ -34,7 +34,7 @@ function Compiler (vm, options) {
     var data = compiler.data = options.data || {}
     var data = compiler.data = options.data || {}
     utils.processOptions(options)
     utils.processOptions(options)
     extend(compiler, options.compilerOptions)
     extend(compiler, options.compilerOptions)
-    extend(vm, options.data, true)
+    extend(vm, data, true)
     extend(vm, options.methods, true)
     extend(vm, options.methods, true)
 
 
     // initialize element
     // initialize element
@@ -44,7 +44,6 @@ function Compiler (vm, options) {
     compiler.vm  = vm
     compiler.vm  = vm
     def(vm, '$', makeHash())
     def(vm, '$', makeHash())
     def(vm, '$el', el)
     def(vm, '$el', el)
-    def(vm, '$data', data)
     def(vm, '$compiler', compiler)
     def(vm, '$compiler', compiler)
 
 
     // keep track of directives and expressions
     // keep track of directives and expressions
@@ -83,7 +82,6 @@ function Compiler (vm, options) {
 
 
     // setup observer
     // setup observer
     compiler.setupObserver()
     compiler.setupObserver()
-
     // beforeCompile hook
     // beforeCompile hook
     compiler.execHook('beforeCompile', 'created')
     compiler.execHook('beforeCompile', 'created')
     // the user might have set some props on the vm 
     // the user might have set some props on the vm 
@@ -91,7 +89,6 @@ function Compiler (vm, options) {
     extend(data, vm)
     extend(data, vm)
     // observe the data
     // observe the data
     Observer.observe(data, '', compiler.observer)
     Observer.observe(data, '', compiler.observer)
-
     // for repeated items, create an index binding
     // for repeated items, create an index binding
     // which should be inenumerable but configurable
     // which should be inenumerable but configurable
     if (compiler.repeat) {
     if (compiler.repeat) {
@@ -100,16 +97,27 @@ function Compiler (vm, options) {
         compiler.createBinding('$index')
         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
     // now parse the DOM, during which we will create necessary bindings
     // and bind the parsed directives
     // and bind the parsed directives
     compiler.compile(el, true)
     compiler.compile(el, true)
-
     // extract dependencies for computed properties
     // extract dependencies for computed properties
     if (computed.length) DepsParser.parse(computed)
     if (computed.length) DepsParser.parse(computed)
-
     // done!
     // done!
     compiler.init = false
     compiler.init = false
-
     // post compile / ready hook
     // post compile / ready hook
     compiler.execHook('afterCompile', 'ready')
     compiler.execHook('afterCompile', 'ready')
 }
 }
@@ -409,7 +417,6 @@ CompilerProto.bindDirective = function (directive) {
 CompilerProto.createBinding = function (key, isExp, isFn) {
 CompilerProto.createBinding = function (key, isExp, isFn) {
 
 
     var compiler = this,
     var compiler = this,
-        data = compiler.data,
         bindings = compiler.bindings,
         bindings = compiler.bindings,
         binding  = new Binding(compiler, key, isExp, isFn)
         binding  = new Binding(compiler, key, isExp, isFn)
 
 
@@ -435,7 +442,7 @@ CompilerProto.createBinding = function (key, isExp, isFn) {
             compiler.define(key, binding)
             compiler.define(key, binding)
         } else {
         } else {
             // ensure path in data so it can be observed
             // 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('.'))
             var parentKey = key.slice(0, key.lastIndexOf('.'))
             if (!hasOwn.call(bindings, parentKey)) {
             if (!hasOwn.call(bindings, parentKey)) {
                 // this is a nested value binding, but the binding for its parent
                 // this is a nested value binding, but the binding for its parent
@@ -477,19 +484,19 @@ CompilerProto.define = function (key, binding) {
     Object.defineProperty(vm, key, {
     Object.defineProperty(vm, key, {
         get: binding.isComputed
         get: binding.isComputed
             ? function () {
             ? function () {
-                return data[key].$get()
+                return compiler.data[key].$get()
             }
             }
             : function () {
             : function () {
-                return data[key]
+                return compiler.data[key]
             },
             },
         set: binding.isComputed
         set: binding.isComputed
             ? function (val) {
             ? function (val) {
-                if (data[key].$set) {
-                    data[key].$set(val)
+                if (compiler.data[key].$set) {
+                    compiler.data[key].$set(val)
                 }
                 }
             }
             }
             : function (val) {
             : function (val) {
-                data[key] = val
+                compiler.data[key] = val
             }
             }
     })
     })
 }
 }

+ 1 - 1
src/directives/component.js

@@ -12,7 +12,7 @@ module.exports = {
         if (!this.component) {
         if (!this.component) {
             this.build(value)
             this.build(value)
         } else {
         } else {
-            this.component.model = value
+            this.component.$data = value
         }
         }
     },
     },
 
 

+ 3 - 3
src/observer.js

@@ -175,7 +175,7 @@ function isWatchable (obj) {
  */
  */
 function emitSet (obj) {
 function emitSet (obj) {
     var type = typeOf(obj),
     var type = typeOf(obj),
-        emitter = obj.__observer__
+        emitter = obj && obj.__observer__
     if (type === ARRAY) {
     if (type === ARRAY) {
         emitter.emit('set', 'length', obj.length)
         emitter.emit('set', 'length', obj.length)
     } else if (type === OBJECT) {
     } else if (type === OBJECT) {
@@ -292,7 +292,7 @@ function observe (obj, rawPath, observer) {
  */
  */
 function unobserve (obj, path, observer) {
 function unobserve (obj, path, observer) {
     if (!obj || !obj.__observer__) return
     if (!obj || !obj.__observer__) return
-    path = path + '.'
+    path = path ? path + '.' : ''
     var proxies = observer.proxies[path]
     var proxies = observer.proxies[path]
     if (!proxies) return
     if (!proxies) return
     obj.__observer__
     obj.__observer__
@@ -307,6 +307,6 @@ module.exports = {
     unobserve   : unobserve,
     unobserve   : unobserve,
     ensurePath  : ensurePath,
     ensurePath  : ensurePath,
     convert     : convert,
     convert     : convert,
-    // used in v-repeat
+    copyPaths   : copyPaths,
     watchArray  : watchArray,
     watchArray  : watchArray,
 }
 }

+ 1 - 1
test/functional/fixtures/extend.html

@@ -61,7 +61,7 @@
                     log.textContent += ' C ready'
                     log.textContent += ' C ready'
                 }
                 }
             })
             })
-            new T({
+            var test = new T({
                 el: '#test',
                 el: '#test',
                 data: {
                 data: {
                     dirMsg: 'directive',
                     dirMsg: 'directive',

+ 10 - 1
test/functional/specs/extend.js

@@ -1,4 +1,4 @@
-casper.test.begin('Encapsulation & Inheritance', 7, function (test) {
+casper.test.begin('Encapsulation & Inheritance', 8, function (test) {
     
     
     casper
     casper
     .start('./fixtures/extend.html', function () {
     .start('./fixtures/extend.html', function () {
@@ -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('#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')
         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 () {
     .run(function () {
         test.done()
         test.done()