mirror of https://github.com/vuejs/vue.git
allow multiple VMs sharing one data object
This commit is contained in:
parent
5b96bdc556
commit
75a4850afb
|
|
@ -6,18 +6,26 @@
|
|||
<script src="../dist/seed.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>a.b.c : <span sd-text="a.b.c"></span></h1>
|
||||
<h2>a.c : <span sd-text="a.c"></span></h2>
|
||||
<h3>Computed property that concats the two: <span sd-text="d"></span></h3>
|
||||
<button sd-on="click:one">one</button>
|
||||
<button sd-on="click:two">two</button>
|
||||
<button sd-on="click:three">three</button>
|
||||
<p><input sd-value="msg"></p>
|
||||
<div id="a">
|
||||
<h1>a.b.c : <span sd-text="a.b.c"></span></h1>
|
||||
<h2>a.c : <span sd-text="a.c"></span></h2>
|
||||
<h3>Computed property that concats the two: <span sd-text="d"></span></h3>
|
||||
<button sd-on="click:one">one</button>
|
||||
<button sd-on="click:two">two</button>
|
||||
<button sd-on="click:three">three</button>
|
||||
<p><input sd-value="msg"></p>
|
||||
</div>
|
||||
<div id="b">
|
||||
<h1 sd-text="a.c"></h1>
|
||||
</div>
|
||||
<script>
|
||||
seed.config({debug: true})
|
||||
var data = { c: 555 }
|
||||
var Demo = seed.ViewModel.extend({
|
||||
init: function () {
|
||||
this.msg = 'Yoyoyo' },
|
||||
this.msg = 'Yoyoyo'
|
||||
this.a = data
|
||||
},
|
||||
props: {
|
||||
one: function () {
|
||||
this.a = {
|
||||
|
|
@ -42,7 +50,13 @@
|
|||
}}
|
||||
}
|
||||
})
|
||||
var app = new Demo({ el: document.body })
|
||||
var app = new Demo({ el: '#a' }),
|
||||
app2 = new seed.ViewModel({
|
||||
el: '#b',
|
||||
data: {
|
||||
a: data
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -5,12 +5,10 @@ var Emitter = require('emitter'),
|
|||
Binding = require('./binding'),
|
||||
DirectiveParser = require('./directive-parser'),
|
||||
TextParser = require('./text-parser'),
|
||||
DepsParser = require('./deps-parser')
|
||||
|
||||
var slice = Array.prototype.slice
|
||||
|
||||
// late bindings
|
||||
var vmAttr, eachAttr
|
||||
DepsParser = require('./deps-parser'),
|
||||
slice = Array.prototype.slice,
|
||||
vmAttr,
|
||||
eachAttr
|
||||
|
||||
/*
|
||||
* The DOM compiler
|
||||
|
|
@ -59,17 +57,19 @@ function Compiler (vm, options) {
|
|||
|
||||
utils.log('\nnew VM instance: ', el, '\n')
|
||||
|
||||
// set el
|
||||
vm.$el = el
|
||||
// link it up!
|
||||
// set stuff on the ViewModel
|
||||
vm.$el = el
|
||||
vm.$compiler = this
|
||||
vm.$parent = options.parentCompiler && options.parentCompiler.vm
|
||||
|
||||
// now for the compiler itself...
|
||||
this.vm = vm
|
||||
this.el = vm.$el
|
||||
this.directives = []
|
||||
this.vm = vm
|
||||
this.el = el
|
||||
this.directives = []
|
||||
|
||||
// Store things during parsing to be processed afterwards,
|
||||
// because we want to have created all bindings before
|
||||
// observing values / parsing dependencies.
|
||||
var observables = this.observables = []
|
||||
var computed = this.computed = [] // computed props to parse deps from
|
||||
var ctxBindings = this.contextBindings = [] // computed props with dynamic context
|
||||
|
|
@ -86,25 +86,28 @@ function Compiler (vm, options) {
|
|||
// setup observer
|
||||
this.setupObserver()
|
||||
|
||||
// call user init
|
||||
// call user init. this will capture some initial values.
|
||||
if (options.init) {
|
||||
options.init.apply(vm, options.args || [])
|
||||
}
|
||||
|
||||
// now parse the DOM
|
||||
// now parse the DOM, during which we will create necessary bindings
|
||||
// and bind the parsed directives
|
||||
this.compileNode(this.el, true)
|
||||
|
||||
// for anything in viewmodel but not binded in DOM, create bindings for them
|
||||
// for anything in viewmodel but not binded in DOM, also create bindings for them
|
||||
for (key in vm) {
|
||||
if (vm.hasOwnProperty(key) &&
|
||||
key.charAt(0) !== '$' &&
|
||||
!this.bindings[key])
|
||||
!this.bindings.hasOwnProperty(key))
|
||||
{
|
||||
this.createBinding(key)
|
||||
}
|
||||
}
|
||||
|
||||
// observe root keys
|
||||
// observe root values so that they emit events when
|
||||
// their nested values change (for an Object)
|
||||
// or when they mutate (for an Array)
|
||||
var i = observables.length, binding
|
||||
while (i--) {
|
||||
binding = observables[i]
|
||||
|
|
@ -112,11 +115,10 @@ function Compiler (vm, options) {
|
|||
}
|
||||
// extract dependencies for computed properties
|
||||
if (computed.length) DepsParser.parse(computed)
|
||||
this.computed = null
|
||||
// extract dependencies for computed properties with dynamic context
|
||||
if (ctxBindings.length) this.bindContexts(ctxBindings)
|
||||
this.contextBindings = null
|
||||
|
||||
|
||||
this.observables = this.computed = this.contextBindings = null
|
||||
}
|
||||
|
||||
var CompilerProto = Compiler.prototype
|
||||
|
|
@ -129,7 +131,8 @@ var CompilerProto = Compiler.prototype
|
|||
CompilerProto.setupObserver = function () {
|
||||
|
||||
var bindings = this.bindings,
|
||||
observer = this.observer = new Emitter()
|
||||
observer = this.observer = new Emitter(),
|
||||
depsOb = DepsParser.observer
|
||||
|
||||
// a hash to hold event proxies for each root level key
|
||||
// so they can be referenced and removed later
|
||||
|
|
@ -138,15 +141,15 @@ CompilerProto.setupObserver = function () {
|
|||
// add own listeners which trigger binding updates
|
||||
observer
|
||||
.on('get', function (key) {
|
||||
if (DepsParser.observer.isObserving) {
|
||||
DepsParser.observer.emit('get', bindings[key])
|
||||
if (depsOb.isObserving && bindings[key]) {
|
||||
depsOb.emit('get', bindings[key])
|
||||
}
|
||||
})
|
||||
.on('set', function (key, val) {
|
||||
bindings[key].update(val)
|
||||
if (bindings[key]) bindings[key].update(val)
|
||||
})
|
||||
.on('mutate', function (key) {
|
||||
bindings[key].pub()
|
||||
if (bindings[key]) bindings[key].pub()
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -406,11 +409,13 @@ CompilerProto.define = function (key, binding) {
|
|||
binding.value.set(value)
|
||||
}
|
||||
} else if (value !== binding.value) {
|
||||
// unwatch the old value
|
||||
Observer.unobserve(binding.value, key, compiler.observer)
|
||||
// set new value
|
||||
binding.value = value
|
||||
compiler.observer.emit('set', key, value)
|
||||
// unwatch the old value!
|
||||
Observer.unobserve(binding.value, key, compiler.observer)
|
||||
// now watch the new one instead
|
||||
// now watch the new value, which in turn emits 'set'
|
||||
// for all its nested values
|
||||
Observer.observe(value, key, compiler.observer)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,6 +58,9 @@ function bind (obj, key, path, observer) {
|
|||
values = obj.__values__,
|
||||
fullKey = (path ? path + '.' : '') + key
|
||||
values[fullKey] = val
|
||||
// emit set on bind
|
||||
// this means when an object is observed it will emit
|
||||
// a first batch of set events.
|
||||
observer.emit('set', fullKey, val)
|
||||
def(obj, key, {
|
||||
enumerable: true,
|
||||
|
|
@ -89,6 +92,13 @@ function isWatchable (obj) {
|
|||
return type === 'Object' || type === 'Array'
|
||||
}
|
||||
|
||||
function emitSet (obj, observer) {
|
||||
var values = obj.__values__
|
||||
for (var key in values) {
|
||||
observer.emit('set', key, values[key])
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
observe: function (obj, path, observer) {
|
||||
|
|
@ -114,7 +124,9 @@ module.exports = {
|
|||
.on('get', proxies.get)
|
||||
.on('set', proxies.set)
|
||||
.on('mutate', proxies.mutate)
|
||||
if (!alreadyConverted) {
|
||||
if (alreadyConverted) {
|
||||
emitSet(obj, obj.__observer__)
|
||||
} else {
|
||||
watch(obj, null, ob)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue