Skip to content
toshi00ysm edited this page Mar 19, 2014 · 4 revisions

Summary

beez.(MVCR)Managerは内部で生成された各インスタンスをツリー構造で管理します。

また、ツリー構造上で保持するインスタンスにアクセスするためのメソッド群を提供します。

Model, View, Controller, Router毎に Manager が存在します。

Managerの自動remove等の恩恵を受けるために、各インスタンスの生成は対応するManagerを通して行うことが必須です。

ツリー構造管理は、View, Modelのみです。他のManagerは、フラットで管理されています。

管理図

manager/mvcr

セットアップ

Managerを利用する前にかならず、setup()を実行する必要があります。

beez.manager.setup();

Manager extend

beez.Manager内部にある、各Managerはすべて extend 出来ます。

beez.manager.setup({
    model : new beez.manager.Model.extend({...}),
    view : new beez.manager.View.extend({...}),
    controller : new beez.manager.Controller.extend({...}),
    router : new beez.manager.Router.extend({...}),
    css: new beez.manager.CSSManager({...}),
    image: new beez.manager.ImageManager({...})
});

ほとんどの場合で、extend する必要はありません。

使い方

var modelManager = beez.manager.model;
var viewManager = beez.manager.view;
var controllerManager = beez.manager.controller;

modelManager.create('/@', myModel);
viewManager.create('/@', myView);
controllerManager.create('/@', myController);

ModelViewControllerの定義方法等はModel, View, Controllerを参照してください。

ツリー構造によるインスタンス管理

ツリー構造図 jsonpath

Managerは内部で生成したインスタンスをツリー構造で管理し、自動remove等の処理をこの構造に沿って実行します。

例えば、

var viewManager = beez.manager.view;

// Viewのインスタンス作成(以下他のViewも同じ)
var ParentBillView = beez.View.extend('ParentBillView', {
    vidx    : 'bill',
    tagName : 'div',
    events  : { },
    initialize : function initialize() { },
    beforeOnce : function beforeOnce() { },
    before : function before() { },
    render : function render() { },
    after : function after() { },
    afterOnce : function afterOnce() { }
});

var ChildAndyView = beez.View.extend('ChildAndyView', {
    vidx    : 'andy',
    tagName : 'div',
    events  : { },
    initialize : function initialize() { },
    beforeOnce : function beforeOnce() { },
    before : function before() { },
    render : function render() { },
    after : function after() { },
    afterOnce : function afterOnce() { }
});

// `manager`のルートを作成
viewManager.root(RootView);

// ルートの子としてviewを作成
viewManager.create('/@', ParentBillView);
viewManager.create('/@', ParentTriciaView);

// billの子としてviewを作成
viewManager.create('/@/bill', ChildAndyView);
viewManager.create('/@/bill', ChildJordanView);

// triciaの子としてviewを作成
viewManager.create('/@/tricia', ChildMarieView);
viewManager.create('/@/tricia', ChildRobertView);

とした場合、Managerで管理されるViewは、

Root - Bill   - Andy
     |        └ Jordan
     |
     └ Tricia - Marie
              └ Robert

という構造で各インスタンスを管理します。 この状態で、

beez.manager.view.remove('/@/bill');

を行うと、「Bill」とその子要素である「Andy」と「Jordan」のremove()メソッドが順に実行されます。また、それらインスタンスのイベントもすべて開放されます。

結果として、Managerのツリー構造は

Root - Tricia - Marie
              └ Robert

の様に変化します。

使い方

インスタンスの生成

Managerを利用して,それぞれのインスタンス生成を行いツリー構造の管理下に置くには、以下の様にします。

beez.manager.view.create('/@', MyView);

インスタンスの取得

ツリー管理下のインスタンスを取得するには、以下の様にします。

var myView = beez.manager.view.get('/@/myView');

非同期でアクセスするには、

var myView = beez.manager.view.async().get('/@/myView');

の様に、async()の処理を挟んでください。

ViewとModelのManagerが提供するメソッド

root()

ツリー管理上のルートとなるインスタンスを設定します。 ルートを設定しないとその後のmanager関連のメソッドが使用できません.

beez.manager.view.root(MyView);
beez.manager.model.root(MyModel);

create()

ツリー管理下にインスタンスを作成します.

var View = beez.View.extend('view1', {
    vidx    : 'myView',
    tagName : 'div',
    events  : { }
});

var Model = beez.Model.extend('Model1', {
    vidx    : 'myModel',
    urlRoot: 'http://0.0.0.0:1109/api'
});

beez.manager.view.create('/@', View);
beez.manager.model.create('/@', Model);

get()

ツリー管理下のインスタンスを取得します.

var myView = beez.manager.view.get('/@/myView');
var myModel = beez.manager.model.get('/@/myModel');

remove()

ツリー管理下のpathを引数として渡すと、path上のインスタンスと子孫インスタンスを破棄します。

beez.manager.view.remove('/@/myView');
beez.manager.model.remove('/@/myModel');

dispose()

ツリー管理下のインスタンスを全て破棄します.

beez.manager.view.dispose();
beez.manager.model.dispose();

trace()

Managerの管理下にあるインスタンス群を [path:インスタンス] の形のObjectとして返します。 Chromeのデベロッパ ツール等でManagerの状態を確認する際に便利なメソッドです。

beez.manager.view.trace();
beez.manager.model.trace();

Image Manager

HTMLタグ <img> の管理を beez.ImangeManager でまとめて行えます。

目的

スマートフォンなどメモリ制限がある環境では、多数の画像をロードすることでブラウザが落ちるケースがあります。 そういったケースで厳密にメモリを管理する場合に有効な機能になります。

beez.manager.image と new Image() は併用可能です。

機能

  • HTMLImageElement をプーリングし、再利用することが出来ます。
  • HTMLImageElement を一般的なGCのタイミングではなく明示的にGCできるように破棄します。
  • HTMLImageElement をコールバックスタイルでロード出来ます。(複数並列ロード対応)

イメージプーリング

beez.manager.image 経由で作成された HTMLImageElementのインスタンス数を制限することが出来ます。

あわせて、Configuration env/key を参照ください beez.manager.image.pool でプーリングの状態を取得可能です。

明示的な破棄

beez.manager.image で生成した HTMLImageElement には、release()メソッド が追加されていますのでこれを使用して、明示的に破棄してください。

CAUTION: release() を実行せず放置すると、そのままメモリに残り続けGCされません。 使用しなくなったイメージは確実にrelease() を実行してください。

イメージロード

beez.manager.image.load() beez.manager.image.loadOne() という各メソッドを使用することでロード済みの HTMLImageElement を簡単に取得することが出来ます。

// 1画像ロード
beez.manager.image
    .loadOne('http://example.com/image.png', {crossOrigin: 'Anonymous'})
    .then(function ($img, next) {
        console.log($img); // HTMLImageElement
        // remove
        //$img.release();
        next();
    }).error(function (err, next) {
        throw new Error(err);
    })
    .end()
;

// 複数画像ロード
beez.manager.image
    .load(
        ['http://example.com/image1.png', 'http://example.com/image2.png'],
        [{crossOrigin: 'Anonymous'}, {}]
    )
    .then(function ($img, next) {
        for (var i = 0; i < res.res.length; i++) {
            var $img = res.res[i]; // HTMLImageElement
            console.log($img);
        }
        next();
    }).error(function (err, next) {
        throw new Error(err);
    })
    .end()
;

Cross-Origin Resource Sharing (CORS)

beez.manager.imageCORS によるクロスドメインな画像リソースの取得にまつわる諸問題について解決手段を提供しています。

解説

Webブラウザでは、同一出身ポリシー ( same-origin policy; 同一生成元ポリシー とも呼ばれる) によって、クロスドメインによるリソースの取得に制限がかかっています。

この制限によって、クロスドメインリクエストで取得した画像を drawImage を用いて Canvas に描画することができなくなるなどの問題が起こります。

この制限を回避する手段としてCORSW3Cによって勧告され、主なブラウザに既に実装されています。

参考:HTTP access control (CORS) | MDN

しかし、CORS を用いたとしても、全ての問題を解決することができるわけではなく、実情として例えば、drawImage に使用する画像が先立って CSSbackground-image としてロードされていたためにブラウザキャッシュから取得された場合などに、実装上は適切に設定・呼び出されたはずの CORS が有効とならず、結果としてクライアントにエラーが出力されることがあります。

解決方法

CORS を適切に設定し、かつ前述の問題も解決する手段として、beez.manager.image では以下の2つの機能を利用可能です。

  • crossOrigin オプション

    • 'Anonymous' など HTMLImageElementcrossOrigin プロパティとして有効な値を渡します。

    • これより、 CORS によるクロスドメインリクエストを設定・呼び出すことが出来ます。

    • ex)

      // request with CORS setting
      beez.manager.image  
          .loadOne('http://www.example.com/path/to/image.png', {crossOrigin: 'Anonymous'})
          .then(…
      
  • cacheKey , cacheId オプションによるブラウザキャッシュの分離

    • リクエストURLに専用のURLクエリ文字列を設定できます。

    • これより、非 CORS な手段により取得されたリソースとはブラウザキャッシュが分離され、該当リソースが CORS によって適切に取得され、かつエラーなく利用可能であることを担保することが出来ます。

    • cacheKey にはパラメータの field を設定します。(省略可能。デフォルト: _)

    • cacheId にはパラメータの value を設定します。

    • ex1)

      // request for http://www.example.com/path/to/image.png?_=beez
      beez.manager.image  
          .loadOne('http://www.example.com/path/to/image.png', {cacheId: 'beez'})
          .then(…
      
    • ex2)

      // request for http://www.example.com/path/to/image.png?cachekey=beez
      beez.manager.image  
          .loadOne('http://www.example.com/path/to/image.png', {cacheKey: 'cachekey', cacheId: 'beez'})
          .then(…
      

【重要】サーバ側で必要な設定

CORS の適切な設定には、リソースを提供するサーバ側の設定も必要となります。

具体的には、以下が該当リソースのレスポンスヘッダとして付加されている必要があります。

  • Access-Control-Allow-Origin: http://foo.example.com http://bar.example.com http://bar.example.com:8080 >リソースのアクセスを許可する Origin 。ここにアプリケーションを提供している自サーバの Origin が含まれている必要があります。サーバによっては、リクエストの Originヘッダ によって渡された Origin が返されるものもあります。)

また、場合により、以下も付加されている場合があります。

  • Access-Control-Request-Method: GET , POST , OPTIONS … (アクセスを許可するHTTPメソッド※)
  • Access-Control-Allow-Headers: (リクエストに付加することを許可するヘッダ※)
  • Access-Control-Allow-Credentials: (レスポンスに Cookie を含む場合、サーバはこれに true をセットする必要があります)

(※ プリフライトリクエスト によって事前に取得し、利用されます。)

もしサードパーティのサーバへリクエストした際にこれらの設定がなかった場合、そのサーバは CORS によるリソースの取得を許可していないと解釈すべきです。

CSS Manager

CSSを読み込んでいるHTMLタグ <link> の管理は beez.CSSManager で行うことが出来ます。

beez.Controller.css 内部で利用されていますので、直接使用することはあまりありません。

合わせて beez.Controller, Configuration env/key を参照ください

使い方

// ロード

//実際のurlは'http://example.com/styl/bootstrap/bootstrap.min.css'となります
var url = 'styl/bootstrap/bootstrap.min.css';

beez.manager.css
    .async()
    .load(url) // http/https で始まらない文字列の場合は、引数がbeez.config.url.base + url になります
    .then(function() {
        var styles = $('link[rel=stylesheet]');
        var $link = _.any(styles, function (obj) {
            return obj.href.indexOf(url) !== -1;
        });
    })
    .error(function onError(e, next) {
        // timeout .....
    })
    .end()
;


// 削除
beez.manager.css.remove(url);

Base Manager

beez.manager.Base beez.manager.BaseManager を使用することで、 MVCR Managerと同等の機能を新たに作成出来ます。

通常作成するケースはないと思います。利用する場合の具体例はテストコードを参照ください。

Clone this wiki locally