LoginSignup
1
1

More than 5 years have passed since last update.

Superfineを使用したMVCの例

Last updated at Posted at 2018-07-09
fineapple.js
import * as superfine from 'https://unpkg.com/superfine?module';

// MVC概要
// 
// app = Controllers(Model,View)
// 
// Model       : アプリの概念。プラットフォーム入出力のないオブジェクト。
// View        : アプリのGUI。ビューの描画を計算する。
// Controllers : アプリの型。メソッドがアプリの制御機能。
// app         : アプリの実体。Controllersのインスタンス。

class Controllers {
  // アプリに必須な属性を設定・保持・管理。
  constructor(model, container, calculator) {
    this.model = model;
    this.view = {
      container: container,
      calculator: calculator,
    };
  }
  // superfineのマウントポイント設定。ビューレンダー(this.view.render)が生成される。
  mount(node) {
    let v = this.view;
    v.node = node;
    v.render = () => {
      v.node = superfine.patch(v.node, v.calculator(this), v.container);
      return this;
    }
    return this;
  }
  // マウントポイント設定とビュー描画の一連の流れ。
  launch() {
    return this.mount().view.render();
  }
  // おまけ。デバッグに便利なようメソッドチェーンで書ける。
  info() {
    console.info(...arguments, this);
    return this;
  }
}

// エクスポート時のユニーク名。
export const Fineapple = Controllers;

// リサイクルエクスポート。
export const h = superfine.h;

// htmlタグのclass属性をJavaScript表現したものを文字列へ変換するユーティリティ。
export const classJoin = o => o.join(' ');
export const classConcat = (a, b) => a.split(' ').concat(b).join(' ');

// htmlタグのstyle属性をJavaScript表現したものを文字列へ変換するユーティリティ。
export const styleJoin = o => Object.keys(o).map(key=>`${key}:${o[key]};`).join('');
export const styleConcat = (a, b) => a + styleJoin(b);

// var foo = ['aaa','bbb']
// var bar = ['ccc','ddd']
// console.assert(classJoin(foo) === 'aaa bbb')
// console.assert(classConcat(classJoin(foo), bar) === 'aaa bbb ccc ddd')

// var foo = {a:'aaa', b:'bbb'}
// var bar = {c:'ccc', d:'ddd'}
// console.assert(styleJoin(foo) === 'a:aaa;b:bbb;')
// console.assert(styleConcat(styleJoin(foo), bar) === 'a:aaa;b:bbb;c:ccc;d:ddd;')

// var foo = {border:'1px solid red', 'font-size':'2em'}
// console.assert(styleJoin(foo) === 'border:1px solid red;font-size:2em;')
counter.js
import { h, Fineapple } from './fineapple.js';

export class Model {
  constructor(count=0) { this.count=count; }
  add(by=1) { this.count+=by; return this; }
  sub(by=1) { this.count-=by; return this; }
}

export class Controllers extends Fineapple {
  add() {
    this.model.add();
    return this.view.render();
  }
  sub() {
    this.model.sub();
    return this.view.render();
  }
}

export class Components {
  display(app, attributes) {
    return h('h2', attributes, app.model.count);
  }

  addButton(app, attributes, children='+') {
    let handlers = {
      onclick: () => app.add(),
    }
    let properties = Object.assign(handlers, attributes);
    return h('button', properties, children);
  }

  subButton(app, attributes, children='-') {
    let handlers = {
      onclick: () => app.sub(),
    }
    let properties = Object.assign(handlers, attributes);
    return h('button', properties, children);
  }
}

export function view() {
  let c = new Components();
  return app => 
    h('div', {class:'counter'}, [
      c.display(app),
      c.subButton(app),
      c.addButton(app),
    ])
}
app.js
import { h } from './fineapple.js';
import * as Counter from './counter.js';


const app = new Counter.Controllers(new Counter.Model(), document.body, app =>
  h('div', {}, [
    h('h1', {}, 'Fineapple: for building web app.'),
    h('div', {class:'counter'}, [
      h('h2', {}, app.model.count),
      h('button', { onclick: () => app.sub().info('sub',app.model) }, '-'),
      h('button', { onclick: () => app.add().info('add',app.model) }, '+'),
    ]),
  ])
);

app.launch().info('launch');


// const c = new Counter.Components();
//
// new Counter.Controllers(new Counter.Model(), document.body, app =>
//   h('div', {}, [
//     h('h1', {}, 'Fineapple: for building web app.'),
//     h('div', {class:'counter'}, [
//       c.display(app),
//       c.subButton(app),
//       c.addButton(app),
//     ]),
//   ])
// )
// .launch().info('launch');


// new Counter.Controllers(new Counter.Model(), document.body, Counter.view()).launch();

demo

1
1
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
1
1