7
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

javascriptでmvcでreactiveなコードを外部ライブラリ使わずガチ組みしてみた

Last updated at Posted at 2015-01-27

という訳でTypeScriptでReactiveなコード書いてみました。

細かい実装は下記を見ていただければと
https://github.com/ts020/reactive_template
詳しくは、readme.htmlをご覧ください。
ちなみに、仮想DOMは実装しんどかったので今回は見送りました。

下記を重視して作ってみました

. Modelの値が変更されたときにviewに通知される事
. 通知にあわせて、自動的に再描画される事
. 値が変更されているプロパティに関係する対象だけが再描画される事
. Canvasやwebglでも使える事

MVCです

Controller

typescript
///<reference path="Model.ts" />
///<reference path="View.ts" />
module app {
    export class Controller {
        view:View;
        model:Model;

        constructor(initialData:any=null) {
            this.model = new Model(initialData);
            this.view = new View(this.model);
        }

        showName(label:string):void {
            this.model.setName(label);
        }
    }
}

Model

setPropertyを実行すると、値に変更が有った場合に[change]イベントが16ミリ秒後実行されます。
遅延実行している理由は、描画とロジック処理負荷を分けるためデス。
また、[change]イベント送出までは、プロパティをどれだけいじっても変更通知される事はないです。

Typescript
///<reference path="olib/reactive/ModelBase.ts" />
module app {
    export class Model extends olib.reactive.ModelBase {
        protected init(initialData:any = null):void {
            this.name = initialData ? initialData.name || "" : "";
        }

        setName(label:string):void {
            this.name = label;
        }

        set name(value:string) {
            this.setProperty("name",value);
        }

        get name():string {
            return this.getProperty("name");
        }

    }
}

View

model値が変更されるとview.updateが実行されます。
updateの中に描画処理をまとめる事で描画負荷のコントロールを行いやすくします。
bindでプロパティに変更が有るときだけ処理が実行されます。
差分のみの変更をするとこで描画負荷を下げます。

Typescript
///<reference path="olib/reactive/ViewBase.ts" />
///<reference path="Model.ts" />
module app {
    export class View extends olib.reactive.ViewBase<Model> {
        nameLabel:HTMLElement;
        protected init():void {
            this.nameLabel = <HTMLElement>document.querySelector("#nameLabel");
            this.update();
        }

        update():void {
            this.bind("name", (value)=>{
                this.nameLabel.innerHTML = value;
            });
        }
    }
}

HTML

html
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <link href='http://fonts.googleapis.com/css?family=Open+Sans+Condensed:700,300' rel='stylesheet' type='text/css'>
    <link rel="stylesheet" type="text/css" href="resource/style.css">
</head>
<body>
<h1>SPA REACTIVE MVC TEMPLATE</h1>
    <div id="nameLabel"></div>
    <input type="text" id="nameInput" onkeyup="controller.showName(this.value)" />
</div>
</body>
<script type="text/javascript" src="resource/App.js"></script>
<script type="text/javascript">
    var controller = new app.Controller({
        name : "Hello World"
    });
</script>
</html>

こんな感じです。
テキストを入力すると、文字がかわります

サンプルにおけるリアクティブな流れ。

スクリーンショット 2015-01-27 20.01.14.png

7
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?