LoginSignup
8
10

More than 5 years have passed since last update.

JqueryでFlux(っぽいもの)

Posted at

をつくるとどうなるのかと思い作ってみた。
jqueryからいきなりreact+flux+es6に行くとあらゆるものが変わってしまうので、
こういう試しも比較する上で面白いのではないかと。

つくるものの要件

クッキークリッカー的にカウンターが

  • ボタンをクリックしたらカウンター+1
  • 1秒ごとに+1
  • カウンターの値を30消費してlevel2にアップデートできる
  • level2だとカウンターが2づつ増える

スクショ

jquery-flux.png

HTML

htmlは以下のような感じ
jqueryとオブジェクトの更新に_.extend()を使いたいのでunderscore.jsを読み込む

index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>JQueryでFlux</title>
</head>
<body>
  <div class="wrapper">
    <div><label>Cookie: </label><span id="value">0</span></div>
    <div>
      <button id="button">Click!</button>
    </div>
    <div>
      level: <span id="level">1</span>
    </div>
    <div>クッキーを30使いアップデートする <button id="update">Update!</button></div>
  </div>
  <script src="https://code.jquery.com/jquery-3.1.0.min.js" integrity="sha256-cCueBR6CsyA4/9szpPfrX3s49M9vUU5BgtiJj06wt/s=" crossorigin="anonymous"></script>
  <script src='https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js'></script>
  <script src='/js/script.js'></script>
</body>
</html>

非Fluxの雑な例

script.js
$(function() {
  $('#button').on('click', function(e) {
    increaseCount();
  });
  setInterval(function() {
    increaseCount();
  }, 1000);
  function increaseCount() {
    var newValue = parseInt($('#value').html(), 10) + 1;
    $('#value').html(newValue);
  }
});

Flux

Fluxの場合
上記との違い

storeを定義する。

つまりDOMに状態を持たせない。
さらに言うとDOMから値を取得しない。

ViewはActionを発行する

適当にJqueryのカスタムイベントを発行する

Actionを受け取る

Actionを受け取り、storeを更新。
更新したら必ずstoreのchangeイベントを発行する。

Viewを更新する。

storeのchangeイベントをトリガーにhtmlを書き換える

script.js
$(function() {
  // Store定義
  var store = {
    cookie: 0,
    level: 1
  };
  // Storeの値は必ずこの関数から取得
  function getStore(key) {
    return  store[key];
  }
  // Storeの値は必ずこの関数を通して更新
  function updateStore(newState) {
    // 現在のStoreに新しい値をマージした新オブジェクトを作成、代入する
    store = _.extend({}, store, newState);
    // update時にchangeイベントを発行する。changeイベントを発行するのはここのみ
    $(window).trigger('store:change');
  }

  // ViewはStore(store:changeイベント)を購読する Viewの更新はここでのみ行う
  $(window).on('store:change', function() {
    $('#value').html(getStore('cookie'));
    $('#level').html(getStore('level'));
  });
  // ここまでがフレームワークと言えるものかもしれない

  // View(html)からActionの発行(Actionをtriggerするのがこのブロックの仕事)
  $('#button').on('click', function() {
    $(window).trigger('action:increase');
  });
  setInterval(function() {
    $(window).trigger('action:increase');
  }, 1000);

  $('#update').on('click', function() {
    $(window).trigger('action:requestUpdate');
  });

  // Actionを受け取ってupdateStore()するのがこのブロックの仕事
  $(window).on('action:increase', function() {
    increaseCount();
  });
  function increaseCount() {
    var amount = 1;
    if(getStore('level') === 2) {
      amount = 2;
    }
    updateStore({cookie: getStore('cookie') + amount});
  }
  function decreaseCount(amount) {
    updateStore({cookie: getStore('cookie') - amount});
  }

  $(window).on('action:requestUpdate', function() {
    if(getStore('level') === 1 && getStore('cookie') > 30) {
      decreaseCount(30);
      increaseLevel();
    }
  });
  function increaseLevel() {
    updateStore({level: getStore('level') + 1});
  }
});
8
10
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
8
10