Commit eedc3d22 authored by rockyl's avatar rockyl

mvvm实现

parent 43f8406e
This diff is collapsed.
This diff is collapsed.
{"id":"engine","url":"engine.85a610a71df748fd9a6ece34f456a06e8f3f1b63.js"} {"id":"engine","url":"engine.210e93fc8ecfcb27da00c77582649b96949d28c3.js"}
\ No newline at end of file \ No newline at end of file
{ {
"name": "aaaa", "name": "zeroing-engine",
"version": "1.0.0", "version": "0.1.0",
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"types": "index.d.ts", "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 { ...@@ -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; this._lastLocalID = this.transform.localID;
//console.log(this.name, this.instanceId , 'dirty!'); //console.log(this.name, this.instanceId , 'dirty!');
this.stage.layoutInvalid = true; this.stage.layoutInvalid = true;
} }*/
} }
/** /**
...@@ -699,7 +699,7 @@ export default class Container extends DisplayObject { ...@@ -699,7 +699,7 @@ export default class Container extends DisplayObject {
if (this._width !== value) { if (this._width !== value) {
//子类有用,有_width,才需设置scaleX //子类有用,有_width,才需设置scaleX
this._width = value; this._width = value;
if(this.stage) this.stage.layoutInvalid = true; //if (this.stage) this.stage.layoutInvalid = true;
this.dispatchEvent(Event.RESIZE); this.dispatchEvent(Event.RESIZE);
} }
} }
...@@ -722,7 +722,7 @@ export default class Container extends DisplayObject { ...@@ -722,7 +722,7 @@ export default class Container extends DisplayObject {
// } // }
if (this._height !== value) { if (this._height !== value) {
this._height = value; this._height = value;
if(this.stage) this.stage.layoutInvalid = true; //if (this.stage) this.stage.layoutInvalid = true;
this.dispatchEvent(Event.RESIZE); this.dispatchEvent(Event.RESIZE);
} }
} }
...@@ -730,8 +730,10 @@ export default class Container extends DisplayObject { ...@@ -730,8 +730,10 @@ export default class Container extends DisplayObject {
clone(withEvents = false, withScripts = false) { clone(withEvents = false, withScripts = false) {
let target = this.constructor.apply(Object.create(this.constructor.prototype)); 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.name = name;
target['__originConfig'] = originConfig;
injectProperties(target, properties); injectProperties(target, properties);
if (withScripts) { if (withScripts) {
...@@ -755,6 +757,20 @@ export default class Container extends DisplayObject { ...@@ -755,6 +757,20 @@ export default class Container extends DisplayObject {
return target; return target;
} }
get $store() {
let p = this;
while (p.parent) {
p = p.parent;
if (p['$isViewRoot']) {
break;
}
}
if (p) {
return p['$_store'];
}
}
//全局遍历 //全局遍历
/** /**
* @method _getElementsByName * @method _getElementsByName
......
...@@ -83,7 +83,20 @@ export class FloatDisplay extends DisplayObject { ...@@ -83,7 +83,20 @@ export class FloatDisplay extends DisplayObject {
} }
}); });
s.addEventListener(Event.ADDED_TO_STAGE, function (e: Event) { s.addEventListener(Event.ADDED_TO_STAGE, function (e: Event) {
if(!container){ this.addHtmlElement();
}, s);
this._transformID = -1;
}
addHtmlElement() {
let s = this;
if(!s.stage){
return;
}
if (!container) {
container = document.createElement('div'); container = document.createElement('div');
container.style.position = "absolute"; container.style.position = "absolute";
container.style.left = "0"; container.style.left = "0";
...@@ -104,9 +117,6 @@ export class FloatDisplay extends DisplayObject { ...@@ -104,9 +117,6 @@ export class FloatDisplay extends DisplayObject {
} }
} }
} }
});
this._transformID = -1;
} }
get htmlElement() { get htmlElement() {
...@@ -126,7 +136,7 @@ export class FloatDisplay extends DisplayObject { ...@@ -126,7 +136,7 @@ export class FloatDisplay extends DisplayObject {
* @param {HtmlElement} htmlElement 需要封装起来的html元素的引用。你可以通过这个引用来调用或设置此元素自身的属性方法和事件,甚至是样式 * @param {HtmlElement} htmlElement 需要封装起来的html元素的引用。你可以通过这个引用来调用或设置此元素自身的属性方法和事件,甚至是样式
*/ */
protected init(htmlElement: any): void { protected init(htmlElement: any): void {
if(!htmlElement){ if (!htmlElement) {
return; return;
} }
let s = this; let s = this;
...@@ -160,6 +170,8 @@ export class FloatDisplay extends DisplayObject { ...@@ -160,6 +170,8 @@ export class FloatDisplay extends DisplayObject {
s._localBoundsSelf.width = w; s._localBoundsSelf.width = w;
s._localBoundsSelf.height = h; s._localBoundsSelf.height = h;
s._htmlElement = she; s._htmlElement = she;
this.addHtmlElement();
} }
/** /**
......
...@@ -115,11 +115,6 @@ export class Stage extends Container { ...@@ -115,11 +115,6 @@ export class Stage extends Container {
*/ */
private static _stageList: any = {}; private static _stageList: any = {};
/**
* 布局失效
*/
layoutInvalid: boolean = false;
/** /**
* 是否暂停 * 是否暂停
* @property pause * @property pause
...@@ -438,7 +433,7 @@ export class Stage extends Container { ...@@ -438,7 +433,7 @@ export class Stage extends Container {
s.dispatchEvent(Event.ON_INIT_STAGE); s.dispatchEvent(Event.ON_INIT_STAGE);
// } // }
}, 100); }, 100);
let rc = canvas;//s.rootDiv; let rc = s.rootDiv; //canvas
let mouseEvent = s.onMouseEvent.bind(s); let mouseEvent = s.onMouseEvent.bind(s);
//鼠标事件 //鼠标事件
if (osType != "pc") { if (osType != "pc") {
...@@ -648,8 +643,10 @@ export class Stage extends Container { ...@@ -648,8 +643,10 @@ export class Stage extends Container {
cp = new Point(); cp = new Point();
} }
let rootDiv = s.rootDiv;
let doc = document.documentElement; 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 left = box.left + window.pageXOffset - doc.clientLeft;
let top = box.top + window.pageYOffset - doc.clientTop; let top = box.top + window.pageYOffset - doc.clientTop;
cp.x = (points[o].pageX - left) * devicePixelRatio; cp.x = (points[o].pageX - left) * devicePixelRatio;
...@@ -1016,14 +1013,6 @@ export class Stage extends Container { ...@@ -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 { public destroy(): void {
let s = this; let s = this;
Stage.removeUpdateObj(s); Stage.removeUpdateObj(s);
......
...@@ -134,8 +134,6 @@ export default class CanvasRenderer extends SystemRenderer { ...@@ -134,8 +134,6 @@ export default class CanvasRenderer extends SystemRenderer {
displayObject.updateTransform(); displayObject.updateTransform();
displayObject.parent = cacheParent; displayObject.parent = cacheParent;
displayObject.stage && displayObject.stage.afterUpdateTransform();
//初始化上下文状态 //初始化上下文状态
context.save(); context.save();
context.setTransform(1, 0, 0, 1, 0, 0); context.setTransform(1, 0, 0, 1, 0, 0);
......
...@@ -179,8 +179,6 @@ export class WebglRenderer extends SystemRenderer { ...@@ -179,8 +179,6 @@ export class WebglRenderer extends SystemRenderer {
displayObject.updateTransform(); displayObject.updateTransform();
displayObject.parent = cacheParent; displayObject.parent = cacheParent;
displayObject.stage && displayObject.stage.afterUpdateTransform();
//绑定渲染对象,没有则是默认root //绑定渲染对象,没有则是默认root
this.bindRenderTexture(renderTexture, transform); this.bindRenderTexture(renderTexture, transform);
......
...@@ -7,14 +7,16 @@ import {StackContainer} from "./StackContainer"; ...@@ -7,14 +7,16 @@ import {StackContainer} from "./StackContainer";
import {loadAssets} from "./assets-manager"; import {loadAssets} from "./assets-manager";
import {instantiate} from "./view-interpreter"; import {instantiate} from "./view-interpreter";
import {dataCenter, DataCenter} from "./data-center"; import {dataCenter, DataCenter} from "./data-center";
import {setProcessMetaLibs} from "../behavior-runtime"; import {setProcessMetaLibs} from "../behavior-runtime/index";
import {Tween} from "../../2d/tween"; import {Tween} from "../../2d/tween/index";
import {Rect} from "./nodes"; import {Rect} from "./nodes/index";
import {injectEnv} from "./enviroment"; import {injectEnv} from "./enviroment";
import {Toast} from "./Toast"; import {Toast} from "./Toast";
import {arrayFind} from "../utils"; import {arrayFind} from "../utils/index";
import {registerCustomModules, registerScripts} from "..";
import {Node} from "./nodes/Node"; 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 { ...@@ -62,6 +64,7 @@ export class GameStage extends Node {
this._popupContainer.name = 'popup-container'; this._popupContainer.name = 'popup-container';
this._popupContainer.addEventListener('change', this.onPopupContainerChange, this); this._popupContainer.addEventListener('change', this.onPopupContainerChange, this);
} }
/** /**
...@@ -180,6 +183,23 @@ export class GameStage extends Node { ...@@ -180,6 +183,23 @@ export class GameStage extends Node {
let viewConfig = this.getViewConfigByName(name); let viewConfig = this.getViewConfigByName(name);
if (viewConfig) { if (viewConfig) {
view = instantiate(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) { if (cache) {
this._viewCache[name] = view; 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 @@ ...@@ -2,15 +2,15 @@
* Created by Raykid on 2017/7/19. * Created by Raykid on 2017/7/19.
*/ */
import {IAres, AresCommandData} from "./Interfaces" import {IZri, ZriCommandData} from "./Interfaces"
import {runExp} from "./Utils" import {runExp} from "./Utils"
export interface CommandContext export interface CommandContext
{ {
target:any; target:any;
scope:any; scope:any;
entity:IAres; entity:IZri;
data:AresCommandData; data:ZriCommandData;
} }
export interface Command export interface Command
......
...@@ -4,18 +4,15 @@ ...@@ -4,18 +4,15 @@
import {Watcher} from "./Watcher"; import {Watcher} from "./Watcher";
export class Dep export class Dep {
{ private _map: { [uid: number]: Watcher } = {};
private _map:{[uid:number]:Watcher} = {};
/** /**
* 添加数据变更订阅者 * 添加数据变更订阅者
* @param watcher 数据变更订阅者 * @param watcher 数据变更订阅者
*/ */
public watch(watcher:Watcher):void public watch(watcher: Watcher): void {
{ if (!this._map[watcher.uid]) {
if(!this._map[watcher.uid])
{
this._map[watcher.uid] = watcher; this._map[watcher.uid] = watcher;
} }
} }
...@@ -24,11 +21,9 @@ export class Dep ...@@ -24,11 +21,9 @@ export class Dep
* 数据变更,通知所有订阅者 * 数据变更,通知所有订阅者
* @param extra 可能的额外数据 * @param extra 可能的额外数据
*/ */
public notify(extra?:any):void public notify(extra?: any): void {
{ for (var uid in this._map) {
for(var uid in this._map) var watcher: Watcher = this._map[uid];
{
var watcher:Watcher = this._map[uid];
watcher.update(extra); watcher.update(extra);
} }
} }
......
...@@ -7,9 +7,9 @@ export interface Compiler ...@@ -7,9 +7,9 @@ export interface Compiler
root:any; root:any;
/** /**
* 初始化编译器 * 初始化编译器
* @param entity Ares实例 * @param entity Zri实例
*/ */
init(entity:IAres):void; init(entity:IZri):void;
/** /**
* 编译方法 * 编译方法
* @param target 要编译的显示节点 * @param target 要编译的显示节点
...@@ -18,7 +18,7 @@ export interface Compiler ...@@ -18,7 +18,7 @@ export interface Compiler
compile(target:any, scope:any):void; compile(target:any, scope:any):void;
} }
export interface IAres export interface IZri
{ {
/** 获取ViewModel */ /** 获取ViewModel */
data:any; data:any;
...@@ -39,13 +39,13 @@ export interface IAres ...@@ -39,13 +39,13 @@ export interface IAres
* @param value 属性值,如果属性名合法则会被用来作为表达式的字符串 * @param value 属性值,如果属性名合法则会被用来作为表达式的字符串
* @return {CommandData|null} 命令数据,如果不是命令则返回null * @return {CommandData|null} 命令数据,如果不是命令则返回null
*/ */
parseCommand(key:string, value:string):AresCommandData; parseCommand(key:string, value:string):ZriCommandData;
/** /**
* 测试是否是通用命令 * 测试是否是通用命令
* @param data 命令数据 * @param data 命令数据
* @return {boolean} 返回一个布尔值,表示该表达式是否是通用命令 * @return {boolean} 返回一个布尔值,表示该表达式是否是通用命令
*/ */
testCommand(data:AresCommandData):boolean; testCommand(data:ZriCommandData):boolean;
/** /**
* 执行通用命令,如果该表达式是通用命令则直接执行,否则什么都不做 * 执行通用命令,如果该表达式是通用命令则直接执行,否则什么都不做
* @param data 命令数据 * @param data 命令数据
...@@ -53,12 +53,12 @@ export interface IAres ...@@ -53,12 +53,12 @@ export interface IAres
* @param scope 变量作用域 * @param scope 变量作用域
* @return {boolean} 返回一个布尔值,表示该表达式是否是通用命令 * @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 export interface IWatcher
...@@ -82,7 +82,7 @@ export interface WatcherCallback ...@@ -82,7 +82,7 @@ export interface WatcherCallback
(newValue?:any, oldValue?:any, extra?:any):void; (newValue?:any, oldValue?:any, extra?:any):void;
} }
export interface AresCommandData export interface ZriCommandData
{ {
/** 主命令名 */ /** 主命令名 */
cmdName:string; cmdName:string;
......
...@@ -5,10 +5,9 @@ ...@@ -5,10 +5,9 @@
import {Watcher} from "./Watcher"; import {Watcher} from "./Watcher";
import {Dep} from "./Dep"; import {Dep} from "./Dep";
export class Mutator export class Mutator {
{
// 记录数组中会造成数据更新的所有方法名 // 记录数组中会造成数据更新的所有方法名
private static _arrMethods:string[] = [ private static _arrMethods: string[] = [
"push", "push",
"pop", "pop",
"unshift", "unshift",
...@@ -23,17 +22,14 @@ export class Mutator ...@@ -23,17 +22,14 @@ export class Mutator
* @param data 原始数据 * @param data 原始数据
* @returns {any} 变异后的数据 * @returns {any} 变异后的数据
*/ */
public static mutate(data:any):any public static mutate(data: any): any {
{
// 如果是简单类型,则啥也不做 // 如果是简单类型,则啥也不做
if(!data || typeof data != "object") return; if (!data || typeof data != "object") return;
// 是个复杂类型对象,但是以前变异过了就不再重做一遍了 // 是个复杂类型对象,但是以前变异过了就不再重做一遍了
if(!data.__ares_mutated__) if (!data.__ares_mutated__) {
{
// 针对每个内部变量都进行一次变异 // 针对每个内部变量都进行一次变异
for(var key in data) for (var key in data) {
{ Mutator.mutateProp(data, key, data[key]);
Mutator.mutateObject(data, key, data[key]);
} }
// 打一个标记表示已经变异过了 // 打一个标记表示已经变异过了
Object.defineProperty(data, "__ares_mutated__", { Object.defineProperty(data, "__ares_mutated__", {
...@@ -46,64 +42,62 @@ export class Mutator ...@@ -46,64 +42,62 @@ export class Mutator
return data; return data;
} }
private static mutateObject(data:any, key:string, value:any):void private static mutateProp(data: any, key: string, value: any): void {
{
// 对每个复杂类型对象都要有一个对应的依赖列表 // 对每个复杂类型对象都要有一个对应的依赖列表
var dep:Dep = new Dep(); var dep: Dep = new Dep();
// 变异过程 // 变异过程
Object.defineProperty(data, key, { Object.defineProperty(data, key, {
enumerable: true, enumerable: true,
configurable: false, configurable: false,
get: ()=>{ get: () => {
// 如果Watcher.updating不是null,说明当前正在执行表达式,那么获取的变量自然是其需要依赖的 // 如果Watcher.updating不是null,说明当前正在执行表达式,那么获取的变量自然是其需要依赖的
var watcher:Watcher = Watcher.updating; var watcher: Watcher = Watcher.updating;
if(watcher) dep.watch(watcher); if (watcher) dep.watch(watcher);
// 利用闭包保存原始值 // 利用闭包保存原始值
return value; return value;
}, },
set: v=>{ set: v => {
if(v == value) return; if (v == value) return;
value = v; value = v;
// 如果是数组就走专门的数组变异方法,否则递归变异对象 // 如果是数组就走专门的数组变异方法,否则递归变异对象
if(Array.isArray(v)) Mutator.mutateArray(v, dep); if (Array.isArray(v)) Mutator.mutateArray(v, dep);
else Mutator.mutate(v); else Mutator.mutate(v);
// 触发通知 // 触发通知
dep.notify(); dep.notify();
} }
}); });
if(Array.isArray(value)){
Mutator.mutateArray(value, dep);
}else{
// 递归变异 // 递归变异
Mutator.mutate(value); Mutator.mutate(value);
} }
}
private static mutateArray(arr:any[], dep:Dep):void private static mutateArray(arr: any[], dep: Dep): void {
{
// 变异当前数组 // 变异当前数组
arr["__proto__"] = Mutator.defineReactiveArray(dep); arr["__proto__"] = Mutator.defineReactiveArray(dep);
// 遍历当前数组,将内容对象全部变异 // 遍历当前数组,将内容对象全部变异
for(var i:number = 0, len:number = arr.length; i < len; i++) for (var i: number = 0, len: number = arr.length; i < len; i++) {
{
Mutator.mutate(arr[i]); Mutator.mutate(arr[i]);
} }
} }
private static defineReactiveArray(dep:Dep):any[] private static defineReactiveArray(dep: Dep): any[] {
{ var proto: any[] = Array.prototype;
var proto:any[] = Array.prototype; var result: any[] = Object.create(proto);
var result:any[] = Object.create(proto);
// 遍历所有方法,一个一个地变异 // 遍历所有方法,一个一个地变异
Mutator._arrMethods.forEach((method:string)=>{ Mutator._arrMethods.forEach((method: string) => {
// 利用闭包记录一个原始方法 // 利用闭包记录一个原始方法
var oriMethod:Function = proto[method]; var oriMethod: Function = proto[method];
// 开始变异 // 开始变异
Object.defineProperty(result, method, { Object.defineProperty(result, method, {
value: function(...args:any[]):any value: function (...args: any[]): any {
{
// 首先调用原始方法,获取返回值 // 首先调用原始方法,获取返回值
var result:any = oriMethod.apply(this, args); var result: any = oriMethod.apply(this, args);
// 数组插入项 // 数组插入项
var inserted:any[]; var inserted: any[];
switch(method) switch (method) {
{
case "push": case "push":
case "unshift": case "unshift":
inserted = args; inserted = args;
...@@ -113,8 +107,7 @@ export class Mutator ...@@ -113,8 +107,7 @@ export class Mutator
break break
} }
// 监视数组插入项,而不是重新监视整个数组 // 监视数组插入项,而不是重新监视整个数组
if(inserted && inserted.length) if (inserted && inserted.length) {
{
Mutator.mutateArray(inserted, dep); Mutator.mutateArray(inserted, dep);
} }
// 触发更新 // 触发更新
...@@ -126,19 +119,17 @@ export class Mutator ...@@ -126,19 +119,17 @@ export class Mutator
}); });
// 提供替换数组设置的方法,因为直接设置数组下标的方式无法变异 // 提供替换数组设置的方法,因为直接设置数组下标的方式无法变异
Object.defineProperty(result, "$set", { Object.defineProperty(result, "$set", {
value: function(index:number, value:any):any value: function (index: number, value: any): any {
{
// 超出数组长度默认追加到最后 // 超出数组长度默认追加到最后
if(index >= this.length) index = this.length; if (index >= this.length) index = this.length;
return this.splice(index, 1, value)[0]; return this.splice(index, 1, value)[0];
} }
}); });
// 提供替换数组移除的方法,因为直接移除的方式无法变异 // 提供替换数组移除的方法,因为直接移除的方式无法变异
Object.defineProperty(result, "$remove", { Object.defineProperty(result, "$remove", {
value: function(item:any):any value: function (item: any): any {
{
var index = this.indexOf(item); var index = this.indexOf(item);
if(index > -1) return this.splice(index, 1); if (index > -1) return this.splice(index, 1);
return null; return null;
} }
}); });
......
...@@ -6,25 +6,25 @@ ...@@ -6,25 +6,25 @@
* @param exp 表达式 * @param exp 表达式
* @returns {Function} 创建的方法 * @returns {Function} 创建的方法
*/ */
export function createEvalFunc(exp:string):(scope:any)=>any export function createEvalFunc(exp: string): (scope: any) => any {
{ var func: (scope: any) => any;
var func:(scope:any)=>any; try {
try func = Function("scope", "with(scope){return " + exp + "}") as (scope: any) => any;
{ } catch (err) {
func = Function("scope", "with(scope){return " + exp + "}") as (scope:any)=>any;
}
catch(err)
{
// 可能是某些版本的解释器不认识模板字符串,将模板字符串变成普通字符串 // 可能是某些版本的解释器不认识模板字符串,将模板字符串变成普通字符串
var sepStr:string = (exp.indexOf('"') < 0 ? '"' : "'"); var sepStr: string = (exp.indexOf('"') < 0 ? '"' : "'");
// 将exp中的·替换为' // 将exp中的·替换为'
var reg:RegExp = /([^\\]?)`/g; var reg: RegExp = /([^\\]?)`/g;
exp = exp.replace(reg, "$1" + sepStr); exp = exp.replace(reg, "$1" + sepStr);
// 将exp中${...}替换为" + ... + "的形式 // 将exp中${...}替换为" + ... + "的形式
reg = /\$\{(.*?)\}/g; reg = /\$\{(.*?)\}/g;
exp = exp.replace(reg, sepStr + "+($1)+" + sepStr); exp = exp.replace(reg, sepStr + "+($1)+" + sepStr);
// 重新生成方法并返回 // 重新生成方法并返回
func = Function("scope", "with(scope){return " + exp + "}") as (scope:any)=>any; try {
func = Function("scope", "with(scope){return " + exp + "}") as (scope: any) => any;
}catch (e) {
console.error('非法的表达式:', exp);
}
} }
return func; return func;
} }
...@@ -35,8 +35,7 @@ export function createEvalFunc(exp:string):(scope:any)=>any ...@@ -35,8 +35,7 @@ export function createEvalFunc(exp:string):(scope:any)=>any
* @param scope 表达式的作用域 * @param scope 表达式的作用域
* @returns {any} 返回值 * @returns {any} 返回值
*/ */
export function evalExp(exp:string, scope:any):any export function evalExp(exp: string, scope: any): any {
{
return createEvalFunc(exp)(scope); return createEvalFunc(exp)(scope);
} }
...@@ -45,8 +44,7 @@ export function evalExp(exp:string, scope:any):any ...@@ -45,8 +44,7 @@ export function evalExp(exp:string, scope:any):any
* @param exp 表达式 * @param exp 表达式
* @returns {Function} 创建的方法 * @returns {Function} 创建的方法
*/ */
export function createRunFunc(exp:string):(scope:any)=>void export function createRunFunc(exp: string): (scope: any) => void {
{
return createEvalFunc("(function(){" + exp + "})()"); return createEvalFunc("(function(){" + exp + "})()");
} }
...@@ -55,7 +53,6 @@ export function createRunFunc(exp:string):(scope:any)=>void ...@@ -55,7 +53,6 @@ export function createRunFunc(exp:string):(scope:any)=>void
* @param exp 表达式 * @param exp 表达式
* @param scope 表达式的作用域 * @param scope 表达式的作用域
*/ */
export function runExp(exp:string, scope:any):void export function runExp(exp: string, scope: any): void {
{
createRunFunc(exp)(scope); 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"; import {createEvalFunc} from "./Utils";
/** /**
* Created by Raykid on 2016/12/22. * Created by Raykid on 2016/12/22.
* 数据更新订阅者,当依赖的数据有更新时会触发callback通知外面 * 数据更新订阅者,当依赖的数据有更新时会触发callback通知外面
*/ */
export class Watcher implements IWatcher export class Watcher implements IWatcher {
{
/** 记录当前正在执行update方法的Watcher引用 */ /** 记录当前正在执行update方法的Watcher引用 */
public static updating:Watcher = null; public static updating: Watcher = null;
private static _uid:number = 0; private static _uid: number = 0;
private _uid:number; private _uid: number;
/** 获取Watcher的全局唯一ID */ /** 获取Watcher的全局唯一ID */
public get uid():number public get uid(): number {
{
return this._uid; return this._uid;
} }
private _value:any; private _value: any;
private _entity:IAres; private _entity: IZri;
private _target:any; private _target: any;
private _exp:string; private _exp: string;
private _scope:any; private _scope: any;
private _expFunc:(scope:any)=>any; private _expFunc: (scope: any) => any;
private _callback:WatcherCallback; private _callback: WatcherCallback;
private _disposed:boolean = false; private _disposed: boolean = false;
public constructor(entity:IAres, target:any, exp:string, scope:any, callback:WatcherCallback) public constructor(entity: IZri, target: any, exp: string, scope: any, callback: WatcherCallback) {
{
// 记录entity // 记录entity
this._entity = entity; this._entity = entity;
// 生成一个全局唯一的ID // 生成一个全局唯一的ID
this._uid = Watcher._uid ++; this._uid = Watcher._uid++;
// 记录作用目标、表达式和作用域 // 记录作用目标、表达式和作用域
this._target = target; this._target = target;
this._exp = exp; this._exp = exp;
...@@ -52,10 +49,9 @@ export class Watcher implements IWatcher ...@@ -52,10 +49,9 @@ export class Watcher implements IWatcher
* 获取到表达式当前最新值 * 获取到表达式当前最新值
* @returns {any} 最新值 * @returns {any} 最新值
*/ */
public getValue():any public getValue(): any {
{ if (this._disposed) return null;
if(this._disposed) return null; var value: any = null;
var value:any = null;
// 记录自身 // 记录自身
Watcher.updating = this; Watcher.updating = this;
// 设置通用属性 // 设置通用属性
...@@ -74,12 +70,9 @@ export class Watcher implements IWatcher ...@@ -74,12 +70,9 @@ export class Watcher implements IWatcher
writable: false writable: false
}); });
// 表达式求值 // 表达式求值
try try {
{
value = this._expFunc.call(this._scope, this._scope); value = this._expFunc.call(this._scope, this._scope);
} } catch (err) {
catch(err)
{
// 输出错误日志 // 输出错误日志
console.warn("表达式求值错误\nerr: " + err.toString() + "\nexp:" + this._exp + ",scope:" + JSON.stringify(this._scope)); console.warn("表达式求值错误\nerr: " + err.toString() + "\nexp:" + this._exp + ",scope:" + JSON.stringify(this._scope));
} }
...@@ -95,20 +88,18 @@ export class Watcher implements IWatcher ...@@ -95,20 +88,18 @@ export class Watcher implements IWatcher
* 当依赖的数据有更新时调用该方法 * 当依赖的数据有更新时调用该方法
* @param extra 可能的额外数据 * @param extra 可能的额外数据
*/ */
public update(extra?:any):void public update(extra?: any): void {
{ if (this._disposed) return;
if(this._disposed) return; var value: any = this.getValue();
var value:any = this.getValue(); if (!Watcher.isEqual(value, this._value)) {
if(!Watcher.isEqual(value, this._value))
{
this._callback && this._callback(value, this._value, extra); this._callback && this._callback(value, this._value, extra);
this._value = Watcher.deepCopy(value); this._value = Watcher.deepCopy(value);
} }
} }
/** 销毁订阅者 */ /** 销毁订阅者 */
public dispose():void public dispose(): void {
{ if (this._disposed) return;
if(this._disposed) return;
this._value = null; this._value = null;
this._target = null; this._target = null;
this._exp = null; this._exp = null;
...@@ -121,8 +112,7 @@ export class Watcher implements IWatcher ...@@ -121,8 +112,7 @@ export class Watcher implements IWatcher
/** /**
* 是否相等,包括基础类型和对象/数组的对比 * 是否相等,包括基础类型和对象/数组的对比
*/ */
private static isEqual(a:any, b:any):boolean private static isEqual(a: any, b: any): boolean {
{
return (a == b || ( return (a == b || (
Watcher.isObject(a) && Watcher.isObject(b) Watcher.isObject(a) && Watcher.isObject(b)
? JSON.stringify(a) == JSON.stringify(b) ? JSON.stringify(a) == JSON.stringify(b)
...@@ -133,23 +123,18 @@ export class Watcher implements IWatcher ...@@ -133,23 +123,18 @@ export class Watcher implements IWatcher
/** /**
* 是否为对象(包括数组、正则等) * 是否为对象(包括数组、正则等)
*/ */
private static isObject(obj:any):boolean private static isObject(obj: any): boolean {
{
return (obj && typeof obj == "object"); return (obj && typeof obj == "object");
} }
/** /**
* 复制对象,若为对象则深度复制 * 复制对象,若为对象则深度复制
*/ */
private static deepCopy(from:any):any private static deepCopy(from: any): any {
{ if (Watcher.isObject(from)) {
if (Watcher.isObject(from))
{
// 复杂类型对象,先字符串化,再对象化 // 复杂类型对象,先字符串化,再对象化
return JSON.parse(JSON.stringify(from)); return JSON.parse(JSON.stringify(from));
} } else {
else
{
// 基本类型对象,直接返回之 // 基本类型对象,直接返回之
return from; return from;
} }
......
/**
* 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);
}
}
}
}
...@@ -2,3 +2,40 @@ ...@@ -2,3 +2,40 @@
* Created by rockyl on 2020-03-02. * 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 @@ ...@@ -4,7 +4,7 @@
import {Stage} from "../2d/display"; import {Stage} from "../2d/display";
import {registerCustomModuleFromConfig, registerScripts, RENDERER_TYPE, setProcessMetaLibs, StageScaleMode} from ".."; 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 {setGlobalContext} from "./behavior-runtime";
import {globalLoader} from "../2d/loader/Loader"; import {globalLoader} from "../2d/loader/Loader";
import {Event} from "../2d/events/Event"; import {Event} from "../2d/events/Event";
......
...@@ -68,6 +68,22 @@ export function getDataByPath(scope, path, throwException?) { ...@@ -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 目标对象 * @param target 目标对象
...@@ -303,6 +319,9 @@ export function instantiateScript(node, ScriptConfig) { ...@@ -303,6 +319,9 @@ export function instantiateScript(node, ScriptConfig) {
const script = node.scripts.add(scriptName, props, disabled); const script = node.scripts.add(scriptName, props, disabled);
} }
export const cmdPrefix = 'z-';
export const cmdOldPrefix = '//z-';
/** /**
* 属性注入 * 属性注入
* @param target * @param target
...@@ -310,8 +329,10 @@ export function instantiateScript(node, ScriptConfig) { ...@@ -310,8 +329,10 @@ export function instantiateScript(node, ScriptConfig) {
*/ */
export function injectProperties(target, source) { export function injectProperties(target, source) {
for (let key in source) { for (let key in source) {
if(!source.hasOwnProperty(cmdPrefix + key)){
propertyParse(key, target, source); propertyParse(key, target, source);
} }
}
return target; 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