Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Z
zeroing-engine
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
劳工
zeroing-engine
Commits
eedc3d22
Commit
eedc3d22
authored
Mar 23, 2020
by
rockyl
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
mvvm实现
parent
43f8406e
Changes
25
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
25 changed files
with
1796 additions
and
723 deletions
+1796
-723
engine.js
debug/engine.js
+832
-193
engine.js.map
debug/engine.js.map
+1
-1
manifest.json
manifest.json
+1
-1
package.json
package.json
+2
-2
px-token.js
px-token.js
+32
-0
Container.ts
src/2d/display/Container.ts
+21
-5
FloatDisplay.ts
src/2d/display/FloatDisplay.ts
+35
-23
Stage.ts
src/2d/display/Stage.ts
+4
-15
CanvasRenderer.ts
src/2d/renderers/CanvasRenderer.ts
+0
-2
WebglRenderer.ts
src/2d/renderers/WebglRenderer.ts
+0
-2
GameStage.ts
src/zeroing/game-warpper/GameStage.ts
+25
-5
Ares.ts
src/zeroing/game-warpper/mvvm/Ares.ts
+0
-128
Commands.ts
src/zeroing/game-warpper/mvvm/Commands.ts
+3
-3
Dep.ts
src/zeroing/game-warpper/mvvm/Dep.ts
+21
-26
Interfaces.ts
src/zeroing/game-warpper/mvvm/Interfaces.ts
+10
-10
Mutator.ts
src/zeroing/game-warpper/mvvm/Mutator.ts
+126
-135
Utils.ts
src/zeroing/game-warpper/mvvm/Utils.ts
+27
-30
Watcher.ts
src/zeroing/game-warpper/mvvm/Watcher.ts
+124
-139
Zri.ts
src/zeroing/game-warpper/mvvm/Zri.ts
+116
-0
ZriCommands.ts
src/zeroing/game-warpper/mvvm/ZriCommands.ts
+248
-0
ZriCompiler.ts
src/zeroing/game-warpper/mvvm/ZriCompiler.ts
+70
-0
index.ts
src/zeroing/game-warpper/mvvm/index.ts
+38
-1
launcher.ts
src/zeroing/launcher.ts
+1
-1
utils.ts
src/zeroing/utils/utils.ts
+22
-1
token.html
token.html
+37
-0
No files found.
debug/engine.js
View file @
eedc3d22
This diff is collapsed.
Click to expand it.
debug/engine.js.map
View file @
eedc3d22
This diff is collapsed.
Click to expand it.
manifest.json
View file @
eedc3d22
{
"id"
:
"engine"
,
"url"
:
"engine.85a610a71df748fd9a6ece34f456a06e8f3f1b63.js"
}
\ No newline at end of file
{
"id"
:
"engine"
,
"url"
:
"engine.210e93fc8ecfcb27da00c77582649b96949d28c3.js"
}
\ No newline at end of file
package.json
View file @
eedc3d22
{
"name"
:
"
aaaa
"
,
"version"
:
"
1.0
.0"
,
"name"
:
"
zeroing-engine
"
,
"version"
:
"
0.1
.0"
,
"description"
:
""
,
"main"
:
"index.js"
,
"types"
:
"index.d.ts"
,
...
...
px-token.js
0 → 100644
View file @
eedc3d22
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'
);
}
}
src/2d/display/Container.ts
View file @
eedc3d22
...
...
@@ -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
...
...
src/2d/display/FloatDisplay.ts
View file @
eedc3d22
...
...
@@ -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
();
}
/**
...
...
src/2d/display/Stage.ts
View file @
eedc3d22
...
...
@@ -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
);
...
...
src/2d/renderers/CanvasRenderer.ts
View file @
eedc3d22
...
...
@@ -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
);
...
...
src/2d/renderers/WebglRenderer.ts
View file @
eedc3d22
...
...
@@ -179,8 +179,6 @@ export class WebglRenderer extends SystemRenderer {
displayObject
.
updateTransform
();
displayObject
.
parent
=
cacheParent
;
displayObject
.
stage
&&
displayObject
.
stage
.
afterUpdateTransform
();
//绑定渲染对象,没有则是默认root
this
.
bindRenderTexture
(
renderTexture
,
transform
);
...
...
src/zeroing/game-warpper/GameStage.ts
View file @
eedc3d22
...
...
@@ -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
;
}
...
...
src/zeroing/game-warpper/mvvm/Ares.ts
deleted
100644 → 0
View file @
43f8406e
/**
* 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
src/zeroing/game-warpper/mvvm/Commands.ts
View file @
eedc3d22
...
...
@@ -2,15 +2,15 @@
* Created by Raykid on 2017/7/19.
*/
import
{
I
Ares
,
Ares
CommandData
}
from
"./Interfaces"
import
{
I
Zri
,
Zri
CommandData
}
from
"./Interfaces"
import
{
runExp
}
from
"./Utils"
export
interface
CommandContext
{
target
:
any
;
scope
:
any
;
entity
:
I
Ares
;
data
:
Ares
CommandData
;
entity
:
I
Zri
;
data
:
Zri
CommandData
;
}
export
interface
Command
...
...
src/zeroing/game-warpper/mvvm/Dep.ts
View file @
eedc3d22
...
...
@@ -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
src/zeroing/game-warpper/mvvm/Interfaces.ts
View file @
eedc3d22
...
...
@@ -7,9 +7,9 @@ export interface Compiler
root
:
any
;
/**
* 初始化编译器
* @param entity
Ares
实例
* @param entity
Zri
实例
*/
init
(
entity
:
I
Ares
):
void
;
init
(
entity
:
I
Zri
):
void
;
/**
* 编译方法
* @param target 要编译的显示节点
...
...
@@ -18,7 +18,7 @@ export interface Compiler
compile
(
target
:
any
,
scope
:
any
):
void
;
}
export
interface
I
Ares
export
interface
I
Zri
{
/** 获取ViewModel */
data
:
any
;
...
...
@@ -39,13 +39,13 @@ export interface IAres
* @param value 属性值,如果属性名合法则会被用来作为表达式的字符串
* @return {CommandData|null} 命令数据,如果不是命令则返回null
*/
parseCommand
(
key
:
string
,
value
:
string
):
Ares
CommandData
;
parseCommand
(
key
:
string
,
value
:
string
):
Zri
CommandData
;
/**
* 测试是否是通用命令
* @param data 命令数据
* @return {boolean} 返回一个布尔值,表示该表达式是否是通用命令
*/
testCommand
(
data
:
Ares
CommandData
):
boolean
;
testCommand
(
data
:
Zri
CommandData
):
boolean
;
/**
* 执行通用命令,如果该表达式是通用命令则直接执行,否则什么都不做
* @param data 命令数据
...
...
@@ -53,12 +53,12 @@ export interface IAres
* @param scope 变量作用域
* @return {boolean} 返回一个布尔值,表示该表达式是否是通用命令
*/
execCommand
(
data
:
Ares
CommandData
,
target
:
any
,
scope
:
any
):
boolean
execCommand
(
data
:
Zri
CommandData
,
target
:
any
,
scope
:
any
):
boolean
}
export
interface
Ares
Options
export
interface
Zri
Options
{
inited
?:(
entity
?:
I
Ares
)
=>
void
;
inited
?:(
entity
?:
I
Zri
)
=>
void
;
}
export
interface
IWatcher
...
...
@@ -82,7 +82,7 @@ export interface WatcherCallback
(
newValue
?:
any
,
oldValue
?:
any
,
extra
?:
any
):
void
;
}
export
interface
Ares
CommandData
export
interface
Zri
CommandData
{
/** 主命令名 */
cmdName
:
string
;
...
...
@@ -92,4 +92,4 @@ export interface AresCommandData
propName
:
string
;
/** 表达式 */
exp
:
string
;
}
\ No newline at end of file
}
src/zeroing/game-warpper/mvvm/Mutator.ts
View file @
eedc3d22
...
...
@@ -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
src/zeroing/game-warpper/mvvm/Utils.ts
View file @
eedc3d22
...
...
@@ -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
src/zeroing/game-warpper/mvvm/Watcher.ts
View file @
eedc3d22
import
{
I
Ares
,
IWatcher
,
WatcherCallback
}
from
"./Interfaces"
;
import
{
I
Zri
,
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
(
"表达式求值错误
\n
err: "
+
err
.
toString
()
+
"
\n
exp:"
+
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
(
"表达式求值错误
\n
err: "
+
err
.
toString
()
+
"
\n
exp:"
+
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
src/zeroing/game-warpper/mvvm/Zri.ts
0 → 100644
View file @
eedc3d22
/**
* 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
;
}
}
src/zeroing/game-warpper/mvvm/ZriCommands.ts
0 → 100644
View file @
eedc3d22
/**
* 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
src/zeroing/game-warpper/mvvm/ZriCompiler.ts
0 → 100644
View file @
eedc3d22
/**
* 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
);
}
}
}
}
src/zeroing/game-warpper/mvvm/index.ts
View file @
eedc3d22
/**
* 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
;
}
src/zeroing/launcher.ts
View file @
eedc3d22
...
...
@@ -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"
;
...
...
src/zeroing/utils/utils.ts
View file @
eedc3d22
...
...
@@ -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
;
...
...
token.html
0 → 100644
View file @
eedc3d22
<!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
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment