Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!DOCTYPE html>
- <html>
- <head>
- <title>Foo</title>
- <meta charset='utf-8' />
- <meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0' />
- <style type='text/css'>
- div {
- cursor:pointer;
- cursor:hand;
- position:absolute;
- top:0;
- left:0;
- }
- </style>
- <script type='text/javascript'>
- window.onload = function() {
- var s = document.getElementsByTagName('div'), cur = 0, ti;
- if (!s) return;
- function go(n) {
- cur = n;
- var i = 1e3, e = s[n], t;
- document.body.className = e.dataset.bodyclass || '';
- for (var k = 0; k < s.length; k++) s[k].style.display = 'none';
- e.style.display = 'inline';
- e.style.fontSize = i + 'px';
- if (e.firstChild && e.firstChild.nodeName === 'IMG') {
- document.body.style.backgroundImage = 'url(' + e.firstChild.src + ')';
- e.firstChild.style.display = 'none';
- if ('classList' in e) e.classList.add('imageText');
- } else {
- document.body.style.backgroundImage = '';
- document.body.style.backgroundColor = e.style.backgroundColor;
- }
- if (ti !== undefined) window.clearInterval(ti);
- t = parseInt(e.dataset.timeToNext || 0, 10);
- if (t > 0) ti = window.setTimeout(fwd, (t * 1000));
- while (
- e.offsetWidth > window.innerWidth ||
- e.offsetHeight > window.innerHeight) {
- e.style.fontSize = (i -= 2) + 'px';
- if (i < 0) break;
- }
- e.style.marginTop = ((window.innerHeight - e.offsetHeight) / 2) + 'px';
- if (window.location.hash !== n) window.location.hash = n;
- document.title = e.textContent || e.innerText;
- }
- document.onclick = function() { go(++cur % (s.length)); };
- function fwd() { go(Math.min(s.length - 1, ++cur)); }
- function rev() { go(Math.max(0, --cur)); }
- document.onkeydown = function(e) {
- if (e.which === 39 || e.which === 34 || e.which === 40) fwd();
- if (e.which === 37 || e.which === 33 || e.which === 38) rev();
- };
- document.ontouchstart = function(e) {
- var x0 = e.changedTouches[0].pageX;
- document.ontouchend = function(e) {
- var x1 = e.changedTouches[0].pageX;
- if (x1 - x0 < 0) fwd();
- if (x1 - x0 > 0) rev();
- };
- };
- function parse_hash() {
- return Math.max(Math.min(
- s.length - 1,
- parseInt(window.location.hash.substring(1), 10)), 0);
- }
- if (window.location.hash) cur = parse_hash() || cur;
- window.onhashchange = function() {
- var c = parse_hash();
- if (c !== cur) go(c);
- };
- go(cur);
- };
- </script></head><body>
- <div><h2 id="build-fe-apps-the-mac-way">build FE apps the MAC way</h2>
- <h4 id="model-action-component-">model, action, component*</h4>
- <h5 id="-i-just-made-that-up">* i just made that up</h5>
- </div>
- <div><p><em>M</em>odels = API</p>
- </div>
- <div><p><em>A</em>ctions = Flux</p>
- </div>
- <div><p><em>C</em>omponents = React Views</p>
- </div>
- <div><p>Why is this different?</p>
- </div>
- <div><h2 id="mvc-or-mvvm-">MVC (or MVVM):</h2>
- <ul>
- <li>view code in separate files (incl. partials)</li>
- <li>logic in views, too, at times</li>
- <li>fat models</li>
- <li>controllers* tend to contain event code</li>
- </ul>
- </div>
- <div><h2 id="mac-flux-react-">MAC (Flux + React):</h2>
- <ul>
- <li>view and model code are in same place (<em>c</em>omponents)</li>
- <li>events are <em>separate</em>, <em>one-way</em>, and <em>queueable</em></li>
- <li>server (request-driven) and UI (user-driven) events are in one place</li>
- </ul>
- </div>
- <div><h1 id="actions">Actions</h1>
- <ul>
- <li>Dispatched by, shockingly, a dispatcher</li>
- <li>(usually EventEmitter subclass)</li>
- </ul>
- </div>
- <div><h1 id="components">Components</h1>
- <ul>
- <li>View code in <code>render()</code></li>
- <li>props as <code>this.props</code> (typesafe)</li>
- <li>view logic in local functions</li>
- </ul>
- </div>
- <div><h1 id="models">Models</h1>
- <ul>
- <li>Event driven too!</li>
- <li>Loading locally? <code>POSTS_LOADED_EVENT</code></li>
- <li>Loading via JSON request? <code>POSTS_LOADED_EVENT</code></li>
- </ul>
- </div>
- <div><h2 id="for-example-post-component-">For example - Post Component:</h2>
- <pre><code class="lang-javascript">Post = React.createClass({
- render: function() {
- return <p className="post"></p>;
- }
- });
- </code></pre>
- </div>
- <div><h2 id="blank-post-logic">Blank post logic</h2>
- <pre><code class="lang-javascript">...
- body: function() {
- if (this.text && this.text.length > 0) {
- return this.text;
- } else {
- return "No content in this post.";
- }
- },
- render: function() {
- return (
- <p className="post">
- {this.body()}
- </p>
- );
- }
- ...
- </code></pre>
- </div>
- <div><h3 id="one-more-piece-">One more piece!</h3>
- <h1 id="stores">Stores</h1>
- </div>
- <div><h2 id="poststore">PostStore</h2>
- <pre><code class="lang-javascript">// PostStore.js
- var _posts = [];
- var PostStore = assign({}, EventEmitter.prototype, {
- emitChange: function() {
- this.emit(CHANGE_EVENT);
- },
- addChangeListener: function(callback) {
- this.on(CHANGE_EVENT, callback);
- },
- removeChangeListener: function(callback) {
- this.removeListener(CHANGE_EVENT, callback);
- }
- });
- ...
- </code></pre>
- </div>
- <div><h2 id="poststore">PostStore</h2>
- <pre><code class="lang-javascript">// Farther down in PostStore.js
- var token = PostStore.dispatchToken;
- token = Dispatcher.register(function(action) {
- switch (action.type) {
- // ...
- case ActionTypes.POST_CHANGED:
- PostStore.updatePost(action.post);
- Dispatcher.waitFor([OtherStore.dispatchToken]);
- PostStore.emitChange();
- break;
- }
- });
- </code></pre>
- </div>
- <div><h1 id="in-summary">In Summary</h1>
- <p>UI/Requests <em>create</em> Actions <em>in</em> Dispatcher, <em>which calls</em> Stores. Stores <em>trigger</em> Components.</p>
- </div>
- <div><h1 id="how-to-test">How to Test</h1>
- <p>Just add synthetic events to your dispatcher. Then, unit test all your Stores, Components, etc.</p>
- </div>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement