├── .github └── FUNDING.yml ├── .gitignore ├── LICENSE ├── README.md ├── docs └── index.html ├── ex ├── 01.md ├── 02.md ├── 03.md ├── 04.md ├── 05.md ├── 06.md ├── 07.md ├── 08.md ├── 09.md ├── 10.md ├── 11.md ├── 12.md ├── 13.md ├── 14.md └── 15.md ├── img ├── babel.gif ├── build.gif ├── cli.gif ├── components.png ├── computed.gif ├── devtools.gif ├── directives.gif ├── eslint.gif ├── gs.gif ├── loading.gif ├── logo-emoji.png ├── ls-al.png ├── my-app.png ├── networking.gif ├── plugin.gif ├── reactivity.gif ├── serve.gif ├── sfc.png ├── two-way.gif ├── vs-code-dist.png ├── vs-code-project.png ├── vue-coins.png └── watcher.gif ├── package.json └── slides ├── Component System.pdf ├── Declarative Rendering.pdf └── vue-principiantes.pdf /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: ianaya89 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.DS_Store 3 | *.log 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 @ianaya89 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Workshop de Vue.js Para Principantes 2 | 3 | > 👨‍🏫👩‍🏫🇪🇸 Vue.js es una de las mejores alternativas en el mundo MV* peleando con gigantes de la industria como React y Angular. En este workshop vas a aprender la simpleza y el poder de este framework que combina lo mejor de ambos mundos. Te voy a enseñar las bases del framework progresivo que te permite crear aplicaciones simples o complejas de manera muy fácil. 4 | 5 | > 🚨 Esta es una nueva version del workshop, podes mirar la version anterior en este [link](https://github.com/ianaya89/workshop-vuejs/tree/v1.0.0). 6 | 7 | 8 |

9 | vue 10 |

11 | 12 | ## Materiales 13 | * 📽 [Slides](https://github.com/ianaya89/workshop-vuejs/tree/master/slides) 14 | * 💸 [Proyecto vue-coins](https://github.com/ianaya89/vue-coins) 15 | * ✏ [Colección Codepen](https://codepen.io/collection/nVzyOE) 16 | * 🔌 [Plugin CLI](https://github.com/ianaya89/vue-cli-plugin-workshop) (Usado en el Proyecto) 17 | * 📹 [Version en Video](https://www.youtube.com/watch?v=Nl9goroCCzg) ([asaditojs](https://twitter.com/asaditojs)) 18 | 19 | ## Temas 20 | 21 | 1. Introducción a [Vue.js](https://vuejs.org/) 22 | 2. Generar aplicaciones con [vue-cli](https://github.com/vuejs/vue-cli) 23 | 3. Breve introducción a [Babel](http://babeljs.io/) y [Webpack](https://webpack.js.org/) 24 | 4. Manipulación del DOM 25 | 5. Data Binding 26 | 6. Sistema de Componentes 27 | 7. Estructurar Aplicaciones 28 | 29 | ## Requisitos 30 | 31 | * Cualquier editor de texto (Recomiendo [Visual Studio Code](https://code.visualstudio.com/) con el plugin [Vetur](https://marketplace.visualstudio.com/items?itemName=octref.vetur)) 32 | * [Node.js](https://nodejs.org/en/) (y npm) 33 | * Conocimiento basico de JavaScript (`for`, `if`, `object`, `array`, `functions` y `ajax`) 34 | * Conocimiento basico de HTML y CSS 35 | * No se requiere conocimiento de ES2015 pero se recomiendan estos links: 36 | * [Method Definitions](https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/funciónes/Method_definitions) 37 | * [Shorthand Properties](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Object_initializer) 38 | * [Template Strings](https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/template_strings) 39 | * [Promises](https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Promise) 40 | * *[Vue Dev Tools](https://github.com/vuejs/vue-devtools)* 41 | 42 | ## Ejercicios 43 | 1. 📚 [Introduccion a Vue.js](https://github.com/ianaya89/workshop-vuejs/blob/master/ex/01.md) 44 | 2. 🎬 *[Directives](https://github.com/ianaya89/workshop-vuejs/blob/master/ex/02.md)* 45 | 3. 🔁 📅 *[Two-Way Data Binding y Eventos](https://github.com/ianaya89/workshop-vuejs/blob/master/ex/03.md)* 46 | 4. 📦 [Componentes](https://github.com/ianaya89/workshop-vuejs/blob/master/ex/04.md) 47 | 5. 👨‍🎓 [Vue Avanzado (SFC)](https://github.com/ianaya89/workshop-vuejs/blob/master/ex/05.md) 48 | 6. 🖥 [CLI](https://github.com/ianaya89/workshop-vuejs/blob/master/ex/06.md) 49 | 7. 👷 [Arquitectura](https://github.com/ianaya89/workshop-vuejs/blob/master/ex/07.md) 50 | 8. 💸 [vue-coins](https://github.com/ianaya89/workshop-vuejs/blob/master/ex/08.md) 51 | 9. 🔌 [vue-cli plugins](https://github.com/ianaya89/workshop-vuejs/blob/master/ex/09.md) 52 | 10. ♻️ [Ciclo de Vida](https://github.com/ianaya89/workshop-vuejs/blob/master/ex/10.md) 53 | 11. 👀 *[Computed & Watch](https://github.com/ianaya89/workshop-vuejs/blob/master/ex/11.md)* 54 | 12. 🐛 [Debugging](https://github.com/ianaya89/workshop-vuejs/blob/master/ex/12.md) 55 | 13. ☎ [Comunicacion de Componentes](https://github.com/ianaya89/workshop-vuejs/blob/master/ex/13.md) [⚠️ WIP] 56 | 14. 🎚 [Modifiers](https://github.com/ianaya89/workshop-vuejs/blob/master/ex/14.md) [⚠️ WIP] 57 | 15. 🔚 [Vue Next](https://github.com/ianaya89/workshop-vuejs/blob/master/ex/15.md) 58 | 59 | ## Licencia 60 | 📄 [Licencia MIT](https://github.com/ndelvalle/workshop-vuejs/blob/master/LICENSE) 61 | 62 | --- 63 | *Cualquier consulta, critica, PR o sugerencia es totalmente bienvenida. 64 | Gracias por acompañarme en este Workshop!* 65 | 66 | **✍️ with ❤️ by [@ianaya89](https://twitter.com/ianaya89)** 67 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Breaking the Binary World | Vue.js 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 26 | 27 | 28 | 35 | 36 | 37 | 38 |
39 |
40 |
41 |
42 | 43 |
44 |
45 |
46 |

47 | Rompiendo el Mundo Binario 48 |
con Vue.js 49 |

50 |

51 | 52 | 🌎  🔨 53 | 54 | 55 | 56 | 57 |

58 |
59 | 60 |
61 |

Ignacio Anaya

62 |

@ianaya89

63 |
Full Stack Developer en E-xact Transactions
64 |
Programming Mentor en Thinkful
65 |
    66 |
  • 67 |
  • 68 |
  • 69 |
  • 70 |
71 |
72 | 73 |
74 | 77 | 78 |
79 |

The State of JavaScript 2016

80 |
    81 |
  • Menos conocido (77%)
  • 82 |
  • Intencion de aprender (49%)
  • 83 |
  • Intencion de volver a usar (88%)
  • 84 |
  • + 300k descargas mensuales en npm
  • 85 |
  • Trending Project en GitHub
  • 86 |
87 |
88 |
89 | 90 |
91 |
92 |

Por Qué Vue.js?

93 |
94 | 95 | 98 | 99 |
100 |

Complejidad

101 |

Inherente vs. Instrumental

102 |
103 | 104 |
105 |

Características

106 |
    107 |
  • Framework Progresivo
  • 108 |
  • View de MV*
  • 109 |
  • Reactivo
  • 110 |
  • Basado en core
  • 111 |
  • Orientado a componentes
  • 112 |
113 |
114 | 115 |
116 |

Performance vs. React

117 | 118 | vs-react 119 | 120 |
121 | 122 |
123 |

Performance vs. Angular

124 | 125 | vs-angular 126 | 127 |
128 | 129 |
130 |
131 | 132 | 140 |
141 | 142 |
143 |
144 |

Declarative Rendering

145 | declarative-rendering 146 |
147 | 148 |
149 |

Caraterísticas

150 |
    151 |
  • Reactivo
  • 152 |
  • Automático
  • 153 |
  • Solo Vista
  • 154 |
155 |
156 | 157 |
158 |

Expressions

159 |

Mustache Syntax para templates dinamicos

160 |

161 | 162 | <h1>{ 'hello ' }} {{ 'world!'}}</h1> 163 | 164 |

165 |
166 | 167 |
168 |

Directives I

169 |

Atributos HTML para manipular el DOM

170 |

171 | 172 | <h1 v-if="true"></h1> 173 | 174 |

175 |
176 | 177 |
178 |

Directives II

179 |

Atributos HTML para manejar eventos del DOM

180 |

181 | 182 | <button v-on:click="send"></button> 183 | 184 |

185 |
186 | 187 |
188 |

data()

189 |

Funcion donde se definen las propiades

190 |
191 | 192 |
193 |

Methods

194 |

Funciones para definir acciones y comportamiento

195 |
196 | 197 |
198 |

Computed

199 |

Propiedades generados en base cambios de otras propiedades

200 |
201 | 202 |
203 |

Watchers

204 |

Funciones para ejecutar acciones en base a cambios de propiedades

205 |
206 | 207 |
208 |

👋🌎

209 |

See the Pen Vue Hello World! by Ignacio Anaya (@ianaya89) on CodePen.

210 |
211 |
212 | 213 |
214 |
215 |

Component System

216 |
217 | components 218 |
219 |
220 | 221 |
222 |

Características

223 |
    224 |
  • ASAP
  • 225 |
  • Reutilizables (no siempre)
  • 226 |
  • Estructura de árbol
  • 227 |
  • HTML Semántico
  • 228 |
229 |
230 | 231 |
232 |

Life Cycle

233 |

Momentos o etapas que transcurren por cada componente

234 |
235 | 236 |
237 |

Life Cycle Hooks

238 |

239 | Metodos que nos permiten definir comportamiento para cada etapa 240 |

241 |
242 | 243 |
244 |

Single File Components (.vue)

245 |

Archivos que sirven para escribir componentes

246 |

No funcionan de forma nativa

247 |
248 |
249 | 250 |
251 |
252 |

Build System

253 |

DX - Developer Experience

254 |
255 | 256 |
257 |

Webpack

258 | vue-loader 259 |
260 | 261 |
262 |

Browserify

263 | vueify 264 |
265 | 266 |
267 |

vue-cli

268 | png 269 |
270 | 271 |
272 |

Chrome Dev Tools

273 | dev-tools 274 |
275 |
276 | 277 |
278 |
279 |

Client Side Routing

280 |

vue-router

281 |
282 |
283 | 284 |
285 |
286 |

Large Scale State Management

287 |

vuex

288 |
289 |
290 | 291 |
292 |

Server Side Rendering

293 |

Nativo

294 |

Nuxt.js

295 |
296 | nuxt 297 |
298 | 299 |
300 |

Mobile Native Rendering

301 |

Weex

302 |

303 | weex 304 |

305 |
306 | 307 |
308 |

Workshop

309 |
310 | 311 |
312 |

Recursos

313 | 322 |
323 | 324 |
325 |

Gracias! 👏

326 |

@ianaya89

327 |

http://bit.ly/2pUh1kU

328 |

📹

329 |
330 | 331 |
332 |

Preguntas?

333 |
334 |
335 |
336 | 337 |
338 | vue 339 |
340 | 341 | 342 | 343 | 344 | 345 | 357 | 358 | 359 | -------------------------------------------------------------------------------- /ex/01.md: -------------------------------------------------------------------------------- 1 | # 📚 Introducción a Vue 2 | 3 | Vue (se pronuncia como la palabra en ingles *view*), es un [framework progresivo](#aclaraciones) para construir interfaces de usuario. A diferencia de alternativas monolíticas (como Angular) Vue esta diseñado para ser adoptado (y aprendido) fácilmente. 4 | El core de Vue esta enfocaado en la capa de la vista del patron *MV*\*, lo cual permite integrarlo en cualquier proyecto existente de forma muy simple. 5 | Mas allá de su sencillez Vue es capaz de construir todo tipo de aplicaciónes cuando se lo combina con las herramientas y librerías adecuadas. 6 | 7 | # 👋 Hello Vue! 8 | 9 | La manera mas fácil de empezar a usar Vue es usando algún editor de código online ([JSFiddle](https://jsfiddle.net) o [Codepen](https://codepen.io)). 10 | 11 | 1. Lo primero que necesitamos es cargar la librería de Vue. 12 | ```html 13 | 14 | ``` 15 | 16 | 2. Ahora necesitamos crear un poco de HTML donde luego vamos a *montar* nuestra aplicación. 17 | ```html 18 |
19 | {{ message }} 20 |
21 | ``` 22 | 23 | 3. Por ultimo vamos a crear la instancia de Vue la cual nos va a permitir enlazar (*bind*) nuestro código con nuestra vista. 24 | 25 | ```javascript 26 | const vm = { 27 | el: '#app', 28 | data() { 29 | return { 30 | message: 'Hello Vue!' 31 | } 32 | } 33 | } 34 | 35 | const app = new Vue(vm) 36 | ``` 37 | 38 | Acabamos de hacer nuestra primera aplicación con Vue. Como mencionamos antes, el framework se enfoca en la parte de la vista y lo que acabamos de hacer implica crear una interacción entre código JS y vista HTML. Vamos a repasar lo que esta ocurriendo acá: 39 | 40 | 1. En la parte HTML hay 2 cosas importantes a tener en cuenta: 41 | 1. Agregamos un elemento `
`. Esto es de suma importancia ya que nos va a servir para indicarle a Vue cual es el alcance (*scope*) de nuestra aplicación. 42 | 2. Agregamos una expresión `{{ message }}`. Las expresiones nos permiten definir valores dinámicos en nuestro HTML. Esto quiere decir que nuestra aplicación en lugar de mostrar la palabra `"message"` va a mostrar el valor de una variable/propiedad llamada `message`. Luego a través de código nos encargamos de definir el valor de `message` y Vue es quien se ocupa de enlazar ese valor en la vista. 43 | 44 | 2. En la parte JS creamos un objeto `vm` (*View Model*). Podemos apreciar que es simplemente un objeto JS plano. Este objeto tiene toda la configuración necesaria que Vue necesita para crear nuestra app. 45 | 1. Dentro de esto objeto tenemos una propiedad `el` que, a través de un selector de CSS, define el elemento HTML donde se va a montar la aplicación. En este caso `
`. 46 | 2. Por otro lado tenemos una función que se llama `data` la cual **devuelve un objeto**. Dentro de este objeto establecemos todas las propiedades que Vue puede utilizar para mostrar en la vista. En resumen, al crear la propiedad `message` dentro de `data` estamos permitiendo que luego, en nuestro HTML, podamos mostrar el contenido de dicha propiedad usando la expresión `{{ message }}`. 47 | 3. El último paso es crear una instancia de Vue pasando como configuración nuestro objeto `vm`. 48 | 49 | 50 | # 🏃‍ Reactividad 51 | 52 | Vue trabaja con el concepto de reactividad, lo cual quiere decir que todos los cambios que hagamos en nuestro `vm` (JS) se van a reflejar de manera automática en la vista (HTML). Podemos ver como funcióna esto de la siguiente manera: 53 | 54 | 1. Abrimos el siguiente [link](https://codepen.io/ianaya89/pen/aWRMQV). Contiene la app básica que creamos antes. 55 | 2. Una vez en Codepen hacemos click en la tab que dice *Console*. 56 | 3. Dentro de la consola podemos acceder a la variable `app` que creamos y modificar el valor de la propiedad `message` escribiendo: `app.message = 'Bye Vue!'`. Apretamos *enter* y vamos a notar que el nuevo valor es renderizado automáticamente en el HTML. 57 | 58 | ![reactivity](../img/reactivity.gif) 59 | 60 | ___ 61 | ### 👉 Aclaraciones 62 | > Cuando decimos que Vue es un framework progresivo esta relacionado con que nos permite que nuestra aplicación evolucione (o escale) paso a paso. Esto quiere decir que podemos arrancar con un proyecto muy sencillo (como una landing page) sin necesidad de tener que cargar módulos o funcionalidad que no necesitamos. Luego, a medida que nuestros requerimientos se tornen mas complejos podemos incorporar esta funciónalidad (y otras herramientas) que nos permitan manejar estos nuevos requerimientos. 63 | 64 | > Vue (al igual que el DOM) trabaja con una estructura de en árbol en cuanto a HTML. Partimos de un componente `root` que representa nuestra aplicación y todos los demás componentes hijos de `root`. En nuestro caso el componente principal es `
`. Esto implica que todo lo que esté por fuera de ese `
` esta fuera del alcance de Vue. Podemos probar agregando la expresión {{ message }} fuera del `
` principal y veremos que deja de funcionar como esperamos. 65 | 66 | > El nombre `vm` es simplemente para darle un significado semántico a nuestros ejemplos ya que se supone que cada componente de Vue recibe un objeto con configuración que representa al *View Model*. Esta variable podría tener cualquier nombre, incluso podríamos no crearla y definir el objeto dentro de la instancia de Vue: `const app = new Vue({})`. 67 | 68 | 69 | ### 📝 [Solución](https://jsfiddle.net/ianaya89/f8s8nh58) 70 | 71 | [⏩](https://github.com/ianaya89/workshop-vuejs/blob/master/ex/02.md) 72 | -------------------------------------------------------------------------------- /ex/02.md: -------------------------------------------------------------------------------- 1 | # 🎬 Directivas 2 | 3 | Las directivas son una característica muy importante dentro de Vue. Junto con las expresiones, son quienes nos permiten manipular, interactuar y modificar el [DOM](https://developer.mozilla.org/es/docs/Referencia_DOM_de_Gecko/Introducci%C3%B3n). 4 | Este concepto (como muchos otros) viene del mundo Angular. Podemos definir entonces a una directiva como atributos personalizados y dinámicos para maniuplar elementos HTML. 5 | 6 | Estas son algunas de las directivas nativas de Vue: 7 | 1. `v-if` y `v-else` ➡️ Agrega o elimina elementos del DOM en función de un resultado `booleano` 8 | 2. `v-show` ➡️ funciona igual a `v-if` pero en lugar de eliminar o agregar el elemento, lo hace visible o invisible. 9 | 3. `v-for` ➡️ Iterar y representa en HTML una colección de elementos (`Array`) o un objeto. 10 | 4. `v-bind` ➡️ Permite que cualquier atributo HTML como `href`, `src` o `class` recibe propiedades para generar valores dinámicos. 11 | 12 | ## `v-if`, `v-else` y `v-show` 13 | 14 | 1. Partiendo del ejemplo anterior vamos agregar una propiedad `show` a nuestro `vm`, que nos permita agregar o eliminar el elemento del DOM. Recuerden que las propiedades siempre deben ser parte del objeto que retorna la función `data`. 15 | 16 | ```js 17 | const vm = { 18 | el: '#app', 19 | data() { 20 | return { 21 | message: 'Hello Vue!', 22 | show: true 23 | } 24 | } 25 | } 26 | 27 | const app = new Vue(vm) 28 | ``` 29 | 30 | 2. Una vez que hayamos definido la propiedad podemos agregar las directivas `v-if` y `v-else` a nuestro HTML. 31 | 32 | ```html 33 |
34 |

35 | {{ message }} 36 |

37 |

38 | El texto esta oculto 39 |

40 |
41 | ``` 42 | 43 | Acabamos de insertar nuestra primera directiva, en base al valor de la propiedad `show` vamos a poder condicionar nuestro HTML. Si `show === true` (en realidad si es *truthy*) se visualizara `'Hello Vue!'`, en caso contrario veremos `'El texto esta oculto'`. Prueben cambiar el valor de `show` para corroborar el funcionamiento. 44 | 45 | Al igual que en JS, el uso de `v-else` cuando usamos un `v-if` es opcional. Podemos decidir si usarlo o no. 46 | 47 | 3. Probemos también con agregar otro elemento HTML usando la directiva `v-show` el cual también va estar enlazado al valor de la propiedad `show` de nuestro `vm`. 48 | 49 | ```html 50 |
51 |

52 | {{ message }} 53 |

54 |

55 | El texto esta oculto 56 |

57 | 58 |

59 | {{ message }} 60 |

61 |
62 | ``` 63 | 64 | Ahora el texto `'Hello Vue!'` se visualizara por duplicado cada vez que `show` sea verdadero. 65 | Si inspeccionamos el DOM usando las *Dev Tools* del browser, podemos observar que 66 | cuando `show === true` ambos elementos permanecen en el DOM. Pero cuando `show === false`, el elemento que usa `v-if` se elimina, mientras que el que usa `v-show` sigue existiendo pero permanece oculto usando la propiedad `display` de CSS. 67 | 68 | ![directives](../img/directives.gif) 69 | 70 | ## `v-bind` 71 | 72 | El uso de esta directiva es muy común ya que nos permite darle dinamismo a cualquier atributo HTML en tiempo real. Es decir que usando `v-bind` podemos modificar desde el `src` de un tag `` hasta el `href` de tag ``. 73 | 74 | 1. Agregamos una nueva propiedad al objeto de la función `data` llamada `url` y le definimos un valor en formato `string` con la url que mas nos guste. 75 | 76 | ```javascript 77 | const vm = { 78 | el: '#app', 79 | data() { 80 | return { 81 | message: 'Hello Vue!', 82 | show: true, 83 | 84 | items: [ 85 | { text: 'A' }, 86 | { text: 'B' }, 87 | { text: 'C' }, 88 | ], 89 | 90 | url: 'https://google.com' 91 | } 92 | } 93 | } 94 | 95 | const app = new Vue(vm) 96 | ``` 97 | 98 | 2. Añadimos un nuevo elemento `` a nuestro HTML al cual lo vamos a enlazar con la variable `url` de nuestro `vm` usando esta sintaxis: `v-bind:href="url"`. 99 | 100 | ```html 101 | 121 | ``` 122 | 123 | Como pueden ver la manera de utilizar la directiva es con el formato `v-bind:[nombre del atributo]`. De ahora en mas cada vez que el valor de la propiedad `url` se modifique también se modificara el valor del atributo `href` de nuestro link. Esta directiva puede escribirse de manera mas sencilla usando un *shortcut*: `:href="url"`. Por lo cual cada vez que en Vue vean `:` que preceden un atributo HTML, recuerden que equivale a escribir la directiva `v-bind`. 124 | 125 | ## `v-for` 126 | 127 | 1. Por ultimo vamos a ver el compartimiento de `v-for`. Nos permite representar una colección de elementos en nuestro HTML. Creamos un `Array` con el nombre `items` en la función `data` de nuestro `vm` y vamos a llenar este array con algunos objetos. 128 | 129 | ```javascript 130 | const vm = { 131 | el: '#app', 132 | data() { 133 | return { 134 | message: 'Hello Vue!', 135 | show: true, 136 | 137 | items: [ 138 | { text: 'A' }, 139 | { text: 'B' }, 140 | { text: 'C' }, 141 | ] 142 | } 143 | } 144 | } 145 | 146 | const app = new Vue(vm) 147 | ``` 148 | 149 | 2. Ahora nos falta agregar el HTML necesario que junto a la directiva `v-for` nos permita visualizar cada elemento dentro de la colección de `items`. 150 | 151 | ```html 152 |
153 |

154 | {{ message }} 155 |

156 |

157 | El texto esta oculto 158 |

159 | 160 |

161 | {{ message }} 162 |

163 | 164 |
    165 |
  • 166 | {{ i.text }} 167 |
  • 168 |
169 |
170 | ``` 171 | 172 | Agregamos tambien la directiva `v-bind` con la propiedad `key`. Esta propiedad es requerida por vue cuando utilizamos colecciones y la directiva `v-for` ya que le permite identificar univocamente cada elemento y evitar problemas en el futuro. Podes encontar mas informacion en este [link](https://es.vuejs.org/v2/guide/list.html#key). 173 | 174 | Si todo salió bien, vas a ver en pantalla una lista que contiene 3 elementos `
  • `. Lo que esta pasando entonces es que a través de la propiedad `i` podemos representar cada uno de los elementos de `items` y definir la estructura HTML con la cual queremos visualizarlos. Como nuestros items son objetos usamos la sintaxis nativa de JS para acceder a sus propiedades `{{ i.text }}`. 175 | 176 | > 👌 Usando la directiva `v-for`, tambien podes al indice que le corresponde a cada elemento con la siguiente sintaxis: `v-for="(item, index) in items`". De esta forma, el primer parametro hace referencia al elemento y el segundo al indice que le corresponde al mismo. 177 | > 👌 `v-for` tambien puede ser utilizado para representar las propiedades de un objeto. Podes ver [este ejemplo](https://es.vuejs.org/v2/guide/list.html#v-for-con-un-Objecto) de la documentación. 178 | 179 | 180 | 181 | ___ 182 | ### 👉 Aclaraciones 183 | > En JS tenemos valores *truthy* y *falsy*. A grandes rasgos esto implica que cualquier valor (independientemente del tipo de dato) puede ser evaluado de forma booleana. Los valores *falsy* son todos aquellos que en el caso de ser evaluados en expresiones booleanas devuelven *false*. Estos valores son: `false`, `''`, `0`, `null` y `undefined`. Esto quiere decir que todos los otros valores (incluso objetos y arreglos vacíos) retornan `true`. 184 | 185 | > En las expresiones podemos escribir cualquier tipo de código JS valido. En realidad no cualquiera. No podemos usar `if`, `else`, `for`, `while` pero si podemos usar *ternary expressions*, concatenar cadenas de texto, operar valores aritméticamente y acceder a métodos y propiedades de las variables. Estos son algunos ejemplos de expresiones validas: 186 | 187 | ```javascript 188 | {{ 1 * 100 }} 189 | {{ str1 + ' ' + str2 }} 190 | {{ JSON.stringify(obj) }} 191 | {{ str.replace(/ /g, '-') }} 192 | {{ arr.join('-') }} 193 | ``` 194 | 195 | Si tenes ganas, podes experimentar en codepen y jugar con diferentes alternativas de codigo JavaScript para probar en las expresiones. 196 | 197 | ### 📝 [Solución](https://jsfiddle.net/8vvm6d5v/4/) 198 | 199 | [⏪](https://github.com/ianaya89/workshop-vuejs/blob/master/ex/01.md) [⏩](https://github.com/ianaya89/workshop-vuejs/blob/master/ex/03.md) 200 | -------------------------------------------------------------------------------- /ex/03.md: -------------------------------------------------------------------------------- 1 | # 🔁 📅 *Two-Way Data Binding* y Eventos 2 | 3 | Hasta ahora vimos como vincular data entre el código y la vista usando directivas y expresiones. Cuando cambiamos código, la vista refresca esos cambios de forma automática en nuestro HTML. Esto sucede gracias a que como mencionamos antes, Vue es un framework reactivo y se encarga de resolver esta cuestión automáticamente. 4 | 5 | Por suerte este concepto de reactividad funciona de forma *bi-direccional*, es decir que Vue también va actualizar nuestro código cuando algo se modifica en la vista. Esto generalmente sucede cuando el usuario interactúa con nuestra aplicación, ingresando data en formularios, haciendo click en botones, etc. 6 | 7 | 8 | ## `v-model` 9 | 10 | Lo primero que vamos a ver es la directiva `v-model` la cual nos permite vincular elementos HTML de tipo `input`, `select` y `textarea` con propiedades de nuestro `vm`. De esta forma cada vez que el usuario modifique el valor de estos elementos, Vue va a actualizar el valor en las propiedades enlazadas. 11 | 12 | 1. Creamos una nueva aplicación (recuerden incluir el `script` con referencia al *framework*), agregamos un elemento `input` dentro del HTML y le agregamos la directiva `v-model` con referencia a una propiedad llamada `name`. También vamos a agregar una expression para mostrar el valor de {{ name }} a medida que el usuario va ingresando la información. 13 | 14 | ```html 15 |
    16 | 17 |

    18 | {{ name }} 19 |

    20 |
    21 | ``` 22 | 23 | 2. Vamos entonces a crear dentro del objeto de la función `data`, una propiedad llamada `name`. 24 | 25 | ```javascript 26 | const vm = { 27 | el: '#app', 28 | data() { 29 | return { 30 | name: '' 31 | } 32 | } 33 | } 34 | 35 | const app = new Vue(vm) 36 | ``` 37 | 38 | Una vez hecho esto, podemos corroborar el funcionamiento escribiendo dentro del `input` en nuestra vista. Vamos a ver que el texto se actualiza de forma instantánea. 39 | 40 | Lo que hicimos fue enlazar el input con una propiedad del `vm`. De ahora en mas cada vez que el usuario modifique el valor del input, nuestra variable va a cambiar y si nosotros modificamos el valor por código también se cambiará en la vista. Podemos probarlo definiendo la propiedad `name` con un valor *default*: 41 | 42 | ```javascript 43 | const vm = { 44 | el: '#app', 45 | data() { 46 | return { 47 | name: 'Ignacio Anaya' 48 | } 49 | } 50 | } 51 | 52 | const app = new Vue(vm) 53 | ``` 54 | 55 | ## `v-on` 56 | 57 | Como decíamos antes, el usuario también interactúa con nuestra aplicación a través de eventos. Como ya sabemos JS y el DOM están orientados a eventos. Esto nos permite a nosotros definir (usando funciones) como reaccionar y que hacer cada vez que estos eventos determinados ocurren. 58 | 59 | Cuando usamos Vue, estas reacciones las definimos dentro de nuestro `vm`. Para definir propiedades lo hacemos usando la función `data`. En el caso de los eventos utilizamos el **objeto** `methods`. 60 | 61 | Vamos a crear un evento que nos permita transformar la variable `name` cada vez que el usuario haga click a un botón. 62 | 63 | 1. Dentro de nuestro `vm`, creamos el objeto `methods` y le definimos una función con el nombre `formatName`. 64 | 65 | ```javascript 66 | const vm = { 67 | el: '#app', 68 | data() { 69 | return { 70 | name: 'Ignacio Anaya' 71 | } 72 | }, 73 | 74 | methods: { 75 | formatName() { 76 | this.name = this.name.split(' ').join('-').toLowerCase() 77 | } 78 | } 79 | } 80 | 81 | const app = new Vue(vm) 82 | ``` 83 | 84 | El compartimiento de nuestra función `formatName` es sencillo. Combinamos los métodos `split` y `join` (de `Array` y `String`) para reemplazar los espacios por guiones y luego convertir todo a minúsculas. Lo importante es identificar que en los métodos accedemos a la propiedades del `vm` (e incluso a otros métodos) usando la variable `this`. Podemos decir que `this` es una representación interna del mismo `vm`. 85 | 86 | 2. Agregamos el botón al cual vamos a enlazar con el método `formatName`. Este enlace lo vamos a conseguir usando la directiva `v-on`. 87 | 88 | ```html 89 |
    90 | 91 | 92 |

    93 | {{ name }} 94 |

    95 |
    96 | ``` 97 | 98 | Como podemos ver, la manera de utilizar la directiva es `v-on:[nombre del evento]` (similar al uso de `v-bind`). Esta directiva es muy flexible y nos permite establecer acciones para cualquier tipo de eventos (`focus`, `keyup`, `blur`, `load`, etc). 99 | 100 | La directiva `v-on` (al igual que `v-bind`), también tiene un *shortcut*, podemos simplificar usando `@`: `@click="formatName"`. 101 | 102 | ![directives](../img/two-way.gif) 103 | 104 | ___ 105 | ### 📝 [Solución](https://jsfiddle.net/5xuhnz4L/1/) 106 | 107 | [⏪](https://github.com/ianaya89/workshop-vuejs/blob/master/ex/02.md) [⏩](https://github.com/ianaya89/workshop-vuejs/blob/master/ex/04.md) 108 | -------------------------------------------------------------------------------- /ex/04.md: -------------------------------------------------------------------------------- 1 | # 📦 *Components* 2 | 3 | El sistema de componentes de Vue es la otra parte fundamental del *framework*. Vue nos permite construir grandes aplicaciones a través de pequeños componentes. Estos componentes pueden ser re-utilizables (o no), pero lo más importante es que cada componente tiene toda la estructura y lógica que necesita para funcionar. Es decir que cada uno tiene su propio código (JS), su propia estructura (HTML) e incluso sus propios estilos (CSS). 4 | 5 | ## `Vue.component()` 6 | 7 | Vamos a crear nuestro primer componente. Para ser más precisos en los ejemplos anteriores ya estábamos creando un componente: que es el componente principal de la aplicación. La diferencia es que ahora vamos a usar el método estático `Vue.component()` que permite crear componentes para que sean utilizados por otros. 8 | 9 | La ventaja es que los componentes que creemos para reutilizar o insertar en otros componentes tienen las mismas características que el componente principal. Es decir que vamos a crearlos usando un objeto `vm` el cual puede (o no) contener la función `data` y el objeto `methods`. En este caso vamos a ver otras propiedades del `vm` que son útiles a la hora de trabajar con componentes. 10 | 11 | 1. En un nuevo fiddle creamos una aplicación de Vue con el siguiente HTML 12 | ```html 13 |
    14 |
    15 | ``` 16 | 17 | 1. Luego en nuestro JS, creamos un nuevo componente que tiene como propósito definir el template para renderizar un determinado objeto (que va a recibir por atributo). También creamos nuestro `vm` e instancia de Vue con una propiedad `family` que contiene una colección de personas. 18 | 19 | ```JS 20 | Vue.component('family-member', { 21 | props: ['member'], 22 | 23 | template: `
  • 24 | {{ member.id }} - {{ member.name }} 25 |
  • ` 26 | }) 27 | 28 | const vm = { 29 | el: '#app', 30 | data () { 31 | return { 32 | family: [ 33 | { id: 1, name: 'Ignacio' }, 34 | { id: 2, name: 'Sofia '}, 35 | { id: 3, name: 'Pedro '} 36 | ] 37 | } 38 | } 39 | } 40 | 41 | const app = new Vue(vm) 42 | ``` 43 | 44 | El objeto `vm` no es necesario explicarlo, vamos a enfocarnos en lo que pasa en `Vue.component()`. Para empezar es importante entender que este método esta registrando dentro de Vue un nuevo componente llamado `family-member`. Desde ahora este nuevo elemento va a poder ser utilizado para cualquier otro componente que tengamos (incluyendo el componente principal). 45 | 46 | Como vemos, el método recibe 2 parámetros. El primero es un `string` con el nombre. El segundo es un objeto (*View Model*) que tiene toda la configuración (métodos, propiedades, etc) que necesita nuestro componente. 47 | 48 | Por otro lado dentro del `vm` de `family-member` tenemos 2 nuevas propiedades. Una es `props`, la cual nos permite definir los atributos que puede recibir nuestro componente a la hora de ser utilizado en el HTML. En nuestro caso decimos nuestro componente tiene un atributo `member`. Las propiedades de `props` funcionan igual que las de `data`, la diferencia es que las de props van a pertenecer al componente padre y el hijo solo tiene acceso de lectura a las mismas (no puede modificar su valor). 49 | 50 | Por otro lado tenemos la propiedad `template` que establece el HTML que va a renderizar nuestro componente. 51 | 52 | 4. Insertamos nuestro componente en el HTML y agregamos las directivas de Vue para que funcione como esperamos. 53 | ```html 54 |
    55 |

    Familia

    56 |
      57 | 58 |
    59 |
    60 | ``` 61 | 62 | El nombre que le pusimos a nuestro componente es el nombre que usamos para declararlo en el HTML. Usamos la directiva `v-for` para crear un `family-member` por cada persona que existe en la propiedad `family` del componente principal. 63 | 64 | También usamos la directiva `v-bind` (con su shortcut `:`) para enlazar cada persona (cada elemento de `family`) con la propiedad `member` del componente hijo (`family-member`). Luego es el componente hijo quien usa la data de cada persona para generar el HTML correspondiente (basado en el template definido). 65 | 66 | > 👌 Recorda siempre usar el atributo `key` con `v-bind` o `:` cuando usas la directiva `v-for`. 67 | 68 | ![directives](../img/components.png) 69 | 70 | ___ 71 | ### 👉 Aclaraciones 72 | 73 | > En grandes aplicaciones el concepto de componentes es realmente muy útil ya que nos permite dividir la aplicación en componentes mas pequeños y manejables, es muy común que podamos encontrarnos con este tipo de estructuras: 74 | ```html 75 |
    76 | 77 | 78 | 79 | 80 | 81 | 82 |
    83 | ``` 84 | 85 | ### 📝 [Solución](https://jsfiddle.net/ianaya89/580pwqqe) 86 | 87 | [⏪](https://github.com/ianaya89/workshop-vuejs/blob/master/ex/03.md) [⏩](https://github.com/ianaya89/workshop-vuejs/blob/master/ex/05.md) 88 | -------------------------------------------------------------------------------- /ex/05.md: -------------------------------------------------------------------------------- 1 | # 👨‍🎓 Vue Avanzado (SFC) 2 | 3 | Ahora que ya sabemos los conceptos básicos de Vue, vamos a aprender a crear aplicaciones web más profesionales. 4 | 5 | Hasta ahora vimos que implementar el framework es muy fácil, simplemente tenemos que agregar la referencia y crear la instancia escribiendo `new Vue({})`. El asunto es que en la mayoría de los casos vamos a querer hacer aplicaciones mas complejas en lugar de prototipos o *landing pages*. 6 | 7 | Recordemos que Vue esta basado en un concepto progresivo y que a medida que nuestra aplicación incremente la complejidad podemos acompañar ese proceso con herramientas o librerías que nos permitan trabajar de manera más óptima. 8 | 9 | 10 | ## *Single File Components* (`.vue`) 11 | 12 | Lo primero que vamos aprender ahora es la *magia* de los archivos `.vue` (SFC: *Single File Components*). Esto nos permite crear componentes en archivos (1 componente = 1 archivo) y escribir todo el código, vista y estilos que pertenece a ese componente. 13 | 14 | La estructura de un archivo `.vue` es la siguente: 15 | 16 | ![vue-file](../img/sfc.png) 17 | 18 | Como ven es muy intuitivo, usamos el tag `template` para HTML, `script` para JS y `style` para CSS. 19 | Las ventajas de los archivos `.vue` son las siguientes: 20 | 21 | 1. Facilitamos el manejo de código HTML en cada componente ya que no usamos mas una variable `string`. 22 | 2. Podemos agregar estilos (CSS) específicos para nuestros componentes. Incluso, usando el atributo `scoped` podemos hacer que sos estilos apliquen unicamente al componente en cuestion. 23 | 3. Nos permiten integrar *pre procesadores* como [Bebel](http://babeljs.io/), [Sass](http://sass-lang.com/) y [Pug](https://pugjs.org/api/getting-started.html). 24 | 25 | Si bien los archivos `.vue` son geniales para los desarrolladores, tenemos un pequeño problema. El browser no soporta este tipo de archivos 😅 26 | 27 | Para poder utilizarlos vamos a tener que incorporar algún sistema de *build*. Esto quiere decir que nosotros como programadores vamos a codear nuestra aplicación en componentes dentro de archivos `.vue` pero con la ayuda de herramientas como [Webpack](https://webpack.github.io/) o [Rollup](https://rollupjs.org/), nuestro código se va a compilar a archivos `.js` que el browser puede interpretar. 28 | 29 | En general este proceso de compilación tiende a ser un poco mas complejo y esta fuera del alcance de este Workshop. 30 | 31 | Por suerte para nosotros, vamos a hacer de este proceso una **caja negra**, ya que vamos confiar en el ecosistema de Vue para configurar e iniciar nuestro proyectos. 💪🏼😎. 32 | 33 | [⏪](https://github.com/ianaya89/workshop-vuejs/blob/master/ex/04.md) [⏩](https://github.com/ianaya89/workshop-vuejs/blob/master/ex/06.md) 34 | -------------------------------------------------------------------------------- /ex/06.md: -------------------------------------------------------------------------------- 1 | # 🖥 CLI 2 | 3 | Un CLI (*Command Line Interface*) es una pequeña utilidad de consola que nos permite interactuar con un programa a través de comandos o instrucciones. Cuando usamos [npm](https://www.npmjs.com/) para instalar una librería, estamos usando un CLI. 4 | 5 | Vue tiene su propio CLI ([@vue/cli](https://cli.vuejs.org/)), el cual tiene un propósito muy simple: facilitar y acelerar el desarrollo aplicaciones con Vue. Nos permite crear todo el *set up* inicial de nuestros proyectos utlizando diferentes tipos de plugins, segun las necesidades que tengamos. Lo bueno de esta utilidad es que no solo crea todos los archivos necesarios, sino que también nos abstrae de la configuración inicial que requerie el proyect. De esta forma podemos empezar a programar desde el momento cero, sin necesidad de ocuparnos del *setup* inicial. 6 | 7 | En nuestro proyecto vamos a usar los plugins default: 8 | - [Babel](https://cli.vuejs.org/core-plugins/babel.html) 9 | - [Eslint](https://cli.vuejs.org/core-plugins/eslint.html) 10 | 11 | Es importante aclarar, que el CLI cuenta con otros plugins como **PWA** o **TypeScript** y ademas nos da la facultad de crear plugins propios. [Aca](https://awesomejs.dev/for/vue-cli/) podes encontrar un listado de plugins realizados por otros desarrolladores. 12 | 13 | ## @vue/cli 14 | El CLI de Vue esta desarrollado en node y es parte del repositorio público de npm, por lo cual podemos instalarlo de manera global para usarlo en nuestra terminal de comandos. 15 | 16 | 1. Abrimos una terminal 17 | 2. Instalamos `@vue/cli` usando npm (recuerden que el *flag* `-g` indica instalación global) 18 | ```bash 19 | $ npm i -g @vue/cli 20 | ``` 21 | 3. Usando la terminal navegamos hasta el directorio donde queramos crear nuestra aplicación usando el comando `cd`. 22 | 4. Creamos nuestro proyecto usando el comando `vue create [nombre de proyecto]`: 23 | ```bash 24 | $ vue create vue-coins 25 | ``` 26 | 5. Seleccionamos el preset *default* (babel, eslint) y presionamos *enter*. 27 | 28 | 29 | > 👌 Para el cli, un *preset* es un conjunto de plugins. Cuando creamos un proyecto y seleccionamos los plugins que queremos, el cli nos ofrecer guardar esa selección como un *preset*. Asi es como la próxima vez que creemos un proyecto podemos reutilizar facilmente esa configuración. 30 | 31 | ![vue-init](../img/cli.gif) 32 | 33 | > 💸 `vue-coins` es el nombre que vamos a usar para nuestro nuestro proyecto. 34 | 35 | Una vez finalizado esto y si no tuvimos ningún tipo de error, vas a navegar al directorio de la aplicacion usando el comando `cd` y luego correr el proyecto con el comando `npm run serve`. 36 | 37 | 1. `$ cd vue-coins` 38 | 2. `$ npm run serve` 39 | 40 | ![serve](../img/serve.gif) 41 | 42 | Luego de correr estos comandos vas a ver en la terminal una URL apuntando a *localhost* y el puerto 8080 (el puerto puede variar si lo tenes utilizado por otro proceso). Podes abrir la URL [http://localhost:8080](http://localhost:8080) en tu navegador y vas poder tu primera App de Vue funcionando 🙌. 43 | 44 | ![my-app](../img/my-app.png) 45 | 46 | ## `npm run serve` 47 | 48 | Si nunca usaron npm scripts pueden chequear como se comportan en la [documentación](https://docs.npmjs.com/misc/scripts). Mientras tanto podemos describirlos como comandos personalizados que nos permiten, entre otras cosas, disponer de las módulos o librerías de npm (locales) en nuestra terminal. 49 | 50 | Si directamente nunca usaron npm, pueden empezar por [acá](https://docs.npmjs.com/getting-started/what-is-npm). Entendamos que npm es un manejador de dependencias, nos permite compartir y utilizar código a través de un registro online. Lo utilizamos principalmente para instalar Vue, el cli, Babel, etc. 51 | 52 | Volviendo al tema de los scripts, estos se configuran en el archivo `package.json`. Este archivo contiene toda la metadata de nuestro proyecto, los scripts y todas las dependencias que utilizamos. Al contar con toda esta información, este archivo me permite tener un ambiente de desarrollo reproducible en cualquier otra computadora. 53 | 54 | Si inspeccionamos el `package.json` creado por el CLI nos encontramos con dos scripts: 55 | 56 | ```json 57 | // package.json 58 | "scripts": { 59 | "serve": "vue-cli-service serve", 60 | "build": "vue-cli-service build", 61 | "lint": "vue-cli-service lint" 62 | }, 63 | ``` 64 | 65 | 1. `serve` ➡️ Incia la aplicación en modo de desarrollo. 66 | 2. `build` ➡️ Compila nuestra aplicación para llevar a produccion. 67 | 3. `lint` ➡️ Corre el proceso de *linting* en nuestros archivos. 68 | 69 | > 👌 Todos los scripts de npm los ejecutamos con el comando `npm run [nombre de script]`. A excepción de los comandos `test` y `start` donde podemos omitir el uso de `run`. 70 | 71 | 72 | ## Proyecto 73 | 74 | Si abrimos el proyecto con el editor de texto, vamos a poder ver como es la estructura de archivos de la applicación, que mas adelante vamos a analizar detalladamente. 75 | 76 | ![my-app](../img/vs-code-project.png) 77 | 78 | > 👌 Si estas dentro del directorio `vue-coins` y estas usando VS Code, podes abrir todo el proyecto con el comando: `$ code .`. 79 | 80 | > 👌 Tambien podes usar el comando: `$ ls -al` para listar los archivos/directorios que fueron creados por el CLI. 81 | 82 | ![my-app](../img/ls-al.png) 83 | 84 | 85 | Listo, nuestra aplicacion ya se esta ejecutando en http://localhost:8080 y ya tenemos todo lo que necesitamos para empezar a trabajar con Vue de forma profesional. 86 | 87 | [⏪](https://github.com/ianaya89/workshop-vuejs/blob/master/ex/05.md) [⏩](https://github.com/ianaya89/workshop-vuejs/blob/master/ex/07.md) 88 | -------------------------------------------------------------------------------- /ex/07.md: -------------------------------------------------------------------------------- 1 | # 👷 Arquitectura 2 | 3 | Antes de comenzar a escribir el código de nuestra aplicación vamos a repasar la estructura del proyecto y librerías instaladas por el CLI. 4 | 5 | ## Babel 6 | 7 | [Babel](http://babeljs.io/) es un transpilador de código. Nos permite transformar y compilar código ES2015 (en adalante) a código equivalente ES5 (o código para browsers *legacy*). La ventaja de esta herramienta es que podemos usar las últimas funcionalidades de JS disponibles sin tener que preocuparnos porque estas vayan a ser soportadas o no por los navegadores. 8 | 9 | > 👀 Cuando decimos ES2015 nos referimos desde esa versión en adelante. Recuerden que desde el 2015 las versiones de JS son anuales, por lo cual cada año tenemos una versión con nueva funcionalidad disponible. 10 | 11 | ![babel](../img/babel.gif) 12 | 13 | Para saber más sobre esta herramienta pueden chequear lo [documentación](http://babeljs.io/docs/setup/). En nuestro caso nos alcanza simplemente con entender para que sirve y como se configura. 14 | 15 | La configuración es sencilla, pero no necesitamos hacerla ya que el CLI lo hizo por nosotros. Si chequean en el proyecto generado van a encontrar un archivo llamado `babel.config.js`. Este es un archivo con formato `js` donde indicamos que *[presets](http://babeljs.io/docs/plugins/)* queremos utilizar y donde podemos modificar otros aspectos de la configuración de Babel. Los *presets* son utilidades donde se define que tipo de funcionalidades ES2015 vamos a querer utilizar o soportar. 16 | 17 | > 👀 Tanto en Babel como en @vue/cli utilizamos el concepto de presets, pero a no confundirse ya que son cosas diferentes. 18 | 19 | ```js 20 | // Archivo babel.config.js 21 | module.exports = { 22 | presets: [ 23 | '@vue/cli-plugin-babel/preset' 24 | ] 25 | } 26 | ``` 27 | 28 | > El [@vue/cli-plugin-babel/preset](https://github.com/vuejs/vue-cli/tree/dev/packages/@vue/cli-plugin-babel#readme), es el preset para Babel oficial (y recomendado) de Vue, podemos combinarlo con otros presets o incluso optar por usar uno diferente. 29 | 30 | 31 | ## ESLint 32 | 33 | [ESlint](https://eslint.org) es una herramienta de *linting*. Este tipo de herramientas nos permiten detectar errores, malas prácticas y establecer un formato uniforme en nuestro código. Puede utilizarse y configurarse con diferentes tipos de reglas. En nuestro caso estamos usando la configuración defualt que nos genera el CLI. En caso de querer customizar el uso de eslint, podemos hacerlo modificando el objeto `eslintConfig` que se encuentra en el archivo `package.json`: 34 | 35 | ```json 36 | // archivo package.json 37 | "eslintConfig": { 38 | "root": true, 39 | "env": { 40 | "node": true 41 | }, 42 | "extends": [ 43 | "plugin:vue/essential", 44 | "eslint:recommended" 45 | ], 46 | "parserOptions": { 47 | "parser": "babel-eslint" 48 | }, 49 | "rules": {} 50 | }, 51 | ``` 52 | 53 | > 👌 A veces es un poco molesto, tener la configuración en el package.json. De ser asi, podes crear un archivo llamado `eslint.json` y mover todo el contenido de `eslintConfig` a ese archivo. 54 | 55 | Al igual que con Babel, ya tenemos todo listo y configurado para usar eslint en nuestro proyecto. A menos que querramos tener reglas especificas o modicar algo, no necesitamos cambiar nada. Cuando tengamos determinado código que no cumpla las reglas establecedidas, vamos a poder ver en la terminal un mensaje indicando que es lo que esta sucediendo. 56 | 57 | ![eslint](../img/eslint.gif) 58 | 59 | > 👌 Existe un [plugin para VS Code](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) que nos permite detectar estos errores de manera mas amigable dentro del editor de texto. Tambien hay plugins para la mayoria de los editores como Sublime o Atom. 60 | 61 | > 📏 Lo mas importante de ESLint no son las reglas en si, sino que TODOS vamos a usar las mismas. Podemos consensuar con el equipo nuestro estilo y formato de código. Al final de del dia vamos a obtener un código más ordenado, uniforme y mas fácil de mantener. 😉 62 | 63 | ## Webpack & Build 64 | 65 | [Webpack](https://webpack.js.org/) es el *module bundler* utilizado internamente por el proceso de `serve` y `build` de `@vue/cli`. Es quien se va a encargar de procesar nuestros archivos y transformar el código de desarrollo en código productivo (optimizado para los browsers). 66 | 67 | Nosotros como desarrolladores, necesitamos un código legible, modularizado y semántico. En cambio los browsers necesitan todo lo contrario para que nuestra aplicacion funcione de la forma mas óptima y rápida posible. Este tipo de herramientas permiten que tanto los browsers como los desarrolladores esten contentos y mantener las dos versiones en nuestro codigo 😃 68 | 69 | Ademas, es en este proceso de compilación donde nuestro código es transpilado por Babel. Escribimos el código usando las últimas y mejores funcionalidades de JavaScript posibles, y el CLI con webpack y babel detras, se encargaran de generar el código compatible necesario. 70 | 71 | No solo compilamos archvios `.js`, Webpack tambien puede compilar recursos estáticos como `.css`, `.png` o `.svg`. 72 | 73 | Lo bueno es que el CLI hizo todo por nosotros nuevamente y no tenemos nada que configurar aca. 74 | Y si bien no es nuestro caso, tambien tenemos la facilidad de poder modificar esta configuración y agregar todo lo que necesitemos creando un archivo llamado `vue.config.js` en el directorio principal del proyecto. 75 | 76 | Para entender un poco mas en detalle como funciona, podemos probar corriendo el comando `$ npm run build` en la terminal. Recorda estar posicionado en el directorio principal del proyecto. 77 | 78 | ![build](../img/build.gif) 79 | 80 | Una vez que hayas corrido el comando, vas a ver que se creo un directorio llamado `dist`, el cual contiene todos nuestros archivos procesados para ser llevados a producción. En el caso de querer hacer un deploy, simplemente tenes que trasaladar esta carpeta a tu servidor web o plataforma de deploy favorita. 81 | 82 | ![vs-code-dist](../img/vs-code-dist.png) 83 | 84 | 85 | ## `main.js` 86 | 87 | Este es el archivo principal de nuestra aplicación. Es aca donde vamos importar la librería `Vue` e inicializar nuestro componente principal `App.vue` 88 | 89 | ```javascript 90 | import Vue from 'vue' 91 | import App from './App.vue' 92 | 93 | Vue.config.productionTip = false 94 | 95 | new Vue({ 96 | render: h => h(App), 97 | }).$mount('#app') 98 | 99 | ``` 100 | 101 | Como pueden ver estamos usando [ES Modules](https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Sentencias/import) para importar (y exportar) archivos `.js`. Si bien es una funcionalidad soportada en navegadores modernos, Babel y Webpack nos aseguran que nuestro código, con esta implementacion, va a funcionar tambien en navegadores mas obsoletos. 102 | 103 | Seguramente lo primero que notas, es que en lugar de el atributo `el`, se esta usando la función `$mount('#app')`. Si bien tienen una sútil diferencia, cumple con el mismo propósito: establecer sobre que elemento del DOM vamos a montar la instancia princial de Vue usando un selector de CSS. 104 | 105 | Por otro lado vemos otra una nueva función en el componente principal: `render`. Esta misma nos permite reemplazar a la propiedad `template`. Si bien en nuestro caso no es necesario, el objetivo de `render()` es crear HTML *programaticamente* e incluso compilar JSX o TypeScript (entre otras cosas). 106 | 107 | > Para los que no esta familiarizados con [*Arrow Functions*](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions), el código que vemos en `render` equivale a `render: function(h) { return h(App) }` 108 | 109 | 110 | ## `App.vue` 111 | 112 | Este archivo representa a nuestro componente principal. Si bien es una buena práctica llamarlo `App`, podría tener el nombre que nosotros querramos. Como mencionamos antes, este archivo concentra toda la lógica (JS), estructura (HTML) y estilos (CSS) del componente. 113 | Lo importante a tener en cuenta es que los tags `script` y `style` son opcionales pero no así el tag `template`. 114 | 115 | Por otro lado siempre que tengamos un tag `script` tenemos que usar el *export default* de *ESModules* para exportar un objeto que representa al componente. 116 | 117 | ```html 118 | 124 | 125 | 135 | 136 | 146 | ``` 147 | 148 | > 🚨 TODOS los componentes de Vue tienen que tener un **único** elemento HTML padre, que es conocido como elemento *root*. 149 | 150 | Si prestan atención, el objeto que exportamos no es mas que un `vm` (*ViewModel*) que respeta la estructura, comportamiento y propiedades que aprendimos anteriormente. 151 | 152 | Otra cosa que nueva que podemos observar es la forma en que se utilizan componentes dentro de `App.vue`. La aplicacion de ejemplo generada por el CLI, nos crea un componente llamado `HelloWorld.vue`. Mas adelante vamos a entrar en detalles sobre el uso de componentes, pero el ejemplo nos sirve para entender como es la forma de usarlos dentro de los archivos: 153 | 154 | 1. Dentro de ` 41 | ``` 42 | 43 | > 👌 El `@` que precede a `/services` es un alias que nos permtie referenciar el directorio principal del proyecto, es decir `.src/`. Es una gran ventaja de @vue/cli (y webpack), ya que no tenemos que lidiar con rutas relativas, sabemos que `@/` siempre refiere ese directorio y no va a cambiar. De esta forma, si movemos archivos de lugar, no tenemos que ocuparnos de cambiar manualmente las rutas de los `import`. Si bien no es obligatorio, recomiendo utilizarlo siempre que podamos. 44 | 45 | 1. Vamos tambien a agregar la funcion `data` con dos propidades: `assets` (array) y `isLoading` (boolean): 46 | 47 | ```html 48 | 49 | 63 | ``` 64 | 65 | 3. Ahora vamos a crear el *hook* `created()` en el componente y haremos una llamada a `getAssets()` dentro del mismo. 66 | 67 | ```html 68 | 69 | 91 | ``` 92 | 93 | Si inspeccionamos la documentación de Coincap o usamos el utilidad *Network* de las herramientas de desarrollo del browser, podemos ver que la lista de assets viene dentro de un objeto llamado `data`. Es por eso que cuando se resuelve la *promise* `getAssets()`, asignamos el valor de `data` a la lista de assets (usando destructuring). Tambien cambiamos el valor de la propiedad `isLoading` a `false`. 94 | 95 | > 👀 Usamos el método `.then()` luego de llamar a `getAssets()` ya que esta función usa internamente `fetch`, el cual esta basado en *promises*. 96 | 97 | > 🚨 Es importante usar *arrow function* para manejar las promesas ya que necesitamos mantener el valor lexico del objeto `this`. 98 | 99 | > 👌 Estamos utilizando destructuring en `.then({ data })` para obtener un acceso directo a la propiedad `data`. El equivalente seria: `res => this.assets = res.data`. 100 | 101 | ![build](../img/networking.gif) 102 | 103 | 1. Para terminar un poco el ejercicio y mostrar la informacion obtenida en la vista, vamos a agregar un poco de HTML y un poco de magia de Vue. Primero agregamos un elemento para indicar que el contenido esta cargando. Este elemento tiene un directiva `v-if`, por lo tanto se va mostrar si y solo si, `isLoading` es igual `true`. 104 | 105 | ```html 106 | 107 | 112 | ``` 113 | 114 | 1. Ahora vamos a crear una tabla con un elemento `` que usa ladirectiva `v-for`. Con esto, logramos representar cada uno de los assets obtenidos por la API. Al contrario del "Cargando...", la tabla solo se muestra cuando `isLoading` es igual a `false`, es por eso que agregamos la directiva v-else a la tabla. 115 | 116 | ```html 117 | 118 | 139 | ``` 140 | 141 | En la tabla vamos a mostrar solo 3 propiedades de cada asset: `symbol`, `name` y `priceUsd`. Por otro lado usamos el `id` como identificador univoco para `key` y ademas agregamos un poco JavaScript para formatear el valor de `priceUsd` y evitar un número muy largo: `parseFloat(a.priceUsd).toFixed(2)`. 142 | 143 | ![build](../img/loading.gif) 144 | 145 | > Todos los *hooks* se implementan de la misma manera, se agrega una función con el nombre del *hook* dentro del `vm` y se ejecuta el código que se requiera. Simplemente tengan en cuenta las limitaciones y características de cada uno. 146 | 147 | > Los componentes tienen una propiedad `name` en el cual podemos definir el nombre del componente. La propiedad es optativa pero es recomendable de usar ya que puede facilitarnos la tarea al momento de hacer *debug*. Recomiendo usarla siempre y colocarle el mismo nombre que tiene el archivo. 148 | 149 | ___ 150 | 151 | ### 🤓 Extras 152 | 153 | En una aplicación real, deberiamos manejar el posible error que pueda ocurrir cuando interactuamos con Coincap, para eso te invito a que experimentes un poco y muestres un mensaje de error cuando la interaccion con el servicio falla. Una pista, tenes que usar el metodo `catch` de la *promise* y podrías usar una propiedad nueva en `data` para saber cuando mostrar el mensaje de error al usuario. 154 | 155 | 156 | ### 📝 [Solución](https://github.com/ianaya89/vue-coins/tree/10) 157 | 158 | [⏪](https://github.com/ianaya89/workshop-vuejs/blob/master/ex/9.md) [⏩](https://github.com/ianaya89/workshop-vuejs/blob/master/ex/11.md) 159 | -------------------------------------------------------------------------------- /ex/11.md: -------------------------------------------------------------------------------- 1 | # 👀 *Computed & Watch* 2 | 3 | En algunos casos necesitamos mostrar tanta información que el template (HTML) puede ponerse un poco engorroso. En otros casos la información no es abundante pero si el proceso para *parsearla* o formatearla. Para este tipo de problemas Vue nos ofrece dos soluciones diferentes pero parecidas: *Computed Properties* & *Watchers*. 4 | 5 | ## Computed 6 | 7 | Las propiedades computadas son aquellas que se crean a partir de los cambios que puedan efectuarse en una o más propiedades del `vm`. Esto quiere decir, que podemos tener una propiedad dinámica cuyo valor va a calcularse cada vez que otra/s propiedad/es cambien su/s valore/s. 8 | 9 | En este caso, vamos a usar una propiedad computada para hacer un filtro en tiempo real sobre la tabla de assets. 10 | 11 | 1. Dentro del `vm` del componente `CoinList`, vamos a agregar una propiedad llamada computed con una función llamada `filteredAssets`. Tambien vamos a agregar a `data` una propiedad llamada `search`. 12 | 13 | ```html 14 | 48 | ``` 49 | 50 | `filteredAssets()` como todas las *computed properties*, **son funciones que devuelven un valor**. 51 | En este caso lo que estamos haciendo es filtrar la lista de assets en base al valor de la propiedad `search`. Como dentro de esta función estamos usando las propiedades `assets` y `search`, Vue se va a encargar de "computar" los valores y obtener un nuevo valor, cada vez que los valores de ambas variables se modifiquen. 52 | 53 | 1. Para usar esta propiedad en nuestro template vamos primero a agregar un input con la directiva `v-model` linkeada a la propiedad `search`. De esta forma, logramos que cada vez que se modifique el valor del input vamos a poder actualizar la lista de `assets` y mostrar solo los que coinciden con el valor de la búsqueda. Por otro lado tenemos que modificar la directiva `v-for` para que en lugar de usar la lista completa de assets use la nueva *computed property*. 54 | 55 | ```html 56 | 77 | ``` 78 | 79 | > 👌 Como habras notado, dentro de `