From cfde85b77385a3b6043c4b3e909831d2fc63e3a9 Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Wed, 24 Jul 2019 19:26:25 +0800 Subject: [PATCH] mvvm --- js-framework/demo.ts | 61 ++++++++++++++++++++++++------------- js-framework/src/vm/mvvm.ts | 36 ++++++++++++++-------- 2 files changed, 64 insertions(+), 33 deletions(-) diff --git a/js-framework/demo.ts b/js-framework/demo.ts index 65e25c2d..2f56af94 100644 --- a/js-framework/demo.ts +++ b/js-framework/demo.ts @@ -1,52 +1,71 @@ -import { VMPanel, View, ViewModel, WRAP_CONTENT, Gravity, Mutable, NativeCall, Text, Color, VLayout, Panel, log, logw, loge, Group, Stack, } from "./index" +import { ViewHolder, VMPanel, View, ViewModel, WRAP_CONTENT, Gravity, Mutable, NativeCall, Text, Color, VLayout, Panel, log, logw, loge, Group, Stack, } from "./index" + interface CountModel { count: number add: () => void } -class CounterVM extends ViewModel { - build(root: Group, model: CountModel) { +class CounterView extends ViewHolder { + number = new Text + counter = new Text + build(root: Group) { const vlayout = new VLayout - const number = new Text - number.textSize = 40 - number.layoutConfig = { + this.number.textSize = 40 + this.number.layoutConfig = { alignment: new Gravity().center() } - const counter = new Text - counter.text = "点击计数" - counter.textSize = 20 + this.counter = new Text + this.counter.text = "点击计数" + this.counter.textSize = 20 vlayout.space = 20 vlayout.layoutConfig = { alignment: new Gravity().center() } - vlayout.addChild(number) - vlayout.addChild(counter) + vlayout.addChild(this.number) + vlayout.addChild(this.counter) root.addChild(vlayout) + } - this.bind((data) => { - loge('bind:', data) - number.text = data.count.toString() - counter.onClick = data.add - }) + setNumber(n: number) { + this.number.text = n.toString() + } + setCounter(v: Function) { + this.counter.onClick = v + } +} + +class CounterVM extends ViewModel { + binding(v: CounterView, model: CountModel): void { + v.setCounter(model.add) + v.setNumber(model.count) } } @Entry -class MyPage extends VMPanel{ +class MyPage extends VMPanel{ - createVM(): ViewModel { - return new CounterVM({ + getVMClass() { + return CounterVM + } + + getModel() { + return { count: 0, add: function () { this.count++ - } - }) + }, + } } + getViewHolder() { + return new CounterView + } + + @NativeCall log() { log("Hello.HEGO") diff --git a/js-framework/src/vm/mvvm.ts b/js-framework/src/vm/mvvm.ts index 1d60da82..1a7c8654 100644 --- a/js-framework/src/vm/mvvm.ts +++ b/js-framework/src/vm/mvvm.ts @@ -1,7 +1,5 @@ import { View, Group } from "../ui/view"; import { Panel } from "../ui/panel"; -import { loge } from "../util/log"; - function listen(obj: T, listener: Function): T { return new Proxy(obj, { @@ -26,38 +24,52 @@ function listen(obj: T, listener: Function): T { }) } -export abstract class VMPanel extends Panel { +export abstract class ViewHolder { + abstract build(root: Group): void +} - private vm: ViewModel = this.createVM() +export abstract class VMPanel extends Panel { - abstract createVM(): ViewModel + private vm: ViewModel = new (this.getVMClass())(this.getModel(), this.getViewHolder()) + + abstract getVMClass(): new (m: M, v: V) => ViewModel - getModel() { - return this.vm.getModel() - } + abstract getModel(): M + + abstract getViewHolder(): V getVM() { return this.vm } build(root: Group): void { - this.vm.build(root, this.vm.getModel()) + this.vm.build(root) } } -export abstract class ViewModel { +export abstract class ViewModel { private model: M private listeners: Function[] = [] - constructor(obj: M) { + private viewHolder: V + + constructor(obj: M, v: V) { this.model = listen(obj, () => { this.listeners.forEach(e => { Reflect.apply(e, this.model, [this.model]) }) }) + this.viewHolder = v } - abstract build(root: Group, model: M): void + build(root: Group) { + this.viewHolder.build(root) + this.bind((data: M) => { + this.binding(this.viewHolder, this.model) + }) + } + + abstract binding(v: V, model: M): void getModel() { return this.model