Comparing version 0.2.3 to 0.3.0
{ | ||
"name": "vue-flow", | ||
"version": "0.2.3", | ||
"version": "0.3.0", | ||
"description": "To make the state of application managed and processed as data flow.", | ||
@@ -5,0 +5,0 @@ "main": "vue-flow.js", |
276
vue-flow.js
(function () { | ||
/** | ||
Vue.flow.model() | ||
Vue.flow.addMiddleware() | ||
Vue.flow.mixin() | ||
Vue.flow.bind() | ||
Vue.flow.model() | ||
Vue.flow.addMiddleware() | ||
Vue.flow.mixin() | ||
Vue.flow.bind() | ||
* */ | ||
@@ -15,5 +15,7 @@ | ||
//数据隔离模式 | ||
var store = {}, | ||
models = {}, | ||
connections = [], | ||
connections = {}, | ||
protos = {}, | ||
@@ -50,4 +52,4 @@ proto, | ||
return function (options) { | ||
var result = opts[actionName].call(models[modelName], options); | ||
return function () { | ||
var result = apply(opts[actionName], arguments, models[modelName]); | ||
if (typeof result !== 'undefined') return dispatch.call(models[modelName], result); | ||
@@ -57,8 +59,7 @@ }; | ||
function dispatch() { | ||
return run_middlewares(this, Array.prototype.slice.call(arguments), { | ||
modelName:modelName, | ||
actionName:actionName, | ||
models:models, | ||
store:store, | ||
return run_middlewares(this, arguments, { | ||
modelName: modelName, | ||
actionName: actionName, | ||
models: models, | ||
store: store, | ||
}, dispatch); | ||
@@ -71,79 +72,9 @@ } | ||
function getState(otherModelName) { | ||
if (!otherModelName) return clone(store[this.name]); | ||
else return clone(store[otherModelName]); | ||
} | ||
}; | ||
function run_middlewares(model, args, meta, dispatch) { | ||
var index=0; | ||
return next(args); | ||
function next(args){ | ||
if(!args || args.constructor !== Array) throw 'the argument of next should be an array'; | ||
if(index<middlewares.length) | ||
return middlewares[index++](dispatch, next, end, meta).apply(model, args); | ||
else return end(args[0]); | ||
} | ||
function end(result){ | ||
if(!result) return; | ||
if(result.constructor !== Object) throw 'the argument of end should be a plain object'; | ||
index = middlewares.length; | ||
result = run_beforeStore_hooks(result, store[meta.modelName]); | ||
return storeState(result, meta.modelName, meta.actionName) | ||
} | ||
} | ||
//数据进出 store 通过 clone 隔离 | ||
function storeState(obj, modelName, actionName) { | ||
var pathValue_, | ||
state = store[modelName], | ||
pipes = connections[modelName], | ||
changedFields = Object.keys(obj), | ||
meta, | ||
changedState=clone(obj); | ||
Object.assign(state, changedState); | ||
for (var i = 0, l = pipes.length; i < l; i++) if (pipes[i]) { | ||
// 第2层根据changedFields判断是否有更新,过滤一把 | ||
if (pipes[i].statePath[1] && changedFields.indexOf(pipes[i].statePath[1]) === -1) continue; | ||
// 数据流入前hook | ||
pathValue_ = pathValue(pipes[i].statePath); | ||
meta = { | ||
name: pipes[i].dataName, | ||
value: pathValue_, | ||
action: modelName + '.' + actionName | ||
}; | ||
run_beforeFlowIn_hooks(pipes[i].comp, meta); | ||
if (pipes[i].comp.$options.beforeFlowIn) | ||
pipes[i].comp.$options.beforeFlowIn.call(pipes[i].comp, meta); | ||
pipes[i].comp.$set(pipes[i].dataName, pathValue_); | ||
} | ||
return changedState; | ||
} | ||
function run_beforeStore_hooks(newState, state) { | ||
var result; | ||
for (var i = 0, l = hook_beforeStore.length; i < l; i++) { | ||
result = hook_beforeStore[i](newState, state); | ||
if (typeof result === 'object') newState = result; | ||
} | ||
return newState; | ||
} | ||
function run_beforeFlowIn_hooks(comp, meta) { | ||
for (var i = 0, l = hook_beforeStore.length; i < l; i++) { | ||
hook_beforeFlowIn[i].call(comp, meta); | ||
} | ||
} | ||
Vue.flow.dispatch = function (modelName, options) { | ||
if (modelName && modelName.constructor === String) | ||
storeState(options, modelName, 'Vue.flow'); | ||
else throw 'the first argument should be a model name the second shuould be a plain object'; | ||
}; | ||
@@ -164,5 +95,5 @@ | ||
Vue.flow.addMiddleware = function (middleware) { | ||
if(typeof middleware === 'object' && middleware.constructor === Array) | ||
middlewares = middleware.concat(middleware); | ||
else if(typeof middleware === 'function') middlewares.push(middleware); | ||
if (typeof middleware === 'object' && middleware.constructor === Array) | ||
middlewares = middlewares.concat(middleware); | ||
else if (typeof middleware === 'function') middlewares.push(middleware); | ||
}; | ||
@@ -177,5 +108,5 @@ | ||
init: function () { | ||
if (this.$options.pipes) { | ||
for (var x in this.$options.pipes) if (this.$options.pipes.hasOwnProperty(x)) { | ||
var statePath = this.$options.pipes[x].split('.'); | ||
if (this.$options.flow) { | ||
for (var x in this.$options.flow) if (this.$options.flow.hasOwnProperty(x)) { | ||
var statePath = this.$options.flow[x].split('.'); | ||
connections[statePath[0]] = connections[statePath[0]] || []; | ||
@@ -193,11 +124,13 @@ connections[statePath[0]].push({ | ||
if(this.$options.action){ | ||
if (this.$options.actions) { | ||
var action; | ||
for (var x in this.$options.action) if (this.$options.action.hasOwnProperty(x)) { | ||
action = this.$options.action[x].split('.'); | ||
for (var x in this.$options.actions) if (this.$options.actions.hasOwnProperty(x)) { | ||
action = this.$options.actions[x].split('.'); | ||
if (!models[action[0]]) throw 'the model ' + action[0] + ' is not exist'; | ||
if (!models[action[0]][action[1]]) throw 'the action ' + action[1] + ' of model ' + action[0] + ' is not exist'; | ||
this[x]=(function(modelName,actionName){ | ||
return function(){ | ||
models[modelName][actionName].call(models[modelName], Array.prototype.slice.call(arguments)); | ||
this[x] = (function (modelName, actionName) { | ||
return function () { | ||
if (arguments[0] && arguments[0].cancelBubble !== undefined && arguments[0].srcElement) | ||
models[modelName][actionName].call(models[modelName]); | ||
else apply(models[modelName][actionName], arguments, models[modelName]); | ||
}; | ||
@@ -207,9 +140,8 @@ })(action[0], action[1]); | ||
} | ||
}, | ||
beforeDestroy: function () { | ||
if (this.$options.pipes) { | ||
if (this.$options.flow) { | ||
var statePath, tmp; | ||
for (var x in this.$options.pipes) if (this.$options.pipes.hasOwnProperty(x)) { | ||
statePath = this.$options.pipes[x].split('.'); | ||
for (var x in this.$options.flow) if (this.$options.flow.hasOwnProperty(x)) { | ||
statePath = this.$options.flow[x].split('.'); | ||
tmp = []; | ||
@@ -229,3 +161,3 @@ for (var i = 0, l = connections[statePath[0]].length; i < l; i++) { | ||
if (!models[name[0]][name[1]]) throw 'the action ' + name[1] + ' of model ' + name[0] + ' is not exist'; | ||
models[name[0]][name[1]](opts); | ||
apply(models[name[0]][name[1]], Array.prototype.slice.call(arguments, 1), models[name[0]]); | ||
} | ||
@@ -236,18 +168,2 @@ } | ||
//extentions | ||
Vue.flow.addMiddleware(function(dispatch, next, end, meta){ | ||
return function(name, options){ | ||
if(typeof name !== 'string') { | ||
return next(Array.prototype.slice.call(arguments)); | ||
} | ||
if (name.indexOf('.') === -1) name = [meta.modelName, name]; | ||
else name = name.split('.'); | ||
if (!meta.models[name[0]]) throw 'the model ' + name[0] + ' is not exist'; | ||
if (!meta.models[name[0]][name[1]]) throw 'the action ' + name[1] + ' of model ' + name[0] + ' is not exist'; | ||
return meta.models[name[0]][name[1]](options); | ||
}; | ||
}); | ||
Vue.flow.mixin({ | ||
@@ -289,17 +205,104 @@ | ||
function getState(otherModelName) { | ||
if (!otherModelName) return clone(store[this.name]); | ||
else return clone(store[otherModelName]); | ||
} | ||
function run_middlewares(model, args, context, dispatch) { | ||
var index = 0; | ||
return next(args); | ||
function next(args) { | ||
if (typeof args !== 'object' || isNaN(args.length)) throw 'please make sure the param of next is type of array or argument'; | ||
if (index < middlewares.length) | ||
return apply(middlewares[index++](dispatch, next, end, context), args, model); | ||
else return end(args[0]); | ||
} | ||
function end(result) { | ||
if (!result) return; | ||
if (result.constructor !== Object) { | ||
console.log(arguments); | ||
throw 'the argument of end should be a plain data object'; | ||
} | ||
index = middlewares.length; | ||
result = run_beforeStore_hooks(result, store[context.modelName]); | ||
return storeState(result, context.modelName, context.actionName) | ||
} | ||
} | ||
//数据进出 store 通过 clone 隔离 | ||
function storeState(obj, modelName, actionName) { | ||
var pathValue_, | ||
state = store[modelName], | ||
pipes = connections[modelName], | ||
changedFields = Object.keys(obj), | ||
meta, | ||
changedState = clone(obj), | ||
values = {}; | ||
Object.assign(state, changedState); | ||
if (pipes && pipes.length) for (var i = 0, l = pipes.length; i < l; i++) if (pipes[i]) { | ||
// 只更新 changedFields 字段 | ||
if (pipes[i].statePath[1] && changedFields.indexOf(pipes[i].statePath[1]) === -1) continue; | ||
//减少克隆次数,分发出去的数据用同一个副本,减少调用 pathValue | ||
pathValue_ = values[pipes[i].statePath] || (values[pipes[i].statePath] = pathValue(pipes[i].statePath)); | ||
meta = { | ||
name: pipes[i].dataName, | ||
value: pathValue_, | ||
action: modelName + '.' + actionName | ||
}; | ||
// 数据流入前hook | ||
run_beforeFlowIn_hooks(pipes[i].comp, meta); | ||
if (pipes[i].comp.$options.beforeFlowIn) | ||
pipes[i].comp.$options.beforeFlowIn.call(pipes[i].comp, meta); | ||
pipes[i].comp.$set(pipes[i].dataName, pathValue_); | ||
} | ||
return changedState; | ||
} | ||
function run_beforeStore_hooks(newState, state) { | ||
var result; | ||
for (var i = 0, l = hook_beforeStore.length; i < l; i++) { | ||
result = hook_beforeStore[i](newState, state); | ||
if (typeof result === 'object') newState = result; | ||
} | ||
return newState; | ||
} | ||
function run_beforeFlowIn_hooks(comp, meta) { | ||
for (var i = 0, l = hook_beforeStore.length; i < l; i++) { | ||
hook_beforeFlowIn[i].call(comp, meta); | ||
} | ||
} | ||
//提升效率空间:支持两层 && 不克隆 | ||
//支持5层 | ||
function pathValue(statePath) { | ||
console.log(statePath); | ||
var state = store[statePath[0]]; | ||
if (!statePath[1]) return clone(state); | ||
else { | ||
state = state[statePath[1]]; | ||
state = isNaN(statePath[1]) ? state[statePath[1]] : (state[statePath[1]] || state[parseInt(statePath[1])]); | ||
if (!statePath[2] || typeof state !== 'object') return clone(state); | ||
else { | ||
state = state[statePath[2]]; | ||
state = isNaN(statePath[2]) ? state[statePath[2]] : (state[statePath[2]] || state[parseInt(statePath[2])]); | ||
if (!statePath[3] || typeof state !== 'object') return clone(state); | ||
else { | ||
state = state[statePath[3]]; | ||
state = isNaN(statePath[3]) ? state[statePath[3]] : (state[statePath[3]] || state[parseInt(statePath[3])]); | ||
if (!statePath[4] || typeof state !== 'object') return clone(state); | ||
else { | ||
return clone(state[statePath[4]]); | ||
return clone(isNaN(statePath[4]) ? state[statePath[4]] : (state[statePath[4]] || state[parseInt(statePath[4])])); | ||
} | ||
@@ -317,2 +320,23 @@ } | ||
function apply(func, args, context) { | ||
switch (args.length) { | ||
case 0: | ||
return context ? func.call(context) : func(); | ||
case 1: | ||
return context ? func.call(context, args[0]) : func(args[0]); | ||
case 2: | ||
return context ? func.call(context, args[0], args[1]) : func(args[0], args[1]); | ||
case 3: | ||
return context ? func.call(context, args[0], args[1], args[2]) : func(args[0], args[1], args[2]); | ||
case 4: | ||
return context ? func.call(context, args[0], args[1], args[2], args[3]) : func(args[0], args[1], args[2], args[3]); | ||
case 5: | ||
return context ? func.call(context, args[0], args[1], args[2], args[3], args[4]) : func(args[0], args[1], args[2], args[3], args[4]); | ||
default: | ||
return func.apply(context || this, args); | ||
} | ||
} | ||
} | ||
@@ -319,0 +343,0 @@ }; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
10578
279
0