|
|
|
@ -871,11 +871,155 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var falsy$1; |
|
|
|
|
var operators = { |
|
|
|
|
'||': falsy$1, |
|
|
|
|
'&&': falsy$1, |
|
|
|
|
'(': falsy$1, |
|
|
|
|
')': falsy$1 |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
function runBinaryFunction(binarys) { |
|
|
|
|
var expr = ''; |
|
|
|
|
for (var i = 0, len = binarys.length; i < len; i++) { |
|
|
|
|
if (_.isBoolean(binarys[i]) || _.has(operators, binarys[i])) { |
|
|
|
|
expr += binarys[i]; |
|
|
|
|
} else { |
|
|
|
|
expr += 'false'; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return new Function('return ' + expr)(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function routeToRegExp(route) { |
|
|
|
|
route = route.replace(/\*./g, '[a-zA-Z0-9_]+.'); |
|
|
|
|
return '^' + route + '$'; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function watch(model, expOrFn, cb, options) { |
|
|
|
|
if (isPlainObject(cb)) { |
|
|
|
|
options = cb; |
|
|
|
|
cb = cb.handler; |
|
|
|
|
} |
|
|
|
|
if (typeof cb === 'string') { |
|
|
|
|
cb = model[cb]; |
|
|
|
|
} |
|
|
|
|
options = options || {}; |
|
|
|
|
options.user = true; |
|
|
|
|
var exps = void 0; |
|
|
|
|
if (_.isFunction(expOrFn) || !(exps = expOrFn.match(/[a-zA-Z0-9_.*]+|[|][|]|[&][&]|[(]|[)]/g)) || exps.length === 1 && !/\*/.test(expOrFn)) { |
|
|
|
|
var watcher = new Watcher(model, expOrFn, cb, options); |
|
|
|
|
if (options.immediate) { |
|
|
|
|
cb(watcher.value); |
|
|
|
|
} |
|
|
|
|
return function unwatchFn() { |
|
|
|
|
watcher.teardown(); |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
var watchers = []; |
|
|
|
|
var fns = exps.slice(); |
|
|
|
|
var complete = false, |
|
|
|
|
running = false; |
|
|
|
|
var callback = function callback(index) { |
|
|
|
|
if (complete === true) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
fns[index] = true; |
|
|
|
|
if (runBinaryFunction(fns)) { |
|
|
|
|
complete = true; |
|
|
|
|
cb(); |
|
|
|
|
} |
|
|
|
|
if (!running) { |
|
|
|
|
running = true; |
|
|
|
|
nextTick(function () { |
|
|
|
|
complete = false; |
|
|
|
|
running = false; |
|
|
|
|
fns = exps.slice(); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
_.each(exps, function (exp, i) { |
|
|
|
|
if (_.has(operators, exp)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
//a.**或a.*形式
|
|
|
|
|
if (/^[1-9a-zA-Z.]+(\*\*$|\*$)/.test(exp)) { |
|
|
|
|
var isGlobal = /\*\*$/.test(exp); |
|
|
|
|
if (isGlobal) { |
|
|
|
|
//a.**的形式
|
|
|
|
|
exp = exp.replace(".**", ""); |
|
|
|
|
} else { |
|
|
|
|
//a.*的形式
|
|
|
|
|
exp = exp.replace(".*", ""); |
|
|
|
|
} |
|
|
|
|
var getter = parsePath(exp); |
|
|
|
|
var v = getter.call(model, model); |
|
|
|
|
var dep = new Dep(); |
|
|
|
|
if (isGlobal) { |
|
|
|
|
(v.__ob__._scopeDeps || (v.__ob__._scopeDeps = [])).push(dep); |
|
|
|
|
} else { |
|
|
|
|
(v.__ob__._deps || (v.__ob__._deps = [])).push(dep); |
|
|
|
|
} |
|
|
|
|
var w = new Watcher(model, function () { |
|
|
|
|
dep.depend(); |
|
|
|
|
return NaN; |
|
|
|
|
}, function () { |
|
|
|
|
callback(i); |
|
|
|
|
}); |
|
|
|
|
watchers.push(function unwatchFn() { |
|
|
|
|
w.teardown(); |
|
|
|
|
v.__ob__._scopeDeps && remove(v.__ob__._scopeDeps, dep); |
|
|
|
|
v.__ob__._deps && remove(v.__ob__._deps, dep); |
|
|
|
|
}); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (/\*\*$|\*$/.test(exp)) { |
|
|
|
|
throw new Error('not support'); |
|
|
|
|
} |
|
|
|
|
//其他含有*的情况,如*.a,*.*.a,a.*.a.*
|
|
|
|
|
if (/\*/.test(exp)) { |
|
|
|
|
//补全路径
|
|
|
|
|
var parent = model.__ob__.parent, |
|
|
|
|
root = model.__ob__; |
|
|
|
|
while (parent) { |
|
|
|
|
exp = '*.' + exp; |
|
|
|
|
root = parent; |
|
|
|
|
parent = parent.parent; |
|
|
|
|
} |
|
|
|
|
var regStr = routeToRegExp(exp); |
|
|
|
|
var _dep = new Dep(); |
|
|
|
|
root._globalDeps || (root._globalDeps = {}); |
|
|
|
|
root._globalDeps[regStr] = _dep; |
|
|
|
|
|
|
|
|
|
var _w = new Watcher(model, function () { |
|
|
|
|
_dep.depend(); |
|
|
|
|
return NaN; |
|
|
|
|
}, function () { |
|
|
|
|
callback(i); |
|
|
|
|
}); |
|
|
|
|
watchers.push(function unwatchFn() { |
|
|
|
|
_w.teardown(); |
|
|
|
|
root._globalDeps && delete root._globalDeps[regStr]; |
|
|
|
|
}); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
var watcher = new Watcher(model, exp, function () { |
|
|
|
|
callback(i); |
|
|
|
|
}, options); |
|
|
|
|
watchers.push(function unwatchFn() { |
|
|
|
|
watcher.teardown(); |
|
|
|
|
}); |
|
|
|
|
}); |
|
|
|
|
return watchers; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var computedWatcherOptions = { lazy: true }; |
|
|
|
|
|
|
|
|
|
function initState(vm, state) { |
|
|
|
|
if (state) { |
|
|
|
|
vm.$$state = observe(state).model; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function initComputed(vm, computed) { |
|
|
|
|
var watchers = vm._computedWatchers = {}; |
|
|
|
@ -942,10 +1086,10 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
|
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function initWatch(vm, watch) { |
|
|
|
|
function initWatch(vm, watch$$1) { |
|
|
|
|
vm._watchers || (vm._watchers = []); |
|
|
|
|
for (var key in watch) { |
|
|
|
|
var handler = watch[key]; |
|
|
|
|
for (var key in watch$$1) { |
|
|
|
|
var handler = watch$$1[key]; |
|
|
|
|
if (_.isArray(handler)) { |
|
|
|
|
for (var i = 0; i < handler.length; i++) { |
|
|
|
|
vm._watchers.push(createWatcher(vm, key, handler[i])); |
|
|
|
@ -956,8 +1100,10 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function createWatcher(vm, keyOrFn, handler, options) { |
|
|
|
|
return Fix.watch(vm.model, keyOrFn, _.bind(handler, vm), options); |
|
|
|
|
function createWatcher(vm, keyOrFn, handler) { |
|
|
|
|
return watch(vm.model, keyOrFn, _.bind(handler, vm.$$model ? vm.model : vm), { |
|
|
|
|
sync: true |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function initMethods(vm, methods) { |
|
|
|
@ -1012,7 +1158,16 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
|
|
|
|
|
if (vm.$$state && key in vm.$$state) { |
|
|
|
|
return vm.$$state[key]; |
|
|
|
|
} |
|
|
|
|
return vm.$$model[key]; |
|
|
|
|
if (vm.$$model && key in vm.$$model) { |
|
|
|
|
return vm.$$model; |
|
|
|
|
} |
|
|
|
|
var p = vm._parent; |
|
|
|
|
while (p) { |
|
|
|
|
if (p.$$context && key in p.$$context) { |
|
|
|
|
return p.$$context[key]; |
|
|
|
|
} |
|
|
|
|
p = p._parent; |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
set: function set(val) { |
|
|
|
|
if (vm.$$state && key in vm.$$state) { |
|
|
|
@ -1021,6 +1176,13 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
|
|
|
|
|
if (vm.$$model && key in vm.$$model) { |
|
|
|
|
return vm.$$model[key] = val; |
|
|
|
|
} |
|
|
|
|
var p = vm._parent; |
|
|
|
|
while (p) { |
|
|
|
|
if (p.$$context && key in p.$$context) { |
|
|
|
|
return p.$$context[key] = val; |
|
|
|
|
} |
|
|
|
|
p = p._parent; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
@ -1032,6 +1194,31 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
|
|
|
|
|
vm.model = createViewModel$1({}, props); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function defineContext(vm, keys) { |
|
|
|
|
var props = {}; |
|
|
|
|
|
|
|
|
|
var _loop2 = function _loop2(i, len) { |
|
|
|
|
var key = keys[i]; |
|
|
|
|
if (!(key in $$skipArray)) { |
|
|
|
|
props[key] = { |
|
|
|
|
enumerable: true, |
|
|
|
|
configurable: true, |
|
|
|
|
get: function get() { |
|
|
|
|
return vm.model[key]; |
|
|
|
|
}, |
|
|
|
|
set: function set(val) { |
|
|
|
|
return vm.model[key] = val; |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
for (var i = 0, len = keys.length; i < len; i++) { |
|
|
|
|
_loop2(i, len); |
|
|
|
|
} |
|
|
|
|
vm.$$context = createViewModel$1({}, props); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var Model = function () { |
|
|
|
|
function Model(model) { |
|
|
|
|
_classCallCheck(this, Model); |
|
|
|
@ -1044,15 +1231,17 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
|
|
|
|
|
} else { |
|
|
|
|
this.options = model || {}; |
|
|
|
|
} |
|
|
|
|
this._parent = Model.target; |
|
|
|
|
var state = _.isFunction(this.state) ? this.state() : this.state; |
|
|
|
|
var keys = _.keys(this.$$model).concat(_.keys(state)).concat(_.keys(this.computed)); |
|
|
|
|
var keys = _.keys(this.$$model).concat(_.keys(state)).concat(_.keys(this.computed)).concat(this.context); |
|
|
|
|
defineProps(this, keys); |
|
|
|
|
this.childContext && defineContext(this, this.childContext); |
|
|
|
|
this.$$model && (this.model.__ob__ = this.$$model.__ob__); |
|
|
|
|
state && initState(this, state); |
|
|
|
|
this._init(); |
|
|
|
|
initState(this, state); |
|
|
|
|
initComputed(this, this.computed); |
|
|
|
|
initWatch(this, this.watch); |
|
|
|
|
initMethods(this, this.actions); |
|
|
|
|
this._init(); |
|
|
|
|
if (this.$$model) { |
|
|
|
|
return this.model; |
|
|
|
|
} |
|
|
|
@ -1080,148 +1269,6 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
|
|
|
|
|
return Model; |
|
|
|
|
}(); |
|
|
|
|
|
|
|
|
|
var falsy$1; |
|
|
|
|
var operators = { |
|
|
|
|
'||': falsy$1, |
|
|
|
|
'&&': falsy$1, |
|
|
|
|
'(': falsy$1, |
|
|
|
|
')': falsy$1 |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
function runBinaryFunction(binarys) { |
|
|
|
|
var expr = ''; |
|
|
|
|
for (var i = 0, len = binarys.length; i < len; i++) { |
|
|
|
|
if (_.isBoolean(binarys[i]) || _.has(operators, binarys[i])) { |
|
|
|
|
expr += binarys[i]; |
|
|
|
|
} else { |
|
|
|
|
expr += 'false'; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return new Function('return ' + expr)(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function routeToRegExp(route) { |
|
|
|
|
route = route.replace(/\*./g, '[a-zA-Z0-9_]+.'); |
|
|
|
|
return '^' + route + '$'; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function watch(model, expOrFn, cb, options) { |
|
|
|
|
if (isPlainObject(cb)) { |
|
|
|
|
options = cb; |
|
|
|
|
cb = cb.handler; |
|
|
|
|
} |
|
|
|
|
if (typeof cb === 'string') { |
|
|
|
|
cb = model[cb]; |
|
|
|
|
} |
|
|
|
|
options = options || {}; |
|
|
|
|
options.user = true; |
|
|
|
|
var exps = void 0; |
|
|
|
|
if (_.isFunction(expOrFn) || !(exps = expOrFn.match(/[a-zA-Z0-9_.*]+|[|][|]|[&][&]|[(]|[)]/g)) || exps.length === 1 && !/\*/.test(expOrFn)) { |
|
|
|
|
var watcher = new Watcher(model, expOrFn, cb, options); |
|
|
|
|
if (options.immediate) { |
|
|
|
|
cb(watcher.value); |
|
|
|
|
} |
|
|
|
|
return function unwatchFn() { |
|
|
|
|
watcher.teardown(); |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
var watchers = []; |
|
|
|
|
var fns = exps.slice(); |
|
|
|
|
var complete = false, |
|
|
|
|
running = false; |
|
|
|
|
var callback = function callback(index) { |
|
|
|
|
if (complete === true) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
fns[index] = true; |
|
|
|
|
if (runBinaryFunction(fns)) { |
|
|
|
|
complete = true; |
|
|
|
|
cb(); |
|
|
|
|
} |
|
|
|
|
if (!running) { |
|
|
|
|
running = true; |
|
|
|
|
nextTick(function () { |
|
|
|
|
complete = false; |
|
|
|
|
running = false; |
|
|
|
|
fns = exps.slice(); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
_.each(exps, function (exp, i) { |
|
|
|
|
if (_.has(operators, exp)) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
//a.**或a.*形式
|
|
|
|
|
if (/^[1-9a-zA-Z.]+(\*\*$|\*$)/.test(exp)) { |
|
|
|
|
var isGlobal = /\*\*$/.test(exp); |
|
|
|
|
if (isGlobal) { |
|
|
|
|
//a.**的形式
|
|
|
|
|
exp = exp.replace(".**", ""); |
|
|
|
|
} else { |
|
|
|
|
//a.*的形式
|
|
|
|
|
exp = exp.replace(".*", ""); |
|
|
|
|
} |
|
|
|
|
var getter = parsePath(exp); |
|
|
|
|
var v = getter.call(model, model); |
|
|
|
|
var dep = new Dep(); |
|
|
|
|
if (isGlobal) { |
|
|
|
|
(v.__ob__._scopeDeps || (v.__ob__._scopeDeps = [])).push(dep); |
|
|
|
|
} else { |
|
|
|
|
(v.__ob__._deps || (v.__ob__._deps = [])).push(dep); |
|
|
|
|
} |
|
|
|
|
var w = new Watcher(model, function () { |
|
|
|
|
dep.depend(); |
|
|
|
|
return NaN; |
|
|
|
|
}, function () { |
|
|
|
|
callback(i); |
|
|
|
|
}); |
|
|
|
|
watchers.push(function unwatchFn() { |
|
|
|
|
w.teardown(); |
|
|
|
|
v.__ob__._scopeDeps && remove(v.__ob__._scopeDeps, dep); |
|
|
|
|
v.__ob__._deps && remove(v.__ob__._deps, dep); |
|
|
|
|
}); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (/\*\*$|\*$/.test(exp)) { |
|
|
|
|
throw new Error('not support'); |
|
|
|
|
} |
|
|
|
|
//其他含有*的情况,如*.a,*.*.a,a.*.a.*
|
|
|
|
|
if (/\*/.test(exp)) { |
|
|
|
|
//补全路径
|
|
|
|
|
var parent = model.__ob__.parent, |
|
|
|
|
root = model.__ob__; |
|
|
|
|
while (parent) { |
|
|
|
|
exp = '*.' + exp; |
|
|
|
|
root = parent; |
|
|
|
|
parent = parent.parent; |
|
|
|
|
} |
|
|
|
|
var regStr = routeToRegExp(exp); |
|
|
|
|
var _dep = new Dep(); |
|
|
|
|
root._globalDeps || (root._globalDeps = {}); |
|
|
|
|
root._globalDeps[regStr] = _dep; |
|
|
|
|
|
|
|
|
|
var _w = new Watcher(model, function () { |
|
|
|
|
_dep.depend(); |
|
|
|
|
return NaN; |
|
|
|
|
}, function () { |
|
|
|
|
callback(i); |
|
|
|
|
}); |
|
|
|
|
watchers.push(function unwatchFn() { |
|
|
|
|
_w.teardown(); |
|
|
|
|
root._globalDeps && delete root._globalDeps[regStr]; |
|
|
|
|
}); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
var watcher = new Watcher(model, exp, function () { |
|
|
|
|
callback(i); |
|
|
|
|
}, options); |
|
|
|
|
watchers.push(function unwatchFn() { |
|
|
|
|
watcher.teardown(); |
|
|
|
|
}); |
|
|
|
|
}); |
|
|
|
|
return watchers; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function toJSON(model) { |
|
|
|
|
var result = void 0; |
|
|
|
|
if (_.isArray(model)) { |
|
|
|
|