├── README.md ├── app ├── lib │ ├── API.js │ ├── app.js │ └── router.js └── main.js └── index.html /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |

🍦 🍦 Vanilla JS 🍦 🍦

5 |

with CJ R.

6 |
7 | 8 | --- 9 | 10 | # M.V.C. 11 | 12 | --- 13 | 14 | ## We will need: 15 | * App 16 | * Component 17 | * model 18 | * view 19 | * controller 20 | * Router 21 | * API 22 | 23 | --- 24 | 25 | 26 | 27 | --- 28 | 29 | # CODE 30 | 31 | --- 32 | 33 | 34 | 35 |
36 |

As a lonely dog, I want to see a list of all of the dogs that are available so that I can see my dating options.

37 |
38 | 39 | --- 40 | 41 | 42 | 43 | --- 44 | 45 | 46 | 47 | --- 48 | 49 | 50 | 51 |
52 |

As a lonely dog, I want to be able to link to a specific dog so that I can share my favorite dogs with my friends.

53 |
54 | 55 | --- 56 | 57 | 58 | 59 | --- 60 | 61 | 62 | 63 | --- 64 | 65 | 66 | 67 |
68 | 69 | 70 | 71 |
72 | 73 | --- 74 | 75 | 76 | 77 | --- 78 | 79 | ## We made: 80 | * App 81 | * Component 82 | * model 83 | * view 84 | * controller 85 | * Router 86 | * API 87 | 88 | ---- 89 | 90 | ## App 91 | * addComponent 92 | * showComponent 93 | * updateView 94 | 95 | ---- 96 | 97 | ## Component 98 | * name 99 | * model 100 | * view 101 | * controller 102 | 103 | ---- 104 | 105 | ## Router 106 | * addRoute 107 | * onHashChange 108 | 109 | ---- 110 | 111 | ## API 112 | * getDogs 113 | * getDog 114 | 115 | --- 116 | 117 | # Conclusion 118 | 119 | --- 120 | 121 | # Should you do this in production? 122 | 123 | ---- 124 | 125 | 126 | 127 | ---- 128 | 129 | # Frameworks Exist For A Reason 130 | 131 | --- 132 | 133 | # Should you do this for fun? 134 | 135 | ---- 136 | 137 | 138 | 139 | ---- 140 | 141 | ### Answer the question: 142 | ### If you were to implement a library/framework/API feature from scratch, how would you do it? 143 | 144 | --- 145 | 146 | ## Links/Plugs 147 | 148 | * This code is here: [https://git.io/vanilla-js](https://git.io/vanilla-js) 149 | * [c.js - A simple MVC framework that no-one should use](https://github.com/w3cj/c.js) 150 | * [August 10th - Develop Denver: An OverVue of Vue.js](https://developdenver.org/talks/72) 151 | * Organizer of the [Vue.js Meetup](https://www.meetup.com/Denver-Vue-js-Meetup/) 152 | * Looking for full talk/lightning talk speakers for August 28th and September 25th 153 | 154 | --- 155 | 156 | 157 | 158 | --- 159 | -------------------------------------------------------------------------------- /app/lib/API.js: -------------------------------------------------------------------------------- 1 | class API { 2 | constructor() { 3 | this.API_URL = 'https://barkwire-api.herokuapp.com/dogs'; 4 | } 5 | getDogs() { 6 | return fetch(this.API_URL) 7 | .then(res => res.json()); 8 | } 9 | getDog(id) { 10 | return fetch(`${this.API_URL}/${id}`) 11 | .then(res => res.json()); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/lib/app.js: -------------------------------------------------------------------------------- 1 | class App { 2 | constructor(selector) { 3 | this.appElement = document.querySelector(selector); 4 | this.componentsByName = {}; 5 | } 6 | addComponent(component) { 7 | this.componentsByName[component.name] = component; 8 | component.model = this.proxify(component.model); 9 | } 10 | showComponent(name) { 11 | this.currentComponent = this.componentsByName[name]; 12 | 13 | if(this.currentComponent) { 14 | this.currentComponent.controller(this.currentComponent.model); 15 | } 16 | this.updateView(); 17 | } 18 | updateView() { 19 | if(this.currentComponent) { 20 | this.appElement.innerHTML = this.currentComponent.view(this.currentComponent.model); 21 | } else { 22 | this.appElement.innerHTML = '

Not Found

'; 23 | } 24 | } 25 | proxify(model) { 26 | const self = this; 27 | return new Proxy(model, { 28 | set(target, property, value) { 29 | console.log('Changing', property, 'from', target[property], 'to', value); 30 | target[property] = value; 31 | self.updateView(); 32 | return true; 33 | } 34 | }); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/lib/router.js: -------------------------------------------------------------------------------- 1 | class Router { 2 | constructor(app) { 3 | this.app = app; 4 | this.routes = []; 5 | this.hashChange = this.hashChange.bind(this); 6 | 7 | window.addEventListener('hashchange', this.hashChange); 8 | window.addEventListener('DOMContentLoaded', this.hashChange); 9 | } 10 | addRoute(name, url) { 11 | this.routes.push({ 12 | name, 13 | url 14 | }); 15 | } 16 | hashChange() { 17 | const hash = window.location.hash; 18 | const route = this.routes.filter(route => hash.match(new RegExp(route.url)))[0]; 19 | 20 | if(route) { 21 | this.params = new RegExp(route.url).exec(hash); 22 | this.app.showComponent(route.name); 23 | } else { 24 | this.app.showComponent(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/main.js: -------------------------------------------------------------------------------- 1 | const app = new App('#app'); 2 | const api = new API(); 3 | 4 | const dogTemplate = (dog) => ` 5 |
6 | 7 |

${dog.name}

8 |
9 |
10 | ${dog.name} 11 |
${dog.imageCaption}
12 |
13 |

${dog.description}

14 |
15 |
16 |
17 | `; 18 | 19 | app.addComponent({ 20 | name: 'dogs', 21 | model: { 22 | dogs: [] 23 | }, 24 | view(model) { 25 | const dogsHTML = model.dogs.reduce((html, dog) => html + `
  • ${dogTemplate(dog)}
  • `, '') 26 | return ` 27 | 30 | `; 31 | }, 32 | controller(model) { 33 | api 34 | .getDogs() 35 | .then(result => { 36 | model.dogs = result.dogs; 37 | }); 38 | } 39 | }); 40 | 41 | app.addComponent({ 42 | name: 'dog', 43 | model: { 44 | dog: {} 45 | }, 46 | view(model) { 47 | return dogTemplate(model.dog); 48 | }, 49 | controller(model) { 50 | api 51 | .getDog(router.params[1]) 52 | .then(result => { 53 | model.dog = result.dog; 54 | }); 55 | } 56 | }); 57 | 58 | const router = new Router(app); 59 | router.addRoute('dogs', '^#/dogs$'); 60 | router.addRoute('dog', '^#/dogs/([0-9]*)$'); 61 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BarkWire 6 | 7 | 8 | 9 |
    10 |

    BarkWire

    11 |
    12 |
    13 |
    14 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | --------------------------------------------------------------------------------