Skip welcome & menu and move to editor
Welcome to JS Bin
Load cached copy from
 
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
  <div id="mvc">
    <h1>0</h1>
    <button>+</button>
    <button>-</button>
  </div>
  <div id="mvp">
    <h1>0</h1>
    <button>+</button>
    <button>-</button>
  </div>
  <div id="mvvm">
    <h1>0</h1>
    <button>+</button>
    <button>-</button>
  </div>
  <div id="flux">
    <h1>0</h1>
    <button>+</button>
    <button>-</button>
  </div>
</body>
</html>
 
//MVC
(function mvc() {
  const root = document.getElementById('mvc'),
   view = root.children[0],
   btnAdd = root.children[1],
   btnDec = root.children[2];
  
  const model = () => {
    let value = 0;
    return {
      add: () => {
        value++;
        view.innerText = value;
      },
      dec: () => {
        value--;
        view.innerText = value;
      }
    }
  };
  (function controller() {
    const m = model();
    root.addEventListener('click', (event) => {
      //View -> Controller
      if(event.target === btnAdd) {
        //Controller -> Model
        m.add();
      } else if(event.target === btnDec) {
        //Controller -> Model
        m.dec();
      }
    })
  }());
})();
//MVP
(function mvp() {
  const root = document.getElementById('mvp'),
   view = root.children[0],
   btnAdd = root.children[1],
   btnDec = root.children[2];
  //Model
  class Model {
    constructor(value) {
      this._value = value;
      this.listeners = [];
    }
    addListener(listener) {
      this.listeners.push(listener);
    }
    notifyListener() {
      for (let listener of this.listeners) {
        //Model --> Presenter
        listener(this._value);
      }
    }
    addOne() {
      this._value++;
      this.notifyListener();
    }
    decOne() {
      this._value--;
      this.notifyListener();
    }
  };
  //Presenter
  const presenter = () => {
    const model = new Model(0);
    //Presenter -> View
    model.addListener((value) => view.innerText = value);
    return (todo) => {
      switch(todo) {
        case 'add': {
          //Presenter -> Model
          model.addOne();
          break;
        };
        case 'dec': {
          //Presenter -> Model
          model.decOne();
          break;
        };
      }
    };
  };
  //View
  const pst = presenter();
  root.addEventListener('click', (event) => {
    if(event.target === btnAdd) {
      //view -> presenter
      pst('add')
    } else if(event.target === btnDec) {
      //view -> presenter
      pst('dec')
    }
  });
}());
//MVVM
(function mvvm() {
  const root = document.getElementById('mvvm'),
   view = root.children[0],
   btnAdd = root.children[1],
   btnDec = root.children[2];
  const observe = (view, model, prop) => {
    let old = model[prop];
    Object.defineProperty(model, prop, {
      get: () => old,
      set: (now) => {
        if(now !== old) {
          //ViewModel -> View
          view.innerText = now;
          //ViewModel <-> Model
          old = now;
        }
      }
    });
  };
  const model = {counter: 0};
  const viewModel = (function() {
    observe(view, model, 'counter');
    return {
      add: () => {
        model.counter++;
      },
      dec: () => {
        model.counter--;
      }
    }
  })();
  root.addEventListener('click', (event) => {
    if(event.target === btnAdd) {
      //View -> ViewModel
      viewModel.add();
    } else if(event.target === btnDec) {
      //View -> ViewModel
      viewModel.dec();
    }
  });
})();
//Flux
(function flux() {
  const root = document.getElementById('flux'),
   view = root.children[0],
   btnAdd = root.children[1],
   btnDec = root.children[2];
  //Store -> View
  const render = (view, state) => {
    view.innerText = state;
  };
  //Dispatcher -> Store
  const createStore = (view, reducer) => {
    let state = reducer();
    return (action) => {
      const nowState = reducer(state, action);
      if(nowState !== state) {
        state = nowState;
        render(view, state);
      }
    }
  }
  const reducer = (state = 0, action) => {
    switch(action) {
      case 'ADD': {
        return state+1;
      };
      case 'DEC': {
        return state-1;
      };
      default: {
        return state;
      }
    }
  }
  const store = createStore(view, reducer);
  root.addEventListener('click', (event) => {
    if(event.target === btnAdd) {
      //Action -> Dispatcher
      store('ADD');
    } else if(event.target === btnDec) {
      //Action -> Dispatcher
      store('DEC');
    }
  });
})();
Output

You can jump to the latest bin by adding /latest to your URL

Dismiss x
public
Bin info
Lovin0730pro
0viewers