diff --git a/js-framework/demo.ts b/js-framework/demo.ts index 1fe4c7d2..47318bf1 100644 --- a/js-framework/demo.ts +++ b/js-framework/demo.ts @@ -100,9 +100,14 @@ enum State { class SnakeModel { state = State.idel direction = Direction.left - width = 10 - height = 10 + width: number + height: number + + constructor(w: number, h: number) { + this.width = w + this.height = h + } food = { x: 0, y: 0 } head: SnakeNode = { @@ -192,6 +197,7 @@ class SnakeModel { } class SnakeView extends ViewHolder { + panel: Stack = new Stack build(root: Group): void { root.bgColor = Color.parse('#000000') @@ -205,23 +211,66 @@ class SnakeView extends ViewHolder { top: 20 } } as StackConfig + root.addChild(this.panel) root.addChild(title) } } class SnakeVM extends ViewModel{ - binding(v: SnakeView, model: SnakeModel) { + timerId?: any + start() { + if (this.timerId !== undefined) { + clearInterval(this.timerId) + } + this.timerId = setInterval(() => { + this.getModel().step() + }, 1000) + } + + stop() { + if (this.timerId !== undefined) { + clearInterval(this.timerId) + this.timerId = undefined + } + } + + binding(v: SnakeView, model: SnakeModel) { + v.panel.width = model.width * 10 + v.panel.height = model.height * 10 + let node: SnakeNode | undefined = model.head + let nodes: SnakeNode[] = [] + while (node != undefined) { + nodes.push(node) + node = node.next + } + nodes.forEach((e, index) => { + let item = v.panel.children[index] + if (item) { + item.x = e.x * 10 + item.height = e.y * 10 + } else { + item = new Stack + item.bgColor = Color.parse('#0000ff') + item.width = item.height = 10 + v.panel.addChild(item) + } + }) + if (nodes.length < v.panel.children.length) { + v.panel.children.length = nodes.length + } } } @Entry class SnakePanel extends VMPanel{ + getVMClass() { return SnakeVM } + getModel() { - return new SnakeModel + return new SnakeModel(this.getRootView().width / 10, this.getRootView().width / 10) } getViewHolder() { diff --git a/js-framework/src/ui/view.ts b/js-framework/src/ui/view.ts index af7ffc48..0466eb06 100644 --- a/js-framework/src/ui/view.ts +++ b/js-framework/src/ui/view.ts @@ -69,7 +69,7 @@ export abstract class View implements Modeling { set: (target, p, v, receiver) => { const oldV = Reflect.get(target, p, receiver) const ret = Reflect.set(target, p, v, receiver) - if (Reflect.getMetadata(p, target)) { + if (Reflect.getMetadata(p, target) && oldV !== v) { receiver.onPropertyChanged(p.toString(), oldV, v) } return ret @@ -209,7 +209,7 @@ export interface LinearConfig extends Config { export abstract class Group extends View { @Property - children: View[] = new Proxy([], { + readonly children: View[] = new Proxy([], { set: (target, index, value) => { if (index === 'length') { this.getDirtyChildrenModel().length = value as number @@ -231,6 +231,7 @@ export abstract class Group extends View { addChild(view: View) { this.children.push(view) } + clean() { this.children.forEach(e => { e.clean() }) super.clean() diff --git a/js-framework/src/vm/mvvm.ts b/js-framework/src/vm/mvvm.ts index d0e2f2e2..78eea0ce 100644 --- a/js-framework/src/vm/mvvm.ts +++ b/js-framework/src/vm/mvvm.ts @@ -30,7 +30,7 @@ export abstract class ViewHolder { export abstract class VMPanel extends Panel { - private vm: ViewModel = new (this.getVMClass())(this.getModel(), this.getViewHolder()) + private vm?: ViewModel abstract getVMClass(): new (m: M, v: V) => ViewModel @@ -44,6 +44,7 @@ export abstract class VMPanel extends Pa } build(root: Group): void { + this.vm = new (this.getVMClass())(this.getModel(), this.getViewHolder()) this.vm.build(root) } }