Commit eedc3d22 authored by rockyl's avatar rockyl

mvvm实现

parent 43f8406e
......@@ -295,6 +295,7 @@ var tslib = {__extends: __extends,__assign: __assign,__rest: __rest,__decorate:
}
return EE;
}());
//# sourceMappingURL=EventDispatcher.js.map
var ObservablePoint = (function (_super) {
tslib_1.__extends(ObservablePoint, _super);
......@@ -1815,6 +1816,18 @@ var tslib = {__extends: __extends,__assign: __assign,__rest: __rest,__decorate:
}
}
}
function safeEval(code, throwException) {
if (throwException === void 0) { throwException = false; }
var func = new Function(code);
try {
return func();
}
catch (e) {
if (throwException) {
throw e;
}
}
}
function injectProp(target, data, callback, ignoreMethod, ignoreNull) {
if (ignoreMethod === void 0) { ignoreMethod = true; }
if (ignoreNull === void 0) { ignoreNull = true; }
......@@ -1990,9 +2003,13 @@ var tslib = {__extends: __extends,__assign: __assign,__rest: __rest,__decorate:
var scriptName = ScriptConfig.script, props = ScriptConfig.props, disabled = ScriptConfig.disabled;
var script = node.scripts.add(scriptName, props, disabled);
}
var cmdPrefix = 'z-';
var cmdOldPrefix = '//z-';
function injectProperties(target, source) {
for (var key in source) {
propertyParse(key, target, source);
if (!source.hasOwnProperty(cmdPrefix + key)) {
propertyParse(key, target, source);
}
}
return target;
}
......@@ -3093,11 +3110,6 @@ var tslib = {__extends: __extends,__assign: __assign,__rest: __rest,__decorate:
}
//# sourceMappingURL=after-constructor.js.map
function isUI(obj) {
return obj.isUI;
}
//# sourceMappingURL=IUIComponent.js.map
var Container = (function (_super) {
tslib_1.__extends(Container, _super);
function Container() {
......@@ -3356,10 +3368,6 @@ var tslib = {__extends: __extends,__assign: __assign,__rest: __rest,__decorate:
child.updateTransform();
}
}
if (this._transform === this.transform && isUI(this) && this._lastLocalID !== this.transform.localID) {
this._lastLocalID = this.transform.localID;
this.stage.layoutInvalid = true;
}
};
Container.prototype.calculateBounds = function () {
if (this._lastBoundsID == this._boundsID)
......@@ -3523,8 +3531,6 @@ var tslib = {__extends: __extends,__assign: __assign,__rest: __rest,__decorate:
set: function (value) {
if (this._width !== value) {
this._width = value;
if (this.stage)
this.stage.layoutInvalid = true;
this.dispatchEvent(Event.RESIZE);
}
},
......@@ -3538,8 +3544,6 @@ var tslib = {__extends: __extends,__assign: __assign,__rest: __rest,__decorate:
set: function (value) {
if (this._height !== value) {
this._height = value;
if (this.stage)
this.stage.layoutInvalid = true;
this.dispatchEvent(Event.RESIZE);
}
},
......@@ -3550,8 +3554,10 @@ var tslib = {__extends: __extends,__assign: __assign,__rest: __rest,__decorate:
if (withEvents === void 0) { withEvents = false; }
if (withScripts === void 0) { withScripts = false; }
var target = this.constructor.apply(Object.create(this.constructor.prototype));
var _a = this['__originConfig'], name = _a.name, properties = _a.properties, events = _a.events, scripts = _a.scripts;
var originConfig = this['__originConfig'];
var name = originConfig.name, properties = originConfig.properties, events = originConfig.events, scripts = originConfig.scripts;
target.name = name;
target['__originConfig'] = originConfig;
injectProperties(target, properties);
if (withScripts) {
if (scripts && scripts.length > 0) {
......@@ -3566,13 +3572,29 @@ var tslib = {__extends: __extends,__assign: __assign,__rest: __rest,__decorate:
target.eventsProxy.start(events);
}
}
for (var _b = 0, _c = this.children; _b < _c.length; _b++) {
var child = _c[_b];
for (var _a = 0, _b = this.children; _a < _b.length; _a++) {
var child = _b[_a];
var childCopy = child.clone(withEvents, withScripts);
target.addChild(childCopy);
}
return target;
};
Object.defineProperty(Container.prototype, "$store", {
get: function () {
var p = this;
while (p.parent) {
p = p.parent;
if (p['$isViewRoot']) {
break;
}
}
if (p) {
return p['$_store'];
}
},
enumerable: true,
configurable: true
});
Container._getElementsByName = function (rex, root, isOnlyOne, isRecursive, resultList) {
var len = root.children.length;
if (len > 0) {
......@@ -3625,32 +3647,39 @@ var tslib = {__extends: __extends,__assign: __assign,__rest: __rest,__decorate:
}
});
s.addEventListener(Event.ADDED_TO_STAGE, function (e) {
if (!container) {
container = document.createElement('div');
container.style.position = "absolute";
container.style.left = "0";
container.style.top = "0";
container.style.fontSize = '30px';
container.style.lineHeight = 'normal';
s.stage.rootDiv.appendChild(container);
}
if (s._htmlElement) {
var style = s._htmlElement.style;
if (!s._isAdded) {
s._isAdded = true;
container.appendChild(s._htmlElement);
s.stage["_floatDisplayList"].push(s);
}
else {
if (s._htmlElement && s.visible) {
style.display = "block";
}
}
}
});
this.addHtmlElement();
}, s);
_this._transformID = -1;
return _this;
}
FloatDisplay.prototype.addHtmlElement = function () {
var s = this;
if (!s.stage) {
return;
}
if (!container) {
container = document.createElement('div');
container.style.position = "absolute";
container.style.left = "0";
container.style.top = "0";
container.style.fontSize = '30px';
container.style.lineHeight = 'normal';
s.stage.rootDiv.appendChild(container);
}
if (s._htmlElement) {
var style = s._htmlElement.style;
if (!s._isAdded) {
s._isAdded = true;
container.appendChild(s._htmlElement);
s.stage["_floatDisplayList"].push(s);
}
else {
if (s._htmlElement && s.visible) {
style.display = "block";
}
}
}
};
Object.defineProperty(FloatDisplay.prototype, "htmlElement", {
get: function () {
return this._htmlElement;
......@@ -3697,6 +3726,7 @@ var tslib = {__extends: __extends,__assign: __assign,__rest: __rest,__decorate:
s._localBoundsSelf.width = w;
s._localBoundsSelf.height = h;
s._htmlElement = she;
this.addHtmlElement();
};
FloatDisplay.prototype.getStyle = function (elem, cssName) {
if (elem.style[cssName]) {
......@@ -4580,7 +4610,6 @@ var tslib = {__extends: __extends,__assign: __assign,__rest: __rest,__decorate:
displayObject.parent = this._tempDisplayObjectParent;
displayObject.updateTransform();
displayObject.parent = cacheParent;
displayObject.stage && displayObject.stage.afterUpdateTransform();
context.save();
context.setTransform(1, 0, 0, 1, 0, 0);
context.globalAlpha = 1;
......@@ -7678,7 +7707,6 @@ var tslib = {__extends: __extends,__assign: __assign,__rest: __rest,__decorate:
displayObject.parent = this._tempDisplayObjectParent;
displayObject.updateTransform();
displayObject.parent = cacheParent;
displayObject.stage && displayObject.stage.afterUpdateTransform();
this.bindRenderTexture(renderTexture, transform);
this.batchManager.currentRenderer.start();
this._activeRenderTarget.clear();
......@@ -7873,7 +7901,6 @@ var tslib = {__extends: __extends,__assign: __assign,__rest: __rest,__decorate:
_this.rootDiv = HTMLElement;
_this.renderObj = null;
_this.renderType = exports.RENDERER_TYPE.UNKNOWN;
_this.layoutInvalid = false;
_this.viewRect = new Rectangle();
_this.autoSteering = false;
_this.autoResize = false;
......@@ -7960,7 +7987,7 @@ var tslib = {__extends: __extends,__assign: __assign,__rest: __rest,__decorate:
Stage.addUpdateObj(s);
s.dispatchEvent(Event.ON_INIT_STAGE);
}, 100);
var rc = canvas;
var rc = s.rootDiv;
var mouseEvent = s.onMouseEvent.bind(s);
if (osType != "pc") {
rc.addEventListener("touchstart", mouseEvent, false);
......@@ -8117,8 +8144,10 @@ var tslib = {__extends: __extends,__assign: __assign,__rest: __rest,__decorate:
else {
cp = new Point();
}
var rootDiv = s.rootDiv;
var doc = document.documentElement;
var box = points[o].target.getBoundingClientRect();
var box = rootDiv.getBoundingClientRect();
console.log(box.y);
var left = box.left + window.pageXOffset - doc.clientLeft;
var top = box.top + window.pageYOffset - doc.clientTop;
cp.x = (points[o].pageX - left) * devicePixelRatio;
......@@ -8407,8 +8436,6 @@ var tslib = {__extends: __extends,__assign: __assign,__rest: __rest,__decorate:
}
}
};
Stage.prototype.afterUpdateTransform = function () {
};
Stage.prototype.destroy = function () {
var s = this;
Stage.removeUpdateObj(s);
......@@ -8427,7 +8454,6 @@ var tslib = {__extends: __extends,__assign: __assign,__rest: __rest,__decorate:
Stage.allUpdateObjList = [];
return Stage;
}(Container));
//# sourceMappingURL=Stage.js.map
var GraphicsData = (function (_super) {
tslib_1.__extends(GraphicsData, _super);
......@@ -19436,6 +19462,11 @@ var tslib = {__extends: __extends,__assign: __assign,__rest: __rest,__decorate:
}(FloatDisplay));
//# sourceMappingURL=HtmlView.js.map
function isUI(obj) {
return obj.isUI;
}
//# sourceMappingURL=IUIComponent.js.map
var nodeTypeMapping = {
node: Node$1,
rect: Rect,
......@@ -19583,6 +19614,665 @@ var tslib = {__extends: __extends,__assign: __assign,__rest: __rest,__decorate:
}(Node$1));
//# sourceMappingURL=Toast.js.map
function createEvalFunc(exp) {
var func;
try {
func = Function("scope", "with(scope){return " + exp + "}");
}
catch (err) {
var sepStr = (exp.indexOf('"') < 0 ? '"' : "'");
var reg = /([^\\]?)`/g;
exp = exp.replace(reg, "$1" + sepStr);
reg = /\$\{(.*?)\}/g;
exp = exp.replace(reg, sepStr + "+($1)+" + sepStr);
try {
func = Function("scope", "with(scope){return " + exp + "}");
}
catch (e) {
console.error('非法的表达式:', exp);
}
}
return func;
}
function evalExp(exp, scope) {
return createEvalFunc(exp)(scope);
}
function createRunFunc(exp) {
return createEvalFunc("(function(){" + exp + "})()");
}
function runExp(exp, scope) {
createRunFunc(exp)(scope);
}
//# sourceMappingURL=Utils.js.map
var Watcher = (function () {
function Watcher(entity, target, exp, scope, callback) {
this._disposed = false;
this._entity = entity;
this._uid = Watcher._uid++;
this._target = target;
this._exp = exp;
this._scope = scope;
this._expFunc = createEvalFunc(exp);
this._callback = callback;
this.update();
}
Object.defineProperty(Watcher.prototype, "uid", {
get: function () {
return this._uid;
},
enumerable: true,
configurable: true
});
Watcher.prototype.getValue = function () {
if (this._disposed)
return null;
var value = null;
Watcher.updating = this;
Object.defineProperty(this._scope, "$root", {
configurable: true,
enumerable: false,
value: this._entity.compiler.root,
writable: false
});
Object.defineProperty(this._scope, "$target", {
configurable: true,
enumerable: false,
value: this._target,
writable: false
});
try {
value = this._expFunc.call(this._scope, this._scope);
}
catch (err) {
console.warn("表达式求值错误\nerr: " + err.toString() + "\nexp:" + this._exp + ",scope:" + JSON.stringify(this._scope));
}
delete this._scope["$root"];
delete this._scope["$target"];
Watcher.updating = null;
return value;
};
Watcher.prototype.update = function (extra) {
if (this._disposed)
return;
var value = this.getValue();
if (!Watcher.isEqual(value, this._value)) {
this._callback && this._callback(value, this._value, extra);
this._value = Watcher.deepCopy(value);
}
};
Watcher.prototype.dispose = function () {
if (this._disposed)
return;
this._value = null;
this._target = null;
this._exp = null;
this._scope = null;
this._expFunc = null;
this._callback = null;
this._disposed = true;
};
Watcher.isEqual = function (a, b) {
return (a == b || (Watcher.isObject(a) && Watcher.isObject(b)
? JSON.stringify(a) == JSON.stringify(b)
: false));
};
Watcher.isObject = function (obj) {
return (obj && typeof obj == "object");
};
Watcher.deepCopy = function (from) {
if (Watcher.isObject(from)) {
return JSON.parse(JSON.stringify(from));
}
else {
return from;
}
};
Watcher.updating = null;
Watcher._uid = 0;
return Watcher;
}());
//# sourceMappingURL=Watcher.js.map
var Dep = (function () {
function Dep() {
this._map = {};
}
Dep.prototype.watch = function (watcher) {
if (!this._map[watcher.uid]) {
this._map[watcher.uid] = watcher;
}
};
Dep.prototype.notify = function (extra) {
for (var uid in this._map) {
var watcher = this._map[uid];
watcher.update(extra);
}
};
return Dep;
}());
//# sourceMappingURL=Dep.js.map
var Mutator = (function () {
function Mutator() {
}
Mutator.mutate = function (data) {
if (!data || typeof data != "object")
return;
if (!data.__ares_mutated__) {
for (var key in data) {
Mutator.mutateProp(data, key, data[key]);
}
Object.defineProperty(data, "__ares_mutated__", {
value: true,
writable: false,
enumerable: false,
configurable: false
});
}
return data;
};
Mutator.mutateProp = function (data, key, value) {
var dep = new Dep();
Object.defineProperty(data, key, {
enumerable: true,
configurable: false,
get: function () {
var watcher = Watcher.updating;
if (watcher)
dep.watch(watcher);
return value;
},
set: function (v) {
if (v == value)
return;
value = v;
if (Array.isArray(v))
Mutator.mutateArray(v, dep);
else
Mutator.mutate(v);
dep.notify();
}
});
if (Array.isArray(value)) {
Mutator.mutateArray(value, dep);
}
else {
Mutator.mutate(value);
}
};
Mutator.mutateArray = function (arr, dep) {
arr["__proto__"] = Mutator.defineReactiveArray(dep);
for (var i = 0, len = arr.length; i < len; i++) {
Mutator.mutate(arr[i]);
}
};
Mutator.defineReactiveArray = function (dep) {
var proto = Array.prototype;
var result = Object.create(proto);
Mutator._arrMethods.forEach(function (method) {
var oriMethod = proto[method];
Object.defineProperty(result, method, {
value: function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
var result = oriMethod.apply(this, args);
var inserted;
switch (method) {
case "push":
case "unshift":
inserted = args;
break;
case "splice":
inserted = args.slice(2);
break;
}
if (inserted && inserted.length) {
Mutator.mutateArray(inserted, dep);
}
dep.notify({ method: args });
return result;
}
});
});
Object.defineProperty(result, "$set", {
value: function (index, value) {
if (index >= this.length)
index = this.length;
return this.splice(index, 1, value)[0];
}
});
Object.defineProperty(result, "$remove", {
value: function (item) {
var index = this.indexOf(item);
if (index > -1)
return this.splice(index, 1);
return null;
}
});
return result;
};
Mutator._arrMethods = [
"push",
"pop",
"unshift",
"shift",
"splice",
"sort",
"reverse"
];
return Mutator;
}());
//# sourceMappingURL=Mutator.js.map
var commands = {
set: function (context) {
runExp(context.data.subCmd + "=" + context.data.exp, context.scope);
return context.target;
},
bind: function (context) {
context.entity.createWatcher(context.target, context.data.exp, context.scope, function (value) {
if (context.data.subCmd)
runExp(context.data.subCmd + "=" + context.data.exp, context.scope);
});
return context.target;
}
};
//# sourceMappingURL=Commands.js.map
var defaultCmdRegExp = /^(data\-)?z[\-_](\w+)([:\$](.+))?$/;
var Zri = (function () {
function Zri(data, compiler, options) {
this._data = Mutator.mutate(data);
this._compiler = compiler;
this._options = options;
this._compiler.init(this);
if (this._options && this._options.inited) {
this._options.inited.call(this._data, this);
}
}
Object.defineProperty(Zri.prototype, "data", {
get: function () {
return this._data;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Zri.prototype, "compiler", {
get: function () {
return this._compiler;
},
enumerable: true,
configurable: true
});
Zri.prototype.createWatcher = function (target, exp, scope, callback) {
return new Watcher(this, target, exp, scope, callback);
};
Zri.prototype.parseCommand = function (key, value, cmdRegExp) {
var result = (cmdRegExp || defaultCmdRegExp).exec(key);
if (!result)
return null;
var key = result[0];
var cmdName = result[2];
var exp = value;
var subCmd = result[4] || "";
return {
cmdName: cmdName,
subCmd: subCmd,
propName: key,
exp: exp
};
};
Zri.prototype.testCommand = function (data) {
if (!data)
return false;
var cmd = commands[data.cmdName];
return (cmd != null);
};
Zri.prototype.execCommand = function (data, target, scope) {
if (!data || !scope)
return false;
var cmd = commands[data.cmdName];
if (!cmd)
return false;
cmd({
target: target,
scope: scope,
entity: this,
data: data
});
return true;
};
return Zri;
}());
//# sourceMappingURL=Zri.js.map
var commands$1 = {
prop: function (context) {
var cmdData = context.cmdData;
var target = context.target;
context.entity.createWatcher(target, cmdData.exp, context.scope, function (value) {
if (cmdData.subCmd != "") {
target[cmdData.subCmd] = value;
}
else {
for (var name in value) {
target[name] = value[name];
}
}
});
return target;
},
on: function (context) {
var cmdData = context.cmdData;
if (cmdData.subCmd != "") {
var handler_1 = context.scope[cmdData.exp] || window[context.cmdData.exp];
if (typeof handler_1 == "function") {
context.target.addEventListener(cmdData.subCmd, function () {
handler_1.apply(this, arguments);
}, context.scope);
}
else {
context.target.addEventListener(cmdData.subCmd, function (evt) {
var scope = Object.create(context.scope);
scope.$event = evt;
scope.$target = context.target;
runExp(cmdData.exp, scope);
});
}
}
return context.target;
},
if: function (context) {
var cmdData = context.cmdData;
var compiled = false;
var refNode = new Container();
refNode.mouseChildren = refNode.mouseEnabled = false;
var parent = context.target.parent;
var index = parent.getChildIndex(context.target);
parent.removeChildAt(index);
parent.addChildAt(refNode, index);
var watcher = context.entity.createWatcher(context.target, cmdData.exp, context.scope, function (value) {
if (!refNode.parent && !context.target.parent) {
watcher.dispose();
return;
}
if (value == true) {
if (!context.target.parent) {
var parent_1 = refNode.parent;
var index_1 = parent_1.getChildIndex(refNode);
parent_1.removeChild(refNode);
parent_1.addChildAt(context.target, index_1);
}
if (!compiled) {
context.compiler.compile(context.target, context.scope);
compiled = true;
}
}
else {
if (context.target.parent) {
var parent_2 = context.target.parent;
var index_2 = parent_2.getChildIndex(context.target);
parent_2.removeChild(context.target);
parent_2.addChildAt(refNode, index_2);
}
}
});
return context.target;
},
for: function (context) {
var cmdData = context.cmdData;
var options = evalExp(cmdData.subCmd, context.scope) || {};
var page = (options.page || Number.MAX_VALUE);
var reg = /^\s*(\S+)\s+in\s+([\s\S]+?)\s*$/;
var res = reg.exec(cmdData.exp);
if (!res) {
console.error("for命令表达式错误:" + cmdData.exp);
return;
}
var itemName = res[1];
var arrName = res[2];
var index = context.target.parent.getChildIndex(context.target);
var parent = new Container();
context.target.parent.addChildAt(parent, index);
context.target.parent.removeChild(context.target);
var forScope = Object.create(context.scope);
Object.defineProperty(forScope, "$forTarget", {
configurable: true,
enumerable: false,
value: context.target,
writable: false
});
context.compiler.compile(parent, forScope);
var isArray;
var curList;
var curIndex;
var lastNode;
var watcher = context.entity.createWatcher(context.target, arrName, forScope, function (value) {
if (!parent.parent) {
watcher.dispose();
return;
}
for (var i = parent.children.length - 1; i >= 0; i--) {
parent.removeChildAt(i).destroy();
}
if (typeof value == "number") {
var temp = [];
for (var i = 0; i < value; i++) {
temp.push(i);
}
value = temp;
}
isArray = (value instanceof Array);
var list;
if (isArray) {
list = value;
}
else {
list = [];
for (var key in value) {
list.push({
key: key,
value: value[key]
});
}
}
curList = list;
curIndex = 0;
lastNode = null;
for (var li = curList.length; curIndex < li; curIndex++) {
var newNode = context.target.clone(true, true);
parent.addChild(newNode);
var newScope = Object.create(forScope);
Object.defineProperty(newScope, "$index", {
configurable: true,
enumerable: false,
value: curIndex,
writable: false
});
if (!isArray) {
Object.defineProperty(newScope, "$key", {
configurable: true,
enumerable: true,
value: curList[curIndex].key,
writable: false
});
}
Object.defineProperty(newScope, "$last", {
configurable: true,
enumerable: false,
value: lastNode,
writable: false
});
Object.defineProperty(newScope, "$length", {
configurable: true,
enumerable: false,
value: curList.length,
writable: false
});
Object.defineProperty(newScope, itemName, {
configurable: true,
enumerable: true,
value: (isArray ? curList[curIndex] : curList[curIndex].value),
writable: false
});
context.compiler.compile(newNode, newScope);
lastNode = newNode;
}
});
return context.target;
}
};
//# sourceMappingURL=ZriCommands.js.map
var interruptCmds = ['for', 'if'];
var ZriCompiler = (function () {
function ZriCompiler(root) {
this._root = root;
}
Object.defineProperty(ZriCompiler.prototype, "root", {
get: function () {
return this._root;
},
enumerable: true,
configurable: true
});
ZriCompiler.prototype.init = function (entity) {
this._entity = entity;
this.compile(this._root, entity.data);
};
ZriCompiler.prototype.compile = function (target, scope) {
var cmdDatas = [];
var needInterrupt = false;
for (var key in target) {
if (key.indexOf(cmdPrefix) < 0) {
continue;
}
var cmdData = this._entity.parseCommand(key, target[key]);
if (cmdData) {
cmdDatas.push(cmdData);
if (interruptCmds.indexOf(cmdData.cmdName) >= 0) {
needInterrupt = true;
cmdDatas.splice(0, cmdDatas.length - 1);
break;
}
}
}
for (var _i = 0, cmdDatas_1 = cmdDatas; _i < cmdDatas_1.length; _i++) {
var cmdData = cmdDatas_1[_i];
delete target[cmdData.propName];
if (interruptCmds.indexOf(cmdData.cmdName) >= 0 && target['__originConfig']) {
delete target['__originConfig'].properties[cmdData.propName];
}
var cmd = commands$1[cmdData.cmdName];
if (!cmd) {
cmdData.subCmd = cmdData.cmdName || "";
cmdData.cmdName = "prop";
cmd = commands$1[cmdData.cmdName];
}
cmd({
scope: scope,
target: target,
entity: this._entity,
cmdData: cmdData,
compiler: this,
});
}
if (!needInterrupt && target.children && target.children.length > 0) {
for (var _a = 0, _b = target.children; _a < _b.length; _a++) {
var child = _b[_a];
this.compile(child, scope);
}
}
};
return ZriCompiler;
}());
//# sourceMappingURL=ZriCompiler.js.map
function bind(store, view, options) {
var compiler = new ZriCompiler(view);
return new Zri(store, compiler, options);
}
function createStore(exp, computed) {
var store = safeEval(exp) || {};
for (var _i = 0, computed_1 = computed; _i < computed_1.length; _i++) {
var item = computed_1[_i];
var getterCode = "return function(){\n\t\t\t" + item.script + "\n\t\t}";
if (name && !store.hasOwnProperty(name)) {
Object.defineProperty(store, item.name, {
get: safeEval(getterCode),
});
}
}
return store;
}
//# sourceMappingURL=index.js.map
var customMap = {};
function registerCustomModules(customs) {
if (!customs) {
return;
}
for (var _i = 0, customs_1 = customs; _i < customs_1.length; _i++) {
var custom = customs_1[_i];
if (custom.assets) {
customMap[custom.id].assets = custom.assets;
}
if (custom.props) {
customMap[custom.id].props = custom.props;
}
}
}
function registerCustomModule(id, def) {
customMap[id] = {
def: def,
};
}
function registerCustomCodeModule(config) {
var id = config.id, code = config.code;
registerCustomModule(id, importCJSCode(code, true));
}
function registerCustomModuleFromConfig(config) {
if (config) {
for (var _i = 0, config_1 = config; _i < config_1.length; _i++) {
var item = config_1[_i];
registerCustomCodeModule(item);
}
}
}
function addCustomModule(id, container, options) {
var creator = customMap[id].def;
if (creator) {
var instance = creator(options);
if (instance) {
container.addChild(instance);
return instance;
}
}
}
function resolveCustomAsset(id, uuid) {
var module = customMap[id];
if (module) {
var config = arrayFind(module.assets, function (item) { return item.uuid === uuid; });
if (config) {
if (config.url.indexOf(linkScheme) === 0) {
var linkUUID = config.url.replace(linkScheme, '');
var linkConfig = getAssetByUUID(linkUUID);
if (linkConfig) {
config = linkConfig;
}
}
}
return config;
}
}
function getProps(id) {
return customMap[id].props || {};
}
//# sourceMappingURL=custom-module.js.map
var GameStage = (function (_super) {
tslib_1.__extends(GameStage, _super);
function GameStage(stage) {
......@@ -19721,6 +20411,16 @@ var tslib = {__extends: __extends,__assign: __assign,__rest: __rest,__decorate:
var viewConfig = this.getViewConfigByName(name);
if (viewConfig) {
view = instantiate(viewConfig);
var store = {};
if (viewConfig.store) {
var _a = viewConfig.store, exp = _a.exp, computed = _a.computed;
store = createStore(exp, computed);
}
view['$isViewRoot'] = true;
view['$_store'] = store;
console.time('bind');
bind(store, view);
console.timeEnd('bind');
if (cache) {
this._viewCache[name] = view;
}
......@@ -19755,69 +20455,6 @@ var tslib = {__extends: __extends,__assign: __assign,__rest: __rest,__decorate:
}(Node$1));
//# sourceMappingURL=GameStage.js.map
var customMap = {};
function registerCustomModules(customs) {
if (!customs) {
return;
}
for (var _i = 0, customs_1 = customs; _i < customs_1.length; _i++) {
var custom = customs_1[_i];
if (custom.assets) {
customMap[custom.id].assets = custom.assets;
}
if (custom.props) {
customMap[custom.id].props = custom.props;
}
}
}
function registerCustomModule(id, def) {
customMap[id] = {
def: def,
};
}
function registerCustomCodeModule(config) {
var id = config.id, code = config.code;
registerCustomModule(id, importCJSCode(code, true));
}
function registerCustomModuleFromConfig(config) {
if (config) {
for (var _i = 0, config_1 = config; _i < config_1.length; _i++) {
var item = config_1[_i];
registerCustomCodeModule(item);
}
}
}
function addCustomModule(id, container, options) {
var creator = customMap[id].def;
if (creator) {
var instance = creator(options);
if (instance) {
container.addChild(instance);
return instance;
}
}
}
function resolveCustomAsset(id, uuid) {
var module = customMap[id];
if (module) {
var config = arrayFind(module.assets, function (item) { return item.uuid === uuid; });
if (config) {
if (config.url.indexOf(linkScheme) === 0) {
var linkUUID = config.url.replace(linkScheme, '');
var linkConfig = getAssetByUUID(linkUUID);
if (linkConfig) {
config = linkConfig;
}
}
}
return config;
}
}
function getProps(id) {
return customMap[id].props || {};
}
//# sourceMappingURL=custom-module.js.map
var template = "\n<div class=\"zeroing-loading-wrapper\">\n\t<div class=\"zeroing-loading-content\">\n\t</div>\n</div>\n";
var style = "\n.zeroing-loading-wrapper{\n\tposition: absolute;\n\ttop:0;\n\tleft: 0;\n\tright: 0;\n\tbottom: 0;\n\tdisplay: flex;\n\tdisplay: -webkit-flex;\n\tjustify-content: center;\n\t-webkit-justify-content: center;\n\talign-items: center;\n\t-webkit-align-items: center;\n}\n@keyframes part-body\n{\n\t0%,40% {transform: scale(1);}\n\t20% {transform: scale(1.5);}\n}\n.zeroing-loading-part {\n\ttransform-origin: 2px 12px;\n\tposition: absolute;\n}\n.zeroing-loading-part-body{\n\tbackground-color: dimgray;\n\twidth: 4px;\n\theight: 6px;\n\tborder-radius: 2px;\n\ttransform-origin: 2px 6px;\n\tanimation: part-body 1500ms linear infinite;\n}\n";
var inited = false;
......@@ -19973,95 +20610,94 @@ var tslib = {__extends: __extends,__assign: __assign,__rest: __rest,__decorate:
/**
* Created by rockyl on 2020-01-27.
*/
const genericRegexp = /(\w+)(<(\w+)>)?/;
var genericRegexp = /(\w+)(<(\w+)>)?/;
function compute(props, options) {
let result = props || {};
for (let key in options) {
let sourceValue = getValue(result, options, key);
let value = sourceValue;
if (options) {
let option = options[key];
if (option && option.type) {
let {type, generic} = parseType(option.type);
switch (type) {
case 'vector2':
value = parseVector2(sourceValue);
break;
case 'array':
let seps = sourceValue.split(',');
seps = seps.map(sep => {
let item;
if (generic) {
switch (generic) {
case 'number':
item = parseFloat(sep);
break;
case 'boolean':
item = sep === 'true';
break;
default:
item = sep;
break;
}
} else {
item = sep;
}
return item;
});
value = seps;
break;
}
}
}
result[key] = value;
}
return result;
var result = props || {};
var _loop_1 = function (key) {
var sourceValue = getValue(result, options, key);
var value = sourceValue;
if (options) {
var option = options[key];
if (option && option.type) {
var _a = parseType(option.type), type = _a.type, generic_1 = _a.generic;
switch (type) {
case 'vector2':
value = parseVector2(sourceValue);
break;
case 'array':
var seps = sourceValue.split(',');
seps = seps.map(function (sep) {
var item;
if (generic_1) {
switch (generic_1) {
case 'number':
item = parseFloat(sep);
break;
case 'boolean':
item = sep === 'true';
break;
default:
item = sep;
break;
}
}
else {
item = sep;
}
return item;
});
value = seps;
break;
}
}
}
result[key] = value;
};
for (var key in options) {
_loop_1(key);
}
return result;
}
function parseType(typeStr) {
let type = typeStr, generic;
let regResult = typeStr.match(genericRegexp);
if (regResult) {
type = regResult[1];
generic = regResult[3];
}
return {
type, generic,
}
var type = typeStr, generic;
var regResult = typeStr.match(genericRegexp);
if (regResult) {
type = regResult[1];
generic = regResult[3];
}
return {
type: type, generic: generic,
};
}
function parseVector2(sourceValue) {
let value = sourceValue;
if (!sourceValue) {
value = {x: undefined, y: undefined};
}
if (typeof sourceValue === 'string') {
let arr = sourceValue.split(',');
value = {
x: arr[0] === '' ? undefined : parseFloat(arr[0]),
y: arr[1] === '' ? undefined : parseFloat(arr[1]),
};
} else if (Array.isArray(sourceValue)) {
value = {
x: sourceValue[0] === '' ? undefined : parseFloat(sourceValue[0]),
y: sourceValue[1] === '' ? undefined : parseFloat(sourceValue[1]),
};
}
return value;
var value = sourceValue;
if (!sourceValue) {
value = { x: undefined, y: undefined };
}
if (typeof sourceValue === 'string') {
var arr = sourceValue.split(',');
value = {
x: arr[0] === '' ? undefined : parseFloat(arr[0]),
y: arr[1] === '' ? undefined : parseFloat(arr[1]),
};
}
else if (Array.isArray(sourceValue)) {
value = {
x: sourceValue[0] === '' ? undefined : parseFloat(sourceValue[0]),
y: sourceValue[1] === '' ? undefined : parseFloat(sourceValue[1]),
};
}
return value;
}
function getValue(props, options, key) {
let value;
if (props.hasOwnProperty(key)) {
value = props[key];
} else if (options && options[key].hasOwnProperty('default')) {
value = options[key].default;
}
return value;
var value;
if (props.hasOwnProperty(key)) {
value = props[key];
}
else if (options && options[key].hasOwnProperty('default')) {
value = options[key].default;
}
return value;
}
//# sourceMappingURL=index.es.js.map
......@@ -20135,6 +20771,8 @@ var tslib = {__extends: __extends,__assign: __assign,__rest: __rest,__decorate:
exports.arrayFind = arrayFind;
exports.backupCanvas = backupCanvas;
exports.clearTextureCache = clearTextureCache;
exports.cmdOldPrefix = cmdOldPrefix;
exports.cmdPrefix = cmdPrefix;
exports.computeProps = compute;
exports.copyProp = copyProp;
exports.cos = cos;
......@@ -20228,6 +20866,7 @@ var tslib = {__extends: __extends,__assign: __assign,__rest: __rest,__decorate:
exports.resolveCustomAsset = resolveCustomAsset;
exports.reverse = reverse;
exports.rgb2hex = rgb2hex;
exports.safeEval = safeEval;
exports.setGlobalContext = setGlobalContext;
exports.setProcessMetaLibs = setProcessMetaLibs;
exports.setScriptMap = setScriptMap;
......
This source diff could not be displayed because it is too large. You can view the blob instead.
{"id":"engine","url":"engine.85a610a71df748fd9a6ece34f456a06e8f3f1b63.js"}
\ No newline at end of file
{"id":"engine","url":"engine.210e93fc8ecfcb27da00c77582649b96949d28c3.js"}
\ No newline at end of file
{
"name": "aaaa",
"version": "1.0.0",
"name": "zeroing-engine",
"version": "0.1.0",
"description": "",
"main": "index.js",
"types": "index.d.ts",
......
function getPxToken(callback) {
if (window['ohjaiohdf']) {
var xhr = new XMLHttpRequest();
xhr.open('get', 'getToken', true);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
var response = JSON.parse(xhr.response);
if (response.success) {
window.eval(response.data);
callback(null, window['ohjaiohdf']());
} else {
callback('state invalid');
}
}
};
xhr.onerror = function (e) {
failedCallback();
};
xhr.onloadend = function () {
if (xhr.status === 404) {
failedCallback();
}
};
xhr.send();
} else {
callback('need login');
}
function failedCallback() {
callback('net error');
}
}
......@@ -423,11 +423,11 @@ export default class Container extends DisplayObject {
}
}
if(this._transform === this.transform && isUI(this) && this._lastLocalID !== this.transform.localID){
/*if(this._transform === this.transform && isUI(this) && this._lastLocalID !== this.transform.localID){
this._lastLocalID = this.transform.localID;
//console.log(this.name, this.instanceId , 'dirty!');
this.stage.layoutInvalid = true;
}
}*/
}
/**
......@@ -699,7 +699,7 @@ export default class Container extends DisplayObject {
if (this._width !== value) {
//子类有用,有_width,才需设置scaleX
this._width = value;
if(this.stage) this.stage.layoutInvalid = true;
//if (this.stage) this.stage.layoutInvalid = true;
this.dispatchEvent(Event.RESIZE);
}
}
......@@ -722,7 +722,7 @@ export default class Container extends DisplayObject {
// }
if (this._height !== value) {
this._height = value;
if(this.stage) this.stage.layoutInvalid = true;
//if (this.stage) this.stage.layoutInvalid = true;
this.dispatchEvent(Event.RESIZE);
}
}
......@@ -730,8 +730,10 @@ export default class Container extends DisplayObject {
clone(withEvents = false, withScripts = false) {
let target = this.constructor.apply(Object.create(this.constructor.prototype));
const {name, properties, events, scripts} = this['__originConfig'];
const originConfig = this['__originConfig'];
const {name, properties, events, scripts} = originConfig;
target.name = name;
target['__originConfig'] = originConfig;
injectProperties(target, properties);
if (withScripts) {
......@@ -755,6 +757,20 @@ export default class Container extends DisplayObject {
return target;
}
get $store() {
let p = this;
while (p.parent) {
p = p.parent;
if (p['$isViewRoot']) {
break;
}
}
if (p) {
return p['$_store'];
}
}
//全局遍历
/**
* @method _getElementsByName
......
......@@ -83,32 +83,42 @@ export class FloatDisplay extends DisplayObject {
}
});
s.addEventListener(Event.ADDED_TO_STAGE, function (e: Event) {
if(!container){
container = document.createElement('div');
container.style.position = "absolute";
container.style.left = "0";
container.style.top = "0";
container.style.fontSize = '30px';
container.style.lineHeight = 'normal';
s.stage.rootDiv.appendChild(container);//, s.stage.rootDiv.childNodes[0]
}
if (s._htmlElement) {
let style = s._htmlElement.style;
if (!s._isAdded) {
s._isAdded = true;
container.appendChild(s._htmlElement);
s.stage["_floatDisplayList"].push(s);
} else {
if (s._htmlElement && s.visible) {
style.display = "block";
}
}
}
});
this.addHtmlElement();
}, s);
this._transformID = -1;
}
addHtmlElement() {
let s = this;
if(!s.stage){
return;
}
if (!container) {
container = document.createElement('div');
container.style.position = "absolute";
container.style.left = "0";
container.style.top = "0";
container.style.fontSize = '30px';
container.style.lineHeight = 'normal';
s.stage.rootDiv.appendChild(container);//, s.stage.rootDiv.childNodes[0]
}
if (s._htmlElement) {
let style = s._htmlElement.style;
if (!s._isAdded) {
s._isAdded = true;
container.appendChild(s._htmlElement);
s.stage["_floatDisplayList"].push(s);
} else {
if (s._htmlElement && s.visible) {
style.display = "block";
}
}
}
}
get htmlElement() {
return this._htmlElement;
}
......@@ -126,7 +136,7 @@ export class FloatDisplay extends DisplayObject {
* @param {HtmlElement} htmlElement 需要封装起来的html元素的引用。你可以通过这个引用来调用或设置此元素自身的属性方法和事件,甚至是样式
*/
protected init(htmlElement: any): void {
if(!htmlElement){
if (!htmlElement) {
return;
}
let s = this;
......@@ -160,6 +170,8 @@ export class FloatDisplay extends DisplayObject {
s._localBoundsSelf.width = w;
s._localBoundsSelf.height = h;
s._htmlElement = she;
this.addHtmlElement();
}
/**
......
......@@ -115,11 +115,6 @@ export class Stage extends Container {
*/
private static _stageList: any = {};
/**
* 布局失效
*/
layoutInvalid: boolean = false;
/**
* 是否暂停
* @property pause
......@@ -438,7 +433,7 @@ export class Stage extends Container {
s.dispatchEvent(Event.ON_INIT_STAGE);
// }
}, 100);
let rc = canvas;//s.rootDiv;
let rc = s.rootDiv; //canvas
let mouseEvent = s.onMouseEvent.bind(s);
//鼠标事件
if (osType != "pc") {
......@@ -648,8 +643,10 @@ export class Stage extends Container {
cp = new Point();
}
let rootDiv = s.rootDiv;
let doc = document.documentElement;
let box = points[o].target.getBoundingClientRect();
let box = rootDiv.getBoundingClientRect();//points[o].target
console.log(box.y);
let left = box.left + window.pageXOffset - doc.clientLeft;
let top = box.top + window.pageYOffset - doc.clientTop;
cp.x = (points[o].pageX - left) * devicePixelRatio;
......@@ -1016,14 +1013,6 @@ export class Stage extends Container {
}
}
afterUpdateTransform() {
/*this.calculateBounds();
if (this.layoutInvalid) {
this.dispatchEvent(Event.LAYOUT_INVALID);
this.layoutInvalid = false;
}*/
}
public destroy(): void {
let s = this;
Stage.removeUpdateObj(s);
......
......@@ -134,8 +134,6 @@ export default class CanvasRenderer extends SystemRenderer {
displayObject.updateTransform();
displayObject.parent = cacheParent;
displayObject.stage && displayObject.stage.afterUpdateTransform();
//初始化上下文状态
context.save();
context.setTransform(1, 0, 0, 1, 0, 0);
......
......@@ -179,8 +179,6 @@ export class WebglRenderer extends SystemRenderer {
displayObject.updateTransform();
displayObject.parent = cacheParent;
displayObject.stage && displayObject.stage.afterUpdateTransform();
//绑定渲染对象,没有则是默认root
this.bindRenderTexture(renderTexture, transform);
......
......@@ -7,14 +7,16 @@ import {StackContainer} from "./StackContainer";
import {loadAssets} from "./assets-manager";
import {instantiate} from "./view-interpreter";
import {dataCenter, DataCenter} from "./data-center";
import {setProcessMetaLibs} from "../behavior-runtime";
import {Tween} from "../../2d/tween";
import {Rect} from "./nodes";
import {setProcessMetaLibs} from "../behavior-runtime/index";
import {Tween} from "../../2d/tween/index";
import {Rect} from "./nodes/index";
import {injectEnv} from "./enviroment";
import {Toast} from "./Toast";
import {arrayFind} from "../utils";
import {registerCustomModules, registerScripts} from "..";
import {arrayFind} from "../utils/index";
import {Node} from "./nodes/Node";
import {bind, createStore} from "./mvvm/index";
import {safeEval} from "../utils/utils";
import {registerCustomModules} from "./custom-module";
/**
* 游戏舞台
......@@ -62,6 +64,7 @@ export class GameStage extends Node {
this._popupContainer.name = 'popup-container';
this._popupContainer.addEventListener('change', this.onPopupContainerChange, this);
}
/**
......@@ -180,6 +183,23 @@ export class GameStage extends Node {
let viewConfig = this.getViewConfigByName(name);
if (viewConfig) {
view = instantiate(viewConfig);
let store = {};
if(viewConfig.store){
const {exp, computed} = viewConfig.store;
store = createStore(exp, computed);
}
view['$isViewRoot'] = true;
view['$_store'] = store;
/*let label = view.children[0];
label['z-for'] = 'item in list';*/
console.time('bind');
bind(store, view);
console.timeEnd('bind');
if (cache) {
this._viewCache[name] = view;
}
......
/**
* Created by Raykid on 2016/12/16.
*/
import {IAres, Compiler, AresOptions, IWatcher, WatcherCallback, AresCommandData} from "./Interfaces";
import {Mutator} from "./Mutator";
import {Watcher} from "./Watcher";
import {CommandContext, Command, commands} from "./Commands"
export const defaultCmdRegExp:RegExp = /^(data\-)?a[\-_](\w+)([:\$](.+))?$/;
/**
* 将数据模型和视图进行绑定
* @param data
* @param compiler 视图解析器,不同类型的视图需要使用不同的解析器解析后方可使用
* @param options 一些额外参数
* @returns {IAres} 绑定实体对象
*/
export function bind(data:any, compiler:Compiler, options?:AresOptions):IAres
{
return new Ares(data, compiler, options);
}
export class Ares implements IAres
{
private _data:any;
private _compiler:Compiler;
private _options:any;
/** 获取ViewModel */
public get data():any
{
return this._data;
}
/** 获取编译器 */
public get compiler():Compiler
{
return this._compiler;
}
public constructor(data:any, compiler:Compiler, options?:AresOptions)
{
// 记录变异对象
this._data = Mutator.mutate(data);
this._compiler = compiler;
this._options = options;
// 初始化Compiler
this._compiler.init(this);
// 调用回调
if(this._options && this._options.inited)
{
this._options.inited.call(this._data, this);
}
}
public createWatcher(target:any, exp:string, scope:any, callback:WatcherCallback):IWatcher
{
return new Watcher(this, target, exp, scope, callback);
}
/**
* 解析表达式成为命令数据
* @param key 属性名,合法的属性名应以a-或a_开头,以:或$分隔主命令和子命令
* @param value 属性值,如果属性名合法则会被用来作为表达式的字符串
* @param cmdRegExp 可选,如果不传则使用默认的命令正则表达式解析命令
* @return {CommandData|null} 命令数据,如果不是命令则返回null
*/
public parseCommand(key:string, value:string, cmdRegExp?:RegExp):AresCommandData
{
var result:RegExpExecArray = (cmdRegExp || defaultCmdRegExp).exec(key);
if(!result) return null;
// 取到key
var key:string = result[0];
// 取到命令名
var cmdName:string = result[2];
// 取到命令字符串
var exp:string = value;
// 取到子命令名
var subCmd:string = result[4] || "";
// 返回结构体
return {
cmdName: cmdName,
subCmd: subCmd,
propName: key,
exp: exp
};
}
/**
* 测试是否是通用命令
* @param data 命令数据
* @return {boolean} 返回一个布尔值,表示该表达式是否是通用命令
*/
public testCommand(data:AresCommandData):boolean
{
// 非空判断
if(!data) return false;
// 取到通用命令
var cmd:Command = commands[data.cmdName];
return (cmd != null);
}
/**
* 执行通用命令,如果该表达式是通用命令则直接执行,否则什么都不做
* @param data 命令数据
* @param target 目标对象
* @param scope 变量作用域
* @return {boolean} 返回一个布尔值,表示该表达式是否是通用命令
*/
public execCommand(data:AresCommandData, target:any, scope:any):boolean
{
// 非空判断
if(!data || !scope) return false;
// 取到通用命令
var cmd:Command = commands[data.cmdName];
// 没找到命令就返回false
if(!cmd) return false;
// 找到命令了,执行之
cmd({
target: target,
scope: scope,
entity: this,
data: data
});
return true;
}
}
\ No newline at end of file
......@@ -2,15 +2,15 @@
* Created by Raykid on 2017/7/19.
*/
import {IAres, AresCommandData} from "./Interfaces"
import {IZri, ZriCommandData} from "./Interfaces"
import {runExp} from "./Utils"
export interface CommandContext
{
target:any;
scope:any;
entity:IAres;
data:AresCommandData;
entity:IZri;
data:ZriCommandData;
}
export interface Command
......
......@@ -4,32 +4,27 @@
import {Watcher} from "./Watcher";
export class Dep
{
private _map:{[uid:number]:Watcher} = {};
export class Dep {
private _map: { [uid: number]: Watcher } = {};
/**
* 添加数据变更订阅者
* @param watcher 数据变更订阅者
*/
public watch(watcher:Watcher):void
{
if(!this._map[watcher.uid])
{
this._map[watcher.uid] = watcher;
}
}
/**
* 添加数据变更订阅者
* @param watcher 数据变更订阅者
*/
public watch(watcher: Watcher): void {
if (!this._map[watcher.uid]) {
this._map[watcher.uid] = watcher;
}
}
/**
* 数据变更,通知所有订阅者
* @param extra 可能的额外数据
*/
public notify(extra?:any):void
{
for(var uid in this._map)
{
var watcher:Watcher = this._map[uid];
watcher.update(extra);
}
}
/**
* 数据变更,通知所有订阅者
* @param extra 可能的额外数据
*/
public notify(extra?: any): void {
for (var uid in this._map) {
var watcher: Watcher = this._map[uid];
watcher.update(extra);
}
}
}
\ No newline at end of file
......@@ -7,9 +7,9 @@ export interface Compiler
root:any;
/**
* 初始化编译器
* @param entity Ares实例
* @param entity Zri实例
*/
init(entity:IAres):void;
init(entity:IZri):void;
/**
* 编译方法
* @param target 要编译的显示节点
......@@ -18,7 +18,7 @@ export interface Compiler
compile(target:any, scope:any):void;
}
export interface IAres
export interface IZri
{
/** 获取ViewModel */
data:any;
......@@ -39,13 +39,13 @@ export interface IAres
* @param value 属性值,如果属性名合法则会被用来作为表达式的字符串
* @return {CommandData|null} 命令数据,如果不是命令则返回null
*/
parseCommand(key:string, value:string):AresCommandData;
parseCommand(key:string, value:string):ZriCommandData;
/**
* 测试是否是通用命令
* @param data 命令数据
* @return {boolean} 返回一个布尔值,表示该表达式是否是通用命令
*/
testCommand(data:AresCommandData):boolean;
testCommand(data:ZriCommandData):boolean;
/**
* 执行通用命令,如果该表达式是通用命令则直接执行,否则什么都不做
* @param data 命令数据
......@@ -53,12 +53,12 @@ export interface IAres
* @param scope 变量作用域
* @return {boolean} 返回一个布尔值,表示该表达式是否是通用命令
*/
execCommand(data:AresCommandData, target:any, scope:any):boolean
execCommand(data:ZriCommandData, target:any, scope:any):boolean
}
export interface AresOptions
export interface ZriOptions
{
inited?:(entity?:IAres)=>void;
inited?:(entity?:IZri)=>void;
}
export interface IWatcher
......@@ -82,7 +82,7 @@ export interface WatcherCallback
(newValue?:any, oldValue?:any, extra?:any):void;
}
export interface AresCommandData
export interface ZriCommandData
{
/** 主命令名 */
cmdName:string;
......@@ -92,4 +92,4 @@ export interface AresCommandData
propName:string;
/** 表达式 */
exp:string;
}
\ No newline at end of file
}
......@@ -5,143 +5,134 @@
import {Watcher} from "./Watcher";
import {Dep} from "./Dep";
export class Mutator
{
// 记录数组中会造成数据更新的所有方法名
private static _arrMethods:string[] = [
"push",
"pop",
"unshift",
"shift",
"splice",
"sort",
"reverse"
];
export class Mutator {
// 记录数组中会造成数据更新的所有方法名
private static _arrMethods: string[] = [
"push",
"pop",
"unshift",
"shift",
"splice",
"sort",
"reverse"
];
/**
* 将用户传进来的数据“变异”成为具有截获数据变更能力的数据
* @param data 原始数据
* @returns {any} 变异后的数据
*/
public static mutate(data:any):any
{
// 如果是简单类型,则啥也不做
if(!data || typeof data != "object") return;
// 是个复杂类型对象,但是以前变异过了就不再重做一遍了
if(!data.__ares_mutated__)
{
// 针对每个内部变量都进行一次变异
for(var key in data)
{
Mutator.mutateObject(data, key, data[key]);
}
// 打一个标记表示已经变异过了
Object.defineProperty(data, "__ares_mutated__", {
value: true,
writable: false,
enumerable: false,
configurable: false
});
}
return data;
}
/**
* 将用户传进来的数据“变异”成为具有截获数据变更能力的数据
* @param data 原始数据
* @returns {any} 变异后的数据
*/
public static mutate(data: any): any {
// 如果是简单类型,则啥也不做
if (!data || typeof data != "object") return;
// 是个复杂类型对象,但是以前变异过了就不再重做一遍了
if (!data.__ares_mutated__) {
// 针对每个内部变量都进行一次变异
for (var key in data) {
Mutator.mutateProp(data, key, data[key]);
}
// 打一个标记表示已经变异过了
Object.defineProperty(data, "__ares_mutated__", {
value: true,
writable: false,
enumerable: false,
configurable: false
});
}
return data;
}
private static mutateObject(data:any, key:string, value:any):void
{
// 对每个复杂类型对象都要有一个对应的依赖列表
var dep:Dep = new Dep();
// 变异过程
Object.defineProperty(data, key, {
enumerable: true,
configurable: false,
get: ()=>{
// 如果Watcher.updating不是null,说明当前正在执行表达式,那么获取的变量自然是其需要依赖的
var watcher:Watcher = Watcher.updating;
if(watcher) dep.watch(watcher);
// 利用闭包保存原始值
return value;
},
set: v=>{
if(v == value) return;
value = v;
// 如果是数组就走专门的数组变异方法,否则递归变异对象
if(Array.isArray(v)) Mutator.mutateArray(v, dep);
else Mutator.mutate(v);
// 触发通知
dep.notify();
}
});
// 递归变异
Mutator.mutate(value);
}
private static mutateProp(data: any, key: string, value: any): void {
// 对每个复杂类型对象都要有一个对应的依赖列表
var dep: Dep = new Dep();
// 变异过程
Object.defineProperty(data, key, {
enumerable: true,
configurable: false,
get: () => {
// 如果Watcher.updating不是null,说明当前正在执行表达式,那么获取的变量自然是其需要依赖的
var watcher: Watcher = Watcher.updating;
if (watcher) dep.watch(watcher);
// 利用闭包保存原始值
return value;
},
set: v => {
if (v == value) return;
value = v;
// 如果是数组就走专门的数组变异方法,否则递归变异对象
if (Array.isArray(v)) Mutator.mutateArray(v, dep);
else Mutator.mutate(v);
// 触发通知
dep.notify();
}
});
if(Array.isArray(value)){
Mutator.mutateArray(value, dep);
}else{
// 递归变异
Mutator.mutate(value);
}
}
private static mutateArray(arr:any[], dep:Dep):void
{
// 变异当前数组
arr["__proto__"] = Mutator.defineReactiveArray(dep);
// 遍历当前数组,将内容对象全部变异
for(var i:number = 0, len:number = arr.length; i < len; i++)
{
Mutator.mutate(arr[i]);
}
}
private static mutateArray(arr: any[], dep: Dep): void {
// 变异当前数组
arr["__proto__"] = Mutator.defineReactiveArray(dep);
// 遍历当前数组,将内容对象全部变异
for (var i: number = 0, len: number = arr.length; i < len; i++) {
Mutator.mutate(arr[i]);
}
}
private static defineReactiveArray(dep:Dep):any[]
{
var proto:any[] = Array.prototype;
var result:any[] = Object.create(proto);
// 遍历所有方法,一个一个地变异
Mutator._arrMethods.forEach((method:string)=>{
// 利用闭包记录一个原始方法
var oriMethod:Function = proto[method];
// 开始变异
Object.defineProperty(result, method, {
value: function(...args:any[]):any
{
// 首先调用原始方法,获取返回值
var result:any = oriMethod.apply(this, args);
// 数组插入项
var inserted:any[];
switch(method)
{
case "push":
case "unshift":
inserted = args;
break
case "splice":
inserted = args.slice(2);
break
}
// 监视数组插入项,而不是重新监视整个数组
if(inserted && inserted.length)
{
Mutator.mutateArray(inserted, dep);
}
// 触发更新
dep.notify({method: args});
// 返回值
return result;
}
});
});
// 提供替换数组设置的方法,因为直接设置数组下标的方式无法变异
Object.defineProperty(result, "$set", {
value: function(index:number, value:any):any
{
// 超出数组长度默认追加到最后
if(index >= this.length) index = this.length;
return this.splice(index, 1, value)[0];
}
});
// 提供替换数组移除的方法,因为直接移除的方式无法变异
Object.defineProperty(result, "$remove", {
value: function(item:any):any
{
var index = this.indexOf(item);
if(index > -1) return this.splice(index, 1);
return null;
}
});
return result;
}
private static defineReactiveArray(dep: Dep): any[] {
var proto: any[] = Array.prototype;
var result: any[] = Object.create(proto);
// 遍历所有方法,一个一个地变异
Mutator._arrMethods.forEach((method: string) => {
// 利用闭包记录一个原始方法
var oriMethod: Function = proto[method];
// 开始变异
Object.defineProperty(result, method, {
value: function (...args: any[]): any {
// 首先调用原始方法,获取返回值
var result: any = oriMethod.apply(this, args);
// 数组插入项
var inserted: any[];
switch (method) {
case "push":
case "unshift":
inserted = args;
break
case "splice":
inserted = args.slice(2);
break
}
// 监视数组插入项,而不是重新监视整个数组
if (inserted && inserted.length) {
Mutator.mutateArray(inserted, dep);
}
// 触发更新
dep.notify({method: args});
// 返回值
return result;
}
});
});
// 提供替换数组设置的方法,因为直接设置数组下标的方式无法变异
Object.defineProperty(result, "$set", {
value: function (index: number, value: any): any {
// 超出数组长度默认追加到最后
if (index >= this.length) index = this.length;
return this.splice(index, 1, value)[0];
}
});
// 提供替换数组移除的方法,因为直接移除的方式无法变异
Object.defineProperty(result, "$remove", {
value: function (item: any): any {
var index = this.indexOf(item);
if (index > -1) return this.splice(index, 1);
return null;
}
});
return result;
}
}
\ No newline at end of file
......@@ -6,27 +6,27 @@
* @param exp 表达式
* @returns {Function} 创建的方法
*/
export function createEvalFunc(exp:string):(scope:any)=>any
{
var func:(scope:any)=>any;
try
{
func = Function("scope", "with(scope){return " + exp + "}") as (scope:any)=>any;
}
catch(err)
{
// 可能是某些版本的解释器不认识模板字符串,将模板字符串变成普通字符串
var sepStr:string = (exp.indexOf('"') < 0 ? '"' : "'");
// 将exp中的·替换为'
var reg:RegExp = /([^\\]?)`/g;
exp = exp.replace(reg, "$1" + sepStr);
// 将exp中${...}替换为" + ... + "的形式
reg = /\$\{(.*?)\}/g;
exp = exp.replace(reg, sepStr + "+($1)+" + sepStr);
// 重新生成方法并返回
func = Function("scope", "with(scope){return " + exp + "}") as (scope:any)=>any;
}
return func;
export function createEvalFunc(exp: string): (scope: any) => any {
var func: (scope: any) => any;
try {
func = Function("scope", "with(scope){return " + exp + "}") as (scope: any) => any;
} catch (err) {
// 可能是某些版本的解释器不认识模板字符串,将模板字符串变成普通字符串
var sepStr: string = (exp.indexOf('"') < 0 ? '"' : "'");
// 将exp中的·替换为'
var reg: RegExp = /([^\\]?)`/g;
exp = exp.replace(reg, "$1" + sepStr);
// 将exp中${...}替换为" + ... + "的形式
reg = /\$\{(.*?)\}/g;
exp = exp.replace(reg, sepStr + "+($1)+" + sepStr);
// 重新生成方法并返回
try {
func = Function("scope", "with(scope){return " + exp + "}") as (scope: any) => any;
}catch (e) {
console.error('非法的表达式:', exp);
}
}
return func;
}
/**
......@@ -35,9 +35,8 @@ export function createEvalFunc(exp:string):(scope:any)=>any
* @param scope 表达式的作用域
* @returns {any} 返回值
*/
export function evalExp(exp:string, scope:any):any
{
return createEvalFunc(exp)(scope);
export function evalExp(exp: string, scope: any): any {
return createEvalFunc(exp)(scope);
}
/**
......@@ -45,9 +44,8 @@ export function evalExp(exp:string, scope:any):any
* @param exp 表达式
* @returns {Function} 创建的方法
*/
export function createRunFunc(exp:string):(scope:any)=>void
{
return createEvalFunc("(function(){" + exp + "})()");
export function createRunFunc(exp: string): (scope: any) => void {
return createEvalFunc("(function(){" + exp + "})()");
}
/**
......@@ -55,7 +53,6 @@ export function createRunFunc(exp:string):(scope:any)=>void
* @param exp 表达式
* @param scope 表达式的作用域
*/
export function runExp(exp:string, scope:any):void
{
createRunFunc(exp)(scope);
export function runExp(exp: string, scope: any): void {
createRunFunc(exp)(scope);
}
\ No newline at end of file
import {IAres, IWatcher, WatcherCallback} from "./Interfaces";
import {IZri, IWatcher, WatcherCallback} from "./Interfaces";
import {createEvalFunc} from "./Utils";
/**
* Created by Raykid on 2016/12/22.
* 数据更新订阅者,当依赖的数据有更新时会触发callback通知外面
*/
export class Watcher implements IWatcher
{
/** 记录当前正在执行update方法的Watcher引用 */
public static updating:Watcher = null;
export class Watcher implements IWatcher {
/** 记录当前正在执行update方法的Watcher引用 */
public static updating: Watcher = null;
private static _uid:number = 0;
private static _uid: number = 0;
private _uid:number;
/** 获取Watcher的全局唯一ID */
public get uid():number
{
return this._uid;
}
private _uid: number;
/** 获取Watcher的全局唯一ID */
public get uid(): number {
return this._uid;
}
private _value:any;
private _value: any;
private _entity:IAres;
private _target:any;
private _exp:string;
private _scope:any;
private _expFunc:(scope:any)=>any;
private _callback:WatcherCallback;
private _entity: IZri;
private _target: any;
private _exp: string;
private _scope: any;
private _expFunc: (scope: any) => any;
private _callback: WatcherCallback;
private _disposed:boolean = false;
private _disposed: boolean = false;
public constructor(entity:IAres, target:any, exp:string, scope:any, callback:WatcherCallback)
{
// 记录entity
this._entity = entity;
// 生成一个全局唯一的ID
this._uid = Watcher._uid ++;
// 记录作用目标、表达式和作用域
this._target = target;
this._exp = exp;
this._scope = scope;
// 将表达式和作用域解析为一个Function
this._expFunc = createEvalFunc(exp);
// 记录回调函数
this._callback = callback;
// 进行首次更新
this.update();
}
public constructor(entity: IZri, target: any, exp: string, scope: any, callback: WatcherCallback) {
// 记录entity
this._entity = entity;
// 生成一个全局唯一的ID
this._uid = Watcher._uid++;
// 记录作用目标、表达式和作用域
this._target = target;
this._exp = exp;
this._scope = scope;
// 将表达式和作用域解析为一个Function
this._expFunc = createEvalFunc(exp);
// 记录回调函数
this._callback = callback;
// 进行首次更新
this.update();
}
/**
* 获取到表达式当前最新值
* @returns {any} 最新值
*/
public getValue():any
{
if(this._disposed) return null;
var value:any = null;
// 记录自身
Watcher.updating = this;
// 设置通用属性
// 这里一定要用defineProperty将目标定义在当前节点上,否则会影响context.scope
Object.defineProperty(this._scope, "$root", {
configurable: true,
enumerable: false,
value: this._entity.compiler.root,
writable: false
});
// 这里一定要用defineProperty将目标定义在当前节点上,否则会影响context.scope
Object.defineProperty(this._scope, "$target", {
configurable: true,
enumerable: false,
value: this._target,
writable: false
});
// 表达式求值
try
{
value = this._expFunc.call(this._scope, this._scope);
}
catch(err)
{
// 输出错误日志
console.warn("表达式求值错误\nerr: " + err.toString() + "\nexp:" + this._exp + ",scope:" + JSON.stringify(this._scope));
}
// 移除通用属性
delete this._scope["$root"];
delete this._scope["$target"];
// 移除自身记录
Watcher.updating = null;
return value;
}
/**
* 获取到表达式当前最新值
* @returns {any} 最新值
*/
public getValue(): any {
if (this._disposed) return null;
var value: any = null;
// 记录自身
Watcher.updating = this;
// 设置通用属性
// 这里一定要用defineProperty将目标定义在当前节点上,否则会影响context.scope
Object.defineProperty(this._scope, "$root", {
configurable: true,
enumerable: false,
value: this._entity.compiler.root,
writable: false
});
// 这里一定要用defineProperty将目标定义在当前节点上,否则会影响context.scope
Object.defineProperty(this._scope, "$target", {
configurable: true,
enumerable: false,
value: this._target,
writable: false
});
// 表达式求值
try {
value = this._expFunc.call(this._scope, this._scope);
} catch (err) {
// 输出错误日志
console.warn("表达式求值错误\nerr: " + err.toString() + "\nexp:" + this._exp + ",scope:" + JSON.stringify(this._scope));
}
// 移除通用属性
delete this._scope["$root"];
delete this._scope["$target"];
// 移除自身记录
Watcher.updating = null;
return value;
}
/**
* 当依赖的数据有更新时调用该方法
* @param extra 可能的额外数据
*/
public update(extra?:any):void
{
if(this._disposed) return;
var value:any = this.getValue();
if(!Watcher.isEqual(value, this._value))
{
this._callback && this._callback(value, this._value, extra);
this._value = Watcher.deepCopy(value);
}
}
/** 销毁订阅者 */
public dispose():void
{
if(this._disposed) return;
this._value = null;
this._target = null;
this._exp = null;
this._scope = null;
this._expFunc = null;
this._callback = null;
this._disposed = true;
}
/**
* 当依赖的数据有更新时调用该方法
* @param extra 可能的额外数据
*/
public update(extra?: any): void {
if (this._disposed) return;
var value: any = this.getValue();
if (!Watcher.isEqual(value, this._value)) {
this._callback && this._callback(value, this._value, extra);
this._value = Watcher.deepCopy(value);
}
}
/**
* 是否相等,包括基础类型和对象/数组的对比
*/
private static isEqual(a:any, b:any):boolean
{
return (a == b || (
Watcher.isObject(a) && Watcher.isObject(b)
? JSON.stringify(a) == JSON.stringify(b)
: false
));
}
/** 销毁订阅者 */
public dispose(): void {
if (this._disposed) return;
this._value = null;
this._target = null;
this._exp = null;
this._scope = null;
this._expFunc = null;
this._callback = null;
this._disposed = true;
}
/**
* 是否为对象(包括数组、正则等)
*/
private static isObject(obj:any):boolean
{
return (obj && typeof obj == "object");
}
/**
* 是否相等,包括基础类型和对象/数组的对比
*/
private static isEqual(a: any, b: any): boolean {
return (a == b || (
Watcher.isObject(a) && Watcher.isObject(b)
? JSON.stringify(a) == JSON.stringify(b)
: false
));
}
/**
* 复制对象,若为对象则深度复制
*/
private static deepCopy(from:any):any
{
if (Watcher.isObject(from))
{
// 复杂类型对象,先字符串化,再对象化
return JSON.parse(JSON.stringify(from));
}
else
{
// 基本类型对象,直接返回之
return from;
}
}
/**
* 是否为对象(包括数组、正则等)
*/
private static isObject(obj: any): boolean {
return (obj && typeof obj == "object");
}
/**
* 复制对象,若为对象则深度复制
*/
private static deepCopy(from: any): any {
if (Watcher.isObject(from)) {
// 复杂类型对象,先字符串化,再对象化
return JSON.parse(JSON.stringify(from));
} else {
// 基本类型对象,直接返回之
return from;
}
}
}
\ No newline at end of file
/**
* Created by rockyl on 2020-03-19.
*/
import {IZri, Compiler, ZriOptions, IWatcher, WatcherCallback, ZriCommandData} from "./Interfaces";
import {Mutator} from "./Mutator";
import {Watcher} from "./Watcher";
import {CommandContext, Command, commands} from "./Commands"
export const defaultCmdRegExp:RegExp = /^(data\-)?z[\-_](\w+)([:\$](.+))?$/;
export class Zri implements IZri
{
private _data:any;
private _compiler:Compiler;
private _options:any;
/** 获取ViewModel */
public get data():any
{
return this._data;
}
/** 获取编译器 */
public get compiler():Compiler
{
return this._compiler;
}
public constructor(data:any, compiler:Compiler, options?:ZriOptions)
{
// 记录变异对象
this._data = Mutator.mutate(data);
this._compiler = compiler;
this._options = options;
// 初始化Compiler
this._compiler.init(this);
// 调用回调
if(this._options && this._options.inited)
{
this._options.inited.call(this._data, this);
}
}
public createWatcher(target:any, exp:string, scope:any, callback:WatcherCallback):IWatcher
{
return new Watcher(this, target, exp, scope, callback);
}
/**
* 解析表达式成为命令数据
* @param key 属性名,合法的属性名应以a-或a_开头,以:或$分隔主命令和子命令
* @param value 属性值,如果属性名合法则会被用来作为表达式的字符串
* @param cmdRegExp 可选,如果不传则使用默认的命令正则表达式解析命令
* @return {CommandData|null} 命令数据,如果不是命令则返回null
*/
public parseCommand(key:string, value:string, cmdRegExp?:RegExp):ZriCommandData
{
var result:RegExpExecArray = (cmdRegExp || defaultCmdRegExp).exec(key);
if(!result) return null;
// 取到key
var key:string = result[0];
// 取到命令名
var cmdName:string = result[2];
// 取到命令字符串
var exp:string = value;
// 取到子命令名
var subCmd:string = result[4] || "";
// 返回结构体
return {
cmdName: cmdName,
subCmd: subCmd,
propName: key,
exp: exp
};
}
/**
* 测试是否是通用命令
* @param data 命令数据
* @return {boolean} 返回一个布尔值,表示该表达式是否是通用命令
*/
public testCommand(data:ZriCommandData):boolean
{
// 非空判断
if(!data) return false;
// 取到通用命令
var cmd:Command = commands[data.cmdName];
return (cmd != null);
}
/**
* 执行通用命令,如果该表达式是通用命令则直接执行,否则什么都不做
* @param data 命令数据
* @param target 目标对象
* @param scope 变量作用域
* @return {boolean} 返回一个布尔值,表示该表达式是否是通用命令
*/
public execCommand(data:ZriCommandData, target:any, scope:any):boolean
{
// 非空判断
if(!data || !scope) return false;
// 取到通用命令
var cmd:Command = commands[data.cmdName];
// 没找到命令就返回false
if(!cmd) return false;
// 找到命令了,执行之
cmd({
target: target,
scope: scope,
entity: this,
data: data
});
return true;
}
}
/**
* Created by rockyl on 2020-03-19.
*/
import {DisplayObject} from "../../../2d/display/DisplayObject";
import {ZriCompiler} from "./ZriCompiler";
import {IWatcher, IZri, ZriCommandData} from "./Interfaces";
import {evalExp, runExp} from "./Utils";
import {Container} from "../../../2d/display/index";
export interface Command {
/**
* 执行命令
* @param context 命令上下文
*/
(context?: CommandContext): DisplayObject;
}
export interface CommandContext {
scope: any;
target: Container;
entity: IZri;
cmdData: ZriCommandData;
[name: string]: any;
}
export const commands: { [name: string]: Command } = {
prop: (context: CommandContext) => {
let cmdData: ZriCommandData = context.cmdData;
let target: DisplayObject = context.target;
context.entity.createWatcher(target, cmdData.exp, context.scope, (value: any) => {
if (cmdData.subCmd != "") {
target[cmdData.subCmd] = value;
} else {
for (let name in value) {
target[name] = value[name];
}
}
});
// 返回节点
return target;
},
on: (context: CommandContext) => {
let cmdData: ZriCommandData = context.cmdData;
if (cmdData.subCmd != "") {
let handler: Function = context.scope[cmdData.exp] || window[context.cmdData.exp];
if (typeof handler == "function") {
// 是函数名形式
context.target.addEventListener(cmdData.subCmd, function () {
handler.apply(this, arguments);
}, context.scope);
} else {
// 是方法执行或者表达式方式
context.target.addEventListener(cmdData.subCmd, (evt: Event) => {
// 创建一个临时的子域,用于保存参数
let scope: any = Object.create(context.scope);
scope.$event = evt;
scope.$target = context.target;
runExp(cmdData.exp, scope);
});
}
}
// 返回节点
return context.target;
},
if: (context: CommandContext) => {
let cmdData: ZriCommandData = context.cmdData;
// 记录一个是否编译过的flag
let compiled: boolean = false;
// 插入一个占位元素
let refNode: Container = new Container();
refNode.mouseChildren = refNode.mouseEnabled = false;
let parent: Container = context.target.parent;
let index: number = parent.getChildIndex(context.target);
parent.removeChildAt(index);
parent.addChildAt(refNode, index);
// 只有在条件为true时才启动编译
let watcher: IWatcher = context.entity.createWatcher(context.target, cmdData.exp, context.scope, (value: boolean) => {
// 如果refNode被从显示列表移除了,则表示该if指令要作废了
if (!refNode.parent && !context.target.parent) {
watcher.dispose();
return;
}
if (value == true) {
// 插入节点
if (!context.target.parent) {
let parent = refNode.parent;
let index: number = parent.getChildIndex(refNode);
parent.removeChild(refNode);
parent.addChildAt(context.target, index);
}
// 启动编译
if (!compiled) {
context.compiler.compile(context.target, context.scope);
compiled = true;
}
} else {
// 移除元素
if (context.target.parent) {
let parent = context.target.parent;
let index: number = parent.getChildIndex(context.target);
parent.removeChild(context.target);
parent.addChildAt(refNode, index);
}
}
});
// 返回节点
return context.target;
},
for: (context: CommandContext) => {
let cmdData: ZriCommandData = context.cmdData;
let options = evalExp(cmdData.subCmd, context.scope) || {};
let page: number = (options.page || Number.MAX_VALUE);
// 解析表达式
let reg: RegExp = /^\s*(\S+)\s+in\s+([\s\S]+?)\s*$/;
let res: RegExpExecArray = reg.exec(cmdData.exp);
if (!res) {
console.error("for命令表达式错误:" + cmdData.exp);
return;
}
let itemName: string = res[1];
let arrName: string = res[2];
// 生成一个容器替换原始模板
let index: number = context.target.parent.getChildIndex(context.target);
let parent: Container = new Container();
context.target.parent.addChildAt(parent, index);
context.target.parent.removeChild(context.target);
// 生成一个新的scope,要向其中添加属性
let forScope: any = Object.create(context.scope);
Object.defineProperty(forScope, "$forTarget", {
configurable: true,
enumerable: false,
value: context.target,
writable: false
});
// 如果有viewport命令,则将其转移至容器上
/*let viewportCmds:ZriCommandData[] = context.cmdDict["viewport"];
if(viewportCmds)
{
let viewportCmd:ZriCommandData = viewportCmds[0];
if(viewportCmd)
{
parent[viewportCmd.propName] = viewportCmd.exp;
delete context.target[viewportCmd.propName];
}
}*/
// 使用原始显示对象编译一次parent
context.compiler.compile(parent, forScope);
// 获取窗口显示范围
//let viewportHandler:ViewPortHandler = getViewportHandler(parent);
// 声明闭包数据
let isArray: boolean;
let curList: any[];
let curIndex: number;
let lastNode: DisplayObject;
// 添加订阅
let watcher: IWatcher = context.entity.createWatcher(context.target, arrName, forScope, (value: any) => {
// 如果refNode被从显示列表移除了,则表示该for指令要作废了
if (!parent.parent) {
watcher.dispose();
return;
}
// 清理原始显示
for (let i: number = parent.children.length - 1; i >= 0; i--) {
parent.removeChildAt(i).destroy();
}
// 如果是数字,构建一个数字列表
if (typeof value == "number") {
let temp: number[] = [];
for (let i: number = 0; i < value; i++) {
temp.push(i);
}
value = temp;
}
// 如果不是数组,而是字典,则转换为数组,方便中断遍历
isArray = (value instanceof Array);
let list: any[];
if (isArray) {
list = value;
} else {
list = [];
for (let key in value) {
list.push({
key: key,
value: value[key]
});
}
}
// 初始化数据
curList = list;
curIndex = 0;
lastNode = null;
for (let li = curList.length; curIndex < li; curIndex++) {
//渲染
// 拷贝一个target
let newNode: DisplayObject = context.target.clone(true, true);
// 添加到显示里
parent.addChild(newNode);
// 生成子域
let newScope: any = Object.create(forScope);
// 这里一定要用defineProperty将目标定义在当前节点上,否则会影响forScope
Object.defineProperty(newScope, "$index", {
configurable: true,
enumerable: false,
value: curIndex,
writable: false
});
// 如果是字典则额外注入一个$key
if (!isArray) {
Object.defineProperty(newScope, "$key", {
configurable: true,
enumerable: true,
value: curList[curIndex].key,
writable: false
});
}
// 注入上一个显示节点
Object.defineProperty(newScope, "$last", {
configurable: true,
enumerable: false,
value: lastNode,
writable: false
});
// 添加长度
Object.defineProperty(newScope, "$length", {
configurable: true,
enumerable: false,
value: curList.length,
writable: false
});
// 注入遍历名
Object.defineProperty(newScope, itemName, {
configurable: true,
enumerable: true,
value: (isArray ? curList[curIndex] : curList[curIndex].value),
writable: false
});
// 开始编译新节点
context.compiler.compile(newNode, newScope);
// 赋值上一个节点
lastNode = newNode;
}
});
// 返回节点
return context.target;
}
};
\ No newline at end of file
/**
* Created by rockyl on 2020-03-19.
*/
import {Compiler, IZri, ZriCommandData} from "./Interfaces";
import {Container, } from "../../../2d/display/index";
import {Command, commands, CommandContext} from "./ZriCommands";
import {cmdPrefix} from "../../utils/utils";
const interruptCmds = ['for', 'if'];
export class ZriCompiler implements Compiler {
private _root: Container;
private _entity: IZri;
constructor(root: Container) {
this._root = root;
}
get root(): Container {
return this._root;
}
init(entity: IZri): void {
this._entity = entity;
this.compile(this._root, entity.data);
}
compile(target: any, scope: any): void {
let cmdDatas = [];
let needInterrupt = false;
for (let key in target) {
if(key.indexOf(cmdPrefix) < 0){
continue;
}
let cmdData = this._entity.parseCommand(key, target[key]);
if (cmdData) {
cmdDatas.push(cmdData);
if(interruptCmds.indexOf(cmdData.cmdName) >= 0){
needInterrupt = true;
cmdDatas.splice(0, cmdDatas.length - 1);
break;
}
}
}
for (let cmdData of cmdDatas) {
delete target[cmdData.propName];
if (interruptCmds.indexOf(cmdData.cmdName) >= 0 && target['__originConfig']) {
delete target['__originConfig'].properties[cmdData.propName];
}
let cmd: Command = commands[cmdData.cmdName];
if (!cmd) {
cmdData.subCmd = cmdData.cmdName || "";
cmdData.cmdName = "prop";
cmd = commands[cmdData.cmdName];
}
cmd({
scope,
target,
entity: this._entity,
cmdData,
compiler: this,
})
}
if (!needInterrupt && target.children && target.children.length > 0) {
for (let child of target.children) {
this.compile(child, scope);
}
}
}
}
/**
* Created by rockyl on 2020-03-02.
*/
import {Zri} from "./Zri";
import {Compiler, IZri, ZriOptions} from "./Interfaces";
import {ZriCompiler} from "./ZriCompiler";
import {Container} from "../../../2d/display/index";
import {safeEval} from "../../utils/utils";
/**
* 将数据模型和视图进行绑定
* @param store 数据
* @param view 视图
* @param options 一些额外参数
* @returns {IZri} 绑定实体对象
*/
export function bind(store: any, view: Container, options?: ZriOptions): IZri {
let compiler = new ZriCompiler(view);
return new Zri(store, compiler, options);
}
/**
* 通过配置生成数据
* @param exp
* @param computed
*/
export function createStore(exp, computed) {
let store = safeEval(exp) || {};
for (let item of computed) {
let getterCode = `return function(){
${item.script}
}`;
if (name && !store.hasOwnProperty(name)) {
Object.defineProperty(store, item.name, {
get: safeEval(getterCode),
})
}
}
return store;
}
......@@ -4,7 +4,7 @@
import {Stage} from "../2d/display";
import {registerCustomModuleFromConfig, registerScripts, RENDERER_TYPE, setProcessMetaLibs, StageScaleMode} from "..";
import {GameStage} from "./game-warpper";
import {GameStage} from "./game-warpper/index";
import {setGlobalContext} from "./behavior-runtime";
import {globalLoader} from "../2d/loader/Loader";
import {Event} from "../2d/events/Event";
......
......@@ -68,6 +68,22 @@ export function getDataByPath(scope, path, throwException?) {
}
}
/**
* 安全的eval方法
* @param code
* @param throwException
*/
export function safeEval(code, throwException = false){
let func = new Function(code);
try {
return func();
}catch (e) {
if (throwException) {
throw e;
}
}
}
/**
* 属性注入方法
* @param target 目标对象
......@@ -303,6 +319,9 @@ export function instantiateScript(node, ScriptConfig) {
const script = node.scripts.add(scriptName, props, disabled);
}
export const cmdPrefix = 'z-';
export const cmdOldPrefix = '//z-';
/**
* 属性注入
* @param target
......@@ -310,7 +329,9 @@ export function instantiateScript(node, ScriptConfig) {
*/
export function injectProperties(target, source) {
for (let key in source) {
propertyParse(key, target, source);
if(!source.hasOwnProperty(cmdPrefix + key)){
propertyParse(key, target, source);
}
}
return target;
......
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Get Token Test</title>
</head>
<body>
<script src="getTokenKey"></script>>
<script src="//yun.duiba.com.cn/js-libs/px-token/0.0.1.4/px-token.min.js"></script>
<script>
function callApi(uri){
getPxToken(async function(e, t){
console.log(e, t);
let token = t;
let el = document.getElementById('token');
el.innerText = 'Token已获取:' + t;
try {
let resp = await fetch(uri + '?token=' + token);
let data = await resp.json();
console.log(data);
}catch (e) {
console.log(e);
}
});
}
</script>
<span id="token">Token获取中...</span>
<div>
<button onclick="callApi('join/tokenJoin.do')">请求[join/tokenJoin.do]</button>
<button onclick="callApi('join/join.do')">请求[join/join.do]</button>
</div>
</body>
</html>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment