|
|
@@ -3,50 +3,27 @@ var Path = require('../parse/path')
|
|
|
var Observer = require('../observe/observer')
|
|
|
|
|
|
/**
|
|
|
- * Setup the binding tree.
|
|
|
+ * Setup the bindings.
|
|
|
*
|
|
|
- * Bindings form a tree-like structure that maps the Object
|
|
|
- * structure of observed data. However, only paths present
|
|
|
- * in the templates are created in the binding tree. When a
|
|
|
- * change event from the data observer arrives on the
|
|
|
- * instance, we traverse the binding tree along the changed
|
|
|
- * path to find the corresponding binding, and trigger
|
|
|
- * change for all its subscribers.
|
|
|
+ * Each accessed path in templates have a correspinding
|
|
|
+ * binding object. When a change is detected and emitted
|
|
|
+ * from the $observer, the corresponding binding notifies
|
|
|
+ * all its subscribing watchers to trigger updates.
|
|
|
*/
|
|
|
|
|
|
exports._initBindings = function () {
|
|
|
- var root = this._rootBinding = new Binding()
|
|
|
- // the $data binding points to the root itself!
|
|
|
- root._addChild('$data', root)
|
|
|
- // point $parent and $root bindings to their
|
|
|
- // repective owners.
|
|
|
- if (this.$parent) {
|
|
|
- root._addChild('$parent', this.$parent._rootBinding)
|
|
|
- root._addChild('$root', this.$root._rootBinding)
|
|
|
- }
|
|
|
+ this._bindings = Object.create(null)
|
|
|
+ this._createBindingAt('$data')
|
|
|
// setup observer events
|
|
|
this.$observer
|
|
|
// simple updates
|
|
|
- .on('set', this._updateBindingAt)
|
|
|
- .on('mutate', this._updateBindingAt)
|
|
|
- .on('delete', this._updateBindingAt)
|
|
|
+ .on('set', updateBindingAt)
|
|
|
+ .on('mutate', updateBindingAt)
|
|
|
+ .on('delete', updateBindingAt)
|
|
|
// adding properties is a bit different
|
|
|
- .on('add', this._updateAdd)
|
|
|
+ .on('add', updateAdd)
|
|
|
// collect dependency
|
|
|
- .on('get', this._collectDep)
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Retrive a binding at a given path.
|
|
|
- * If `create` is true, create all bindings that do not
|
|
|
- * exist yet along the way.
|
|
|
- *
|
|
|
- * @param {String} path
|
|
|
- * @return {Binding|undefined}
|
|
|
- */
|
|
|
-
|
|
|
-exports._getBindingAt = function (path) {
|
|
|
- return Path.getFromObserver(this._rootBinding, path)
|
|
|
+ .on('get', collectDep)
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -58,15 +35,7 @@ exports._getBindingAt = function (path) {
|
|
|
*/
|
|
|
|
|
|
exports._createBindingAt = function (path) {
|
|
|
- path = path.split(Observer.pathDelimiter)
|
|
|
- var b = this._rootBinding
|
|
|
- var child, key
|
|
|
- for (var i = 0, l = path.length; i < l; i++) {
|
|
|
- key = path[i]
|
|
|
- child = b[key] || b._addChild(key)
|
|
|
- b = child
|
|
|
- }
|
|
|
- return b
|
|
|
+ return this._bindings[path] = new Binding()
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -78,13 +47,13 @@ exports._createBindingAt = function (path) {
|
|
|
* @param {Boolean} fromScope
|
|
|
*/
|
|
|
|
|
|
-exports._updateBindingAt = function (path, k, v, fromScope) {
|
|
|
- // root binding updates on any change,
|
|
|
+function updateBindingAt (path, k, v, fromScope) {
|
|
|
+ // the '$data' binding updates on any change,
|
|
|
// but only if the change is not from parent scopes
|
|
|
if (!fromScope) {
|
|
|
- this._rootBinding._notify()
|
|
|
+ this._bindings.$data._notify()
|
|
|
}
|
|
|
- var binding = this._getBindingAt(path, true)
|
|
|
+ var binding = this._bindings[path]
|
|
|
if (binding) {
|
|
|
binding._notify()
|
|
|
}
|
|
|
@@ -101,10 +70,10 @@ exports._updateBindingAt = function (path, k, v, fromScope) {
|
|
|
* @param {String} path
|
|
|
*/
|
|
|
|
|
|
-exports._updateAdd = function (path) {
|
|
|
+function updateAdd (path) {
|
|
|
var index = path.lastIndexOf(Observer.pathDelimiter)
|
|
|
if (index > -1) path = path.slice(0, index)
|
|
|
- this._updateBindingAt(path)
|
|
|
+ updateBindingAt.call(this, path)
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -114,7 +83,7 @@ exports._updateAdd = function (path) {
|
|
|
* @param {String} path
|
|
|
*/
|
|
|
|
|
|
-exports._collectDep = function (path) {
|
|
|
+function collectDep (path) {
|
|
|
var watcher = this._activeWatcher
|
|
|
// the get event might have come from a child vm's watcher
|
|
|
// so this._activeWatcher is not guarunteed to be defined
|