[{"data":1,"prerenderedAt":7256},["ShallowReactive",2],{"blog-post-getting-started-vue-vite-es":3,"blog-post-adjacent-getting-started-vue-vite-es":6581},{"id":4,"title":5,"author":6,"body":7,"date":6563,"description":13,"extension":6564,"image":6565,"lastmod":6566,"meta":6567,"navigation":1869,"order":130,"path":6568,"seo":6569,"sitemap":6570,"slug":6573,"stem":6574,"summary":6575,"tags":6576,"__hash__":6580},"content_es\u002Fblog\u002Fblog\u002Fgetting-started-vue-vite.md","Comenzando con Vue 3 y Vite","David Deras",{"type":8,"value":9,"toc":6543},"minimark",[10,14,17,20,25,28,74,77,87,89,93,102,105,108,110,114,117,141,152,163,166,175,178,187,190,270,273,281,301,304,307,310,318,323,337,343,355,361,376,382,396,405,412,440,443,451,460,462,466,469,738,745,753,767,772,850,854,857,868,1275,1285,1290,1790,1797,1804,1811,1822,1824,1828,1838,2047,2050,2111,2118,2373,2390,2396,2748,2761,2766,3019,3048,3051,3078,3086,3095,3106,3108,3111,3113,3117,3120,3123,3129,3342,3356,3701,3716,3719,3739,3745,3747,3751,3754,3761,3767,4029,4044,4050,4272,4281,4598,4604,4607,4630,4634,4644,4654,4663,4667,4673,4718,4721,4744,4748,4755,4762,4765,4796,4799,4801,4805,4812,4825,4828,4904,4914,4920,4923,4946,4948,4952,4961,4970,4973,4991,4997,5246,5253,5294,5301,5547,5554,5566,5571,6176,6182,6189,6202,6204,6208,6211,6216,6229,6238,6245,6250,6265,6288,6300,6320,6338,6357,6362,6374,6384,6389,6424,6427,6430,6439,6442,6465,6468,6484,6486,6490,6493,6533,6535,6538,6540],[11,12,13],"p",{},"En esta guía, exploraremos cómo iniciar un proyecto moderno con Vue 3 y Vite, explicaremos la estructura del proyecto, como funciona una aplicación Vue, el router, Pinia, los composables, veremos algunas buenas prácticas para desarrollar aplicaciones escalables y mantenibles, y como extra publicaremos el proyecto en GitHub y veremos cómo instalar Tailwind CSS v4 para obtener estilos rápidos y responsivos.",[15,16],"table-of-contents",{},[18,19],"hr",{},[21,22,24],"h2",{"id":23},"configurando-el-entorno","Configurando el entorno",[11,26,27],{},"Antes de continuar, debemos tener:",[29,30,31,50,58,66],"ul",{},[32,33,34,35,39,40,49],"li",{},"Node.js, cualquier versión ",[36,37,38],"strong",{},"LTS",". Recomiendo acostumbrarse a utilizar ",[41,42,48],"a",{"target":43,"href":44,"rel":45},"_blank","https:\u002F\u002Fgithub.com\u002Fcoreybutler\u002Fnvm-windows",[46,47],"noopener","noreferrer","nvm"," para manejar múltiples versiones de Node.",[32,51,52,53,57],{},"Un gestor de paquetes (aquí usaremos ",[54,55,56],"code",{},"npm",", que ya se instala con Node.js).",[32,59,60,65],{},[41,61,64],{"target":43,"href":62,"rel":63},"https:\u002F\u002Fcode.visualstudio.com\u002F",[46,47],"VS Code"," actualizado",[32,67,68,73],{},[41,69,72],{"target":43,"href":70,"rel":71},"https:\u002F\u002Fwww.desarrollolibre.net\u002Fblog\u002Fprogramacion-basica\u002Fla-guia-de-git-que-nunca-tuve",[46,47],"Git configurado"," correctamente",[11,75,76],{},"Además, instala la extensión oficial de Vue.js para VS Code:",[29,78,79],{},[32,80,81,86],{},[41,82,85],{"target":43,"href":83,"rel":84},"https:\u002F\u002Fmarketplace.visualstudio.com\u002Fitems?itemName=Vue.volar",[46,47],"Vue.js (Volar)",".\nMás adelante exploraremos otros plugins útiles como ESLint, Prettier y Tailwind CSS IntelliSense.",[18,88],{},[21,90,92],{"id":91},"javascript-o-typescript","¿JavaScript o TypeScript?",[11,94,95,96,101],{},"Vue 3 tiene un soporte bastante bueno para TypeScript, puedes usarlo teniendo en cuenta la ",[41,97,100],{"target":43,"href":98,"rel":99},"https:\u002F\u002Fvuejs.org\u002Fguide\u002Ftypescript\u002Foverview.html",[46,47],"guía de uso oficial",".",[11,103,104],{},"No necesitas usar TypeScript en todos tus proyectos, especialmente si estás comenzando o solo quieres experimentar. Asi que mi recomendación es que valores tu contexto, la aplicación y tu equipo (si estás trabajando en uno).",[11,106,107],{},"En esta guía usaremos JavaScript para mantener las cosas simples.",[18,109],{},[21,111,113],{"id":112},"creando-el-proyecto-con-vite","Creando el proyecto con Vite",[11,115,116],{},"La forma más rápida de iniciar un proyecto Vue 3 con Vite es usando el comando (puedes ejecutarlo en cualquier carpeta donde quieras crear el proyecto, utiliza la terminal integrada de VS Code o tu terminal favorita):",[118,119,124],"pre",{"className":120,"code":121,"language":122,"meta":123,"style":123},"language-bash shiki shiki-themes vitesse-light vitesse-dark","npm create vue@latest\n","bash","",[54,125,126],{"__ignoreMap":123},[127,128,131,134,138],"span",{"class":129,"line":130},"line",1,[127,132,56],{"class":133},"s_xSY",[127,135,137],{"class":136},"spP0B"," create",[127,139,140],{"class":136}," vue@latest\n",[11,142,143,144,147,148,151],{},"Si es primera vez que lo usas, te preguntará si deseas instalar el paquete ",[54,145,146],{},"create-vue",". Responde que sí (escribimos ",[54,149,150],{},"y"," y damos ENTER).",[11,153,154,159],{},[155,156],"img",{"alt":157,"src":158},"Instalando create-vue","\u002Fblog\u002Fgetting-started-vue-vite\u002Fshared\u002Finstall-create-vue-package.webp",[160,161,162],"em",{},"Instalando paquete: create-vue",[11,164,165],{},"Nos preguntará por el nombre del proyecto, escribe el nombre que quieras:",[11,167,168,172],{},[155,169],{"alt":170,"src":171},"Nombre del proyecto","\u002Fblog\u002Fgetting-started-vue-vite\u002Fshared\u002Fproject-name.webp",[160,173,174],{},"Asígnale un nombre a tu proyecto",[11,176,177],{},"Luego selecciona las opciones que necesites:",[11,179,180,184],{},[155,181],{"alt":182,"src":183},"Opciones del proyecto","\u002Fblog\u002Fgetting-started-vue-vite\u002Fshared\u002Fproject-options.webp",[160,185,186],{},"Features disponibles al crear una app Vue",[11,188,189],{},"Vamos punto por punto (tal como se muestra en la imagen, nos movemos con las flechas y seleccionamos con la barra espaciadora):",[191,192,193,199,210,222,228,234,258,264],"ol",{},[32,194,195,198],{},[36,196,197],{},"TypeScript",": como mencionamos antes, usaremos JavaScript, así que ignoramos.",[32,200,201,204,205,101],{},[36,202,203],{},"JSX Support",": no usaremos ",[41,206,209],{"target":43,"href":207,"rel":208},"https:\u002F\u002Fkinsta.com\u002Fes\u002Fblog\u002Fque-es-jsx\u002F",[46,47],"JSX",[32,211,212,215,216,221],{},[36,213,214],{},"Router (SPA development)",": Vue Router es esencial para trabajar con Vue como SPA (Single Page Application). No ahondaremos en temas de ",[41,217,220],{"target":43,"href":218,"rel":219},"https:\u002F\u002Fwww.geeksforgeeks.org\u002Fblogs\u002Fspa-vs-mpa-which-one-is-better-for-you\u002F",[46,47],"SPA vs MPA",", solo ten presente que Vue funciona como una SPA por defecto. Selecciona esta opción.",[32,223,224,227],{},[36,225,226],{},"Pinia (state management)",": es la librería oficial para el manejo de estado. Nos ayudará a manejar datos compartidos entre componentes. Selecciona esta opción.",[32,229,230,233],{},[36,231,232],{},"Vitest (unit testing)",": es el framework de testing recomendado para proyectos con Vite. No lo usaremos en esta guía.",[32,235,236,239,240,245,246,251,252,257],{},[36,237,238],{},"End-to-End Testing",": nos permitirá elegir e integrar una herramienta para pruebas E2E (",[41,241,244],{"target":43,"href":242,"rel":243},"https:\u002F\u002Fplaywright.dev\u002F",[46,47],"Playwright",", ",[41,247,250],{"target":43,"href":248,"rel":249},"https:\u002F\u002Fwww.cypress.io\u002F",[46,47],"Cypress"," o ",[41,253,256],{"target":43,"href":254,"rel":255},"https:\u002F\u002Fnightwatchjs.org\u002F",[46,47],"Nightwatch","). No lo usaremos en esta guía.",[32,259,260,263],{},[36,261,262],{},"ESLint (error prevention)",": es una herramienta para mantener la calidad del código, ayudando a detectar errores y mantener un estilo consistente. Recomiendo mucho su uso, aunque es importante personalizarlo según tu equipo y proyecto. La seleccionaremos para explorarla un poco más adelante.",[32,265,266,269],{},[36,267,268],{},"Prettier (code formatting)",": es una herramienta para formatear el código automáticamente. En este caso la seleccionaremos también para explorarla.",[11,271,272],{},"Presionamos ENTER y ahora nos preguntará sobre algunas features experimentales de Vite:",[11,274,275,279],{},[155,276],{"alt":277,"src":278},"Features experimentales de Vite","\u002Fblog\u002Fgetting-started-vue-vite\u002Fshared\u002Fproject-experimental-options.webp",[160,280,277],{},[191,282,283,295],{},[32,284,285,288,289,294],{},[36,286,287],{},"Oxlint",": es un nuevo linter, parte de ",[41,290,293],{"target":43,"href":291,"rel":292},"https:\u002F\u002Foxc.rs\u002F",[46,47],"OXC",", una nueva colección de herramientas de javascript escritas en Rust, Oxlint es en extremo rápido y promete bastante, sin embargo como se menciona en su web, aún tiene sus detalles, así que por ahora recomiendo seguir usando ESLint. Ignoramos esta opción.",[32,296,297,300],{},[36,298,299],{},"rolldown vite (experimental)",": Rolldown-vite es una bifurcación de Vite que utiliza Rolldown en lugar de Rollup y esbuild, con el objetivo de obtener el máximo rendimiento. Pronto se convertirá en el paquete por defecto, por ahora ignoremos esta opción.",[11,302,303],{},"Continuamos presionando ENTER.",[11,305,306],{},"Nos preguntará si queremos empezar con un proyecto totalmente en blanco o con ejemplos. Si es tu primera vez, te recomiendo seleccionar \"No\" para que puedas ver una estructura básica con ejemplos. Esa será la opción que seleccionaremos aquí.",[11,308,309],{},"Vite creará la estructura inicial del proyecto y nos dará algunos comandos útiles, vamos ejecutando uno por uno:",[11,311,312,316],{},[155,313],{"alt":314,"src":315},"Proyecto creado","\u002Fblog\u002Fgetting-started-vue-vite\u002Fshared\u002Fproject-created.webp",[160,317,314],{},[191,319,320],{},[32,321,322],{},"Primero navegamos a la carpeta del proyecto:",[118,324,326],{"className":120,"code":325,"language":122,"meta":123,"style":123},"cd nombre-del-proyecto\n",[54,327,328],{"__ignoreMap":123},[127,329,330,334],{"class":129,"line":130},[127,331,333],{"class":332},"sHLBJ","cd",[127,335,336],{"class":136}," nombre-del-proyecto\n",[191,338,340],{"start":339},2,[32,341,342],{},"Instalamos las dependencias (esto puede tardar unos minutos dependiendo de tu conexión):",[118,344,346],{"className":120,"code":345,"language":122,"meta":123,"style":123},"npm install\n",[54,347,348],{"__ignoreMap":123},[127,349,350,352],{"class":129,"line":130},[127,351,56],{"class":133},[127,353,354],{"class":136}," install\n",[191,356,358],{"start":357},3,[32,359,360],{},"Este comando es para correr Prettier, no tendrá ningún efecto porque no hemos modificado nada aún, pero es bueno tenerlo presente:",[118,362,364],{"className":120,"code":363,"language":122,"meta":123,"style":123},"npm run format\n",[54,365,366],{"__ignoreMap":123},[127,367,368,370,373],{"class":129,"line":130},[127,369,56],{"class":133},[127,371,372],{"class":136}," run",[127,374,375],{"class":136}," format\n",[191,377,379],{"start":378},4,[32,380,381],{},"Finalmente, iniciamos el servidor de desarrollo:",[118,383,385],{"className":120,"code":384,"language":122,"meta":123,"style":123},"npm run dev\n",[54,386,387],{"__ignoreMap":123},[127,388,389,391,393],{"class":129,"line":130},[127,390,56],{"class":133},[127,392,372],{"class":136},[127,394,395],{"class":136}," dev\n",[11,397,398,402],{},[155,399],{"alt":400,"src":401},"Servidor de desarrollo corriendo","\u002Fblog\u002Fgetting-started-vue-vite\u002Fshared\u002Fdev-server-running.webp",[160,403,404],{},"Servidor de desarrollo levantado",[11,406,407,408,411],{},"Vite corre el servidor de desarrollo en ",[54,409,410],{},"http:\u002F\u002Flocalhost:5173\u002F"," (el puerto puede variar si el 5173 ya está en uso (5174, 5175, etc.) ).",[413,414,415,418,432],"blockquote",{},[11,416,417],{},"El puerto 5173 es un guiño al propio Vite:",[29,419,420,423,426,429],{},[32,421,422],{},"5 = V",[32,424,425],{},"1 = I",[32,427,428],{},"7 = T",[32,430,431],{},"3 = E",[11,433,434,435,101],{},"Aunque más allá de eso, Vite utiliza el puerto 5173 porque es poco habitual en entornos de desarrollo, lo que reduce la probabilidad de conflictos con otros servidores locales. Vía ",[41,436,439],{"target":43,"href":437,"rel":438},"https:\u002F\u002Fmedium.com\u002F@bishakhghosh0\u002Fwhy-localhost-5173-is-every-frontend-developers-best-friend-b3bb5b6fb1db",[46,47],"Why localhost:5173 is Every Frontend Developer’s Best Friend",[11,441,442],{},"Si entramos a esa URL en nuestro navegador, veremos la app Vue corriendo:",[11,444,445,449],{},[155,446],{"alt":447,"src":448},"App Vue corriendo","\u002Fblog\u002Fgetting-started-vue-vite\u002Fshared\u002Fvue-app-running.webp",[160,450,447],{},[11,452,453,454,459],{},"El equipo de Vue comparte varios recursos oficiales para aprender más sobre el framework, comenzando por la ",[41,455,458],{"target":43,"href":456,"rel":457},"https:\u002F\u002Fvuejs.org\u002Fguide\u002Fintroduction.html",[46,47],"documentación oficial",". Explora cada enlace para aprender y conocer sobre todo el ecosistema.",[18,461],{},[21,463,465],{"id":464},"estructura-del-proyecto","Estructura del proyecto",[11,467,468],{},"Pasemos a ver la estructura inicial, abre el proyecto en tu editor de código favorito (recomiendo VS Code):",[118,470,472],{"className":120,"code":471,"language":122,"meta":123,"style":123},"my-vue-app\u002F\n├── .vscode\u002F              # (Si estás en VS Code) Configuración de Visual Studio Code\n├── node_modules\u002F         # Dependencias del proyecto, generadas al instalar los paquetes\n├── public\u002F               # Archivos estáticos\n├── src\u002F                  # Código fuente de la aplicación\n│   ├── assets\u002F           # Recursos como imágenes y estilos\n│   ├── components\u002F       # Componentes Vue reutilizables\n│   ├── router\u002F           # Configuración de Vue Router\n│   ├── store\u002F            # Configuración de Pinia\n│   ├── views\u002F            # Vistas para las rutas\n│   ├── App.vue           # Componente raíz de la aplicación\n│   └── main.js           # Punto de entrada de la aplicación\n├── .editorconfig         # Configuración de EditorConfig\n├── .gitattributes        # Configuración de Git\n├── .gitignore            # Archivos y carpetas ignoradas por Git\n├── .prettierrc.json      # Configuración de Prettier\n├── eslint.config.js      # Configuración de ESLint\n├── index.html            # Archivo HTML principal\n├── jsconfig.json         # Configuración de JavaScript para el editor\n├── package-lock.json     # Versiones exactas de las dependencias (autogenerado)\n├── package.json          # Información del proyecto y scripts\n├── README.md             # Documentación del proyecto\n└── vite.config.js        # Configuración de Vite\n",[54,473,474,479,491,501,511,522,537,550,563,576,589,602,616,627,638,649,660,671,682,693,704,715,726],{"__ignoreMap":123},[127,475,476],{"class":129,"line":130},[127,477,478],{"class":133},"my-vue-app\u002F\n",[127,480,481,484,487],{"class":129,"line":339},[127,482,483],{"class":133},"├──",[127,485,486],{"class":136}," .vscode\u002F",[127,488,490],{"class":489},"snYqZ","              # (Si estás en VS Code) Configuración de Visual Studio Code\n",[127,492,493,495,498],{"class":129,"line":357},[127,494,483],{"class":133},[127,496,497],{"class":136}," node_modules\u002F",[127,499,500],{"class":489},"         # Dependencias del proyecto, generadas al instalar los paquetes\n",[127,502,503,505,508],{"class":129,"line":378},[127,504,483],{"class":133},[127,506,507],{"class":136}," public\u002F",[127,509,510],{"class":489},"               # Archivos estáticos\n",[127,512,514,516,519],{"class":129,"line":513},5,[127,515,483],{"class":133},[127,517,518],{"class":136}," src\u002F",[127,520,521],{"class":489},"                  # Código fuente de la aplicación\n",[127,523,525,528,531,534],{"class":129,"line":524},6,[127,526,527],{"class":133},"│",[127,529,530],{"class":136},"   ├──",[127,532,533],{"class":136}," assets\u002F",[127,535,536],{"class":489},"           # Recursos como imágenes y estilos\n",[127,538,540,542,544,547],{"class":129,"line":539},7,[127,541,527],{"class":133},[127,543,530],{"class":136},[127,545,546],{"class":136}," components\u002F",[127,548,549],{"class":489},"       # Componentes Vue reutilizables\n",[127,551,553,555,557,560],{"class":129,"line":552},8,[127,554,527],{"class":133},[127,556,530],{"class":136},[127,558,559],{"class":136}," router\u002F",[127,561,562],{"class":489},"           # Configuración de Vue Router\n",[127,564,566,568,570,573],{"class":129,"line":565},9,[127,567,527],{"class":133},[127,569,530],{"class":136},[127,571,572],{"class":136}," store\u002F",[127,574,575],{"class":489},"            # Configuración de Pinia\n",[127,577,579,581,583,586],{"class":129,"line":578},10,[127,580,527],{"class":133},[127,582,530],{"class":136},[127,584,585],{"class":136}," views\u002F",[127,587,588],{"class":489},"            # Vistas para las rutas\n",[127,590,592,594,596,599],{"class":129,"line":591},11,[127,593,527],{"class":133},[127,595,530],{"class":136},[127,597,598],{"class":136}," App.vue",[127,600,601],{"class":489},"           # Componente raíz de la aplicación\n",[127,603,605,607,610,613],{"class":129,"line":604},12,[127,606,527],{"class":133},[127,608,609],{"class":136},"   └──",[127,611,612],{"class":136}," main.js",[127,614,615],{"class":489},"           # Punto de entrada de la aplicación\n",[127,617,619,621,624],{"class":129,"line":618},13,[127,620,483],{"class":133},[127,622,623],{"class":136}," .editorconfig",[127,625,626],{"class":489},"         # Configuración de EditorConfig\n",[127,628,630,632,635],{"class":129,"line":629},14,[127,631,483],{"class":133},[127,633,634],{"class":136}," .gitattributes",[127,636,637],{"class":489},"        # Configuración de Git\n",[127,639,641,643,646],{"class":129,"line":640},15,[127,642,483],{"class":133},[127,644,645],{"class":136}," .gitignore",[127,647,648],{"class":489},"            # Archivos y carpetas ignoradas por Git\n",[127,650,652,654,657],{"class":129,"line":651},16,[127,653,483],{"class":133},[127,655,656],{"class":136}," .prettierrc.json",[127,658,659],{"class":489},"      # Configuración de Prettier\n",[127,661,663,665,668],{"class":129,"line":662},17,[127,664,483],{"class":133},[127,666,667],{"class":136}," eslint.config.js",[127,669,670],{"class":489},"      # Configuración de ESLint\n",[127,672,674,676,679],{"class":129,"line":673},18,[127,675,483],{"class":133},[127,677,678],{"class":136}," index.html",[127,680,681],{"class":489},"            # Archivo HTML principal\n",[127,683,685,687,690],{"class":129,"line":684},19,[127,686,483],{"class":133},[127,688,689],{"class":136}," jsconfig.json",[127,691,692],{"class":489},"         # Configuración de JavaScript para el editor\n",[127,694,696,698,701],{"class":129,"line":695},20,[127,697,483],{"class":133},[127,699,700],{"class":136}," package-lock.json",[127,702,703],{"class":489},"     # Versiones exactas de las dependencias (autogenerado)\n",[127,705,707,709,712],{"class":129,"line":706},21,[127,708,483],{"class":133},[127,710,711],{"class":136}," package.json",[127,713,714],{"class":489},"          # Información del proyecto y scripts\n",[127,716,718,720,723],{"class":129,"line":717},22,[127,719,483],{"class":133},[127,721,722],{"class":136}," README.md",[127,724,725],{"class":489},"             # Documentación del proyecto\n",[127,727,729,732,735],{"class":129,"line":728},23,[127,730,731],{"class":133},"└──",[127,733,734],{"class":136}," vite.config.js",[127,736,737],{"class":489},"        # Configuración de Vite\n",[11,739,740,741,744],{},"La estructura puede variar ligeramente dependiendo de las opciones seleccionadas al crear el proyecto (por ejemplo, si se incluye o no ESLint o Pinia). Además, si estás usando VS Code es probable que veas la carpeta ",[54,742,743],{},".vscode\u002F"," con configuraciones específicas para el editor y que algunos archivos los veas \"agrupados\":",[11,746,747,751],{},[155,748],{"alt":749,"src":750},"Estructura del proyecto en VS Code","\u002Fblog\u002Fgetting-started-vue-vite\u002Fshared\u002Fproject-structure-nested.webp",[160,752,749],{},[11,754,755,756,759,760,763,764,101],{},"Esto es solo una forma visual que tiene VS Code para organizar los archivos, puedes mostrarlos individualmente (opción que prefiero) cambiando el valor de ",[54,757,758],{},"\"explorer.fileNesting.enabled\""," a ",[54,761,762],{},"false"," en el archivo ",[54,765,766],{},".vscode\\settings.json",[768,769,771],"h3",{"id":770},"entendiendo-las-carpetas-principales","Entendiendo las carpetas principales",[29,773,774,780],{},[32,775,776,779],{},[54,777,778],{},"public\u002F",": Aquí van los archivos estáticos que no serán procesados por Vite. Puedes colocar imágenes, fuentes u otros recursos que necesites servir directamente.",[32,781,782,785,786],{},[54,783,784],{},"src\u002F",": Esta es la carpeta más importante, contiene todo el código fuente de tu aplicación. Aquí tenemos:\n",[29,787,788,794,800,812,828,838,844],{},[32,789,790,793],{},[54,791,792],{},"assets\u002F",": Aquí van los recursos como imágenes, fuentes y estilos CSS.",[32,795,796,799],{},[54,797,798],{},"components\u002F",": Aquí van los componentes Vue globales, reutilizables, que puedes usar en diferentes partes de tu aplicación, por ejemplo, botones, tarjetas, modales, etc.",[32,801,802,805,806,811],{},[54,803,804],{},"router\u002F",": Aquí va la configuración de ",[41,807,810],{"href":808,"target":43,"rel":809},"https:\u002F\u002Frouter.vuejs.org\u002F",[46,47],"Vue Router",", donde defines las rutas de tu aplicación y cómo se navega entre ellas, así como la posible configuración de guards, lazy loading, etc.",[32,813,814,805,817,822,823],{},[54,815,816],{},"store\u002F",[41,818,821],{"href":819,"target":43,"rel":820},"https:\u002F\u002Fpinia.vuejs.org\u002F",[46,47],"Pinia",", donde defines el ",[41,824,827],{"href":825,"target":43,"rel":826},"https:\u002F\u002Fkinsta.com\u002Fes\u002Fblog\u002Fvue-pinia\u002F",[46,47],"estado global de tu aplicación. ",[32,829,830,833,834,837],{},[54,831,832],{},"views\u002F",": Aquí van las vistas principales que corresponden a las rutas definidas en Vue Router. Cada vista generalmente representa una página completa, caso contrario a los componentes que son partes más pequeñas y reutilizables. A final todos son archivos ",[54,835,836],{},".vue",", por lo que la diferencia radica en su propósito y uso.",[32,839,840,843],{},[54,841,842],{},"App.vue",": Este es el componente raíz de tu aplicación, donde se monta todo (ya explicaremos más adelante).",[32,845,846,849],{},[54,847,848],{},"main.js",": Este es el punto de entrada de tu aplicación, donde se inicializa Vue, se configuran los plugins (como Vue Router y Pinia) y se monta la aplicación en el DOM.",[768,851,853],{"id":852},"es-suficiente-esta-estructura","¿Es suficiente esta estructura?",[11,855,856],{},"Es una estructura básica que por ahora está bien. A medida que tu aplicación crezca normalmente se busca organizar mejor el código. Aquí hay dos propuestas:",[29,858,859],{},[32,860,861,862,864,865,867],{},"Crear subcarpetas por módulo\u002Ffuncionalidad dentro de las distintas carpetas, como ",[54,863,798],{}," y ",[54,866,832],{},". Por ejemplo:",[118,869,871],{"className":120,"code":870,"language":122,"meta":123,"style":123},"my-vue-app\u002F\n├── src\u002F\n│   ├── assets\u002F\n│   ├── components\u002F\n│   │   ├── auth\u002F\n│   │   │   ├── LoginForm.vue\n│   │   │   └── RegisterForm.vue\n│   │   ├── dashboard\u002F\n│   │   │   ├── StatsCard.vue\n│   │   │   └── ChartWidget.vue\n│   │   └── shared\u002F\n│   │       ├── BaseButton.vue\n│   │       └── BaseModal.vue\n│   │\n│   ├── views\u002F\n│   │   ├── auth\u002F\n│   │   │   ├── LoginView.vue\n│   │   │   └── RegisterView.vue\n│   │   ├── dashboard\u002F\n│   │   │   └── DashboardView.vue\n│   │   └── home\u002F\n│   │       └── HomeView.vue\n│   │\n│   ├── store\u002F\n│   │   ├── auth\u002F\n│   │   │   └── auth.store.js\n│   │   ├── dashboard\u002F\n│   │   │   └── dashboard.store.js\n│   │   └── shared\u002F\n│   │       └── ui.store.js\n│   │\n│   ├── router\u002F\n│   │   ├── auth.routes.js\n│   │   ├── dashboard.routes.js\n│   │   └── index.js\n│   │\n│   ├── ...\n├── ...\n",[54,872,873,877,884,893,902,914,927,940,951,964,977,988,1000,1012,1019,1028,1038,1051,1064,1074,1087,1098,1109,1115,1125,1136,1150,1161,1175,1186,1198,1205,1215,1227,1239,1251,1258,1268],{"__ignoreMap":123},[127,874,875],{"class":129,"line":130},[127,876,478],{"class":133},[127,878,879,881],{"class":129,"line":339},[127,880,483],{"class":133},[127,882,883],{"class":136}," src\u002F\n",[127,885,886,888,890],{"class":129,"line":357},[127,887,527],{"class":133},[127,889,530],{"class":136},[127,891,892],{"class":136}," assets\u002F\n",[127,894,895,897,899],{"class":129,"line":378},[127,896,527],{"class":133},[127,898,530],{"class":136},[127,900,901],{"class":136}," components\u002F\n",[127,903,904,906,909,911],{"class":129,"line":513},[127,905,527],{"class":133},[127,907,908],{"class":136},"   │",[127,910,530],{"class":136},[127,912,913],{"class":136}," auth\u002F\n",[127,915,916,918,920,922,924],{"class":129,"line":524},[127,917,527],{"class":133},[127,919,908],{"class":136},[127,921,908],{"class":136},[127,923,530],{"class":136},[127,925,926],{"class":136}," LoginForm.vue\n",[127,928,929,931,933,935,937],{"class":129,"line":539},[127,930,527],{"class":133},[127,932,908],{"class":136},[127,934,908],{"class":136},[127,936,609],{"class":136},[127,938,939],{"class":136}," RegisterForm.vue\n",[127,941,942,944,946,948],{"class":129,"line":552},[127,943,527],{"class":133},[127,945,908],{"class":136},[127,947,530],{"class":136},[127,949,950],{"class":136}," dashboard\u002F\n",[127,952,953,955,957,959,961],{"class":129,"line":565},[127,954,527],{"class":133},[127,956,908],{"class":136},[127,958,908],{"class":136},[127,960,530],{"class":136},[127,962,963],{"class":136}," StatsCard.vue\n",[127,965,966,968,970,972,974],{"class":129,"line":578},[127,967,527],{"class":133},[127,969,908],{"class":136},[127,971,908],{"class":136},[127,973,609],{"class":136},[127,975,976],{"class":136}," ChartWidget.vue\n",[127,978,979,981,983,985],{"class":129,"line":591},[127,980,527],{"class":133},[127,982,908],{"class":136},[127,984,609],{"class":136},[127,986,987],{"class":136}," shared\u002F\n",[127,989,990,992,994,997],{"class":129,"line":604},[127,991,527],{"class":133},[127,993,908],{"class":136},[127,995,996],{"class":136},"       ├──",[127,998,999],{"class":136}," BaseButton.vue\n",[127,1001,1002,1004,1006,1009],{"class":129,"line":618},[127,1003,527],{"class":133},[127,1005,908],{"class":136},[127,1007,1008],{"class":136},"       └──",[127,1010,1011],{"class":136}," BaseModal.vue\n",[127,1013,1014,1016],{"class":129,"line":629},[127,1015,527],{"class":133},[127,1017,1018],{"class":136},"   │\n",[127,1020,1021,1023,1025],{"class":129,"line":640},[127,1022,527],{"class":133},[127,1024,530],{"class":136},[127,1026,1027],{"class":136}," views\u002F\n",[127,1029,1030,1032,1034,1036],{"class":129,"line":651},[127,1031,527],{"class":133},[127,1033,908],{"class":136},[127,1035,530],{"class":136},[127,1037,913],{"class":136},[127,1039,1040,1042,1044,1046,1048],{"class":129,"line":662},[127,1041,527],{"class":133},[127,1043,908],{"class":136},[127,1045,908],{"class":136},[127,1047,530],{"class":136},[127,1049,1050],{"class":136}," LoginView.vue\n",[127,1052,1053,1055,1057,1059,1061],{"class":129,"line":673},[127,1054,527],{"class":133},[127,1056,908],{"class":136},[127,1058,908],{"class":136},[127,1060,609],{"class":136},[127,1062,1063],{"class":136}," RegisterView.vue\n",[127,1065,1066,1068,1070,1072],{"class":129,"line":684},[127,1067,527],{"class":133},[127,1069,908],{"class":136},[127,1071,530],{"class":136},[127,1073,950],{"class":136},[127,1075,1076,1078,1080,1082,1084],{"class":129,"line":695},[127,1077,527],{"class":133},[127,1079,908],{"class":136},[127,1081,908],{"class":136},[127,1083,609],{"class":136},[127,1085,1086],{"class":136}," DashboardView.vue\n",[127,1088,1089,1091,1093,1095],{"class":129,"line":706},[127,1090,527],{"class":133},[127,1092,908],{"class":136},[127,1094,609],{"class":136},[127,1096,1097],{"class":136}," home\u002F\n",[127,1099,1100,1102,1104,1106],{"class":129,"line":717},[127,1101,527],{"class":133},[127,1103,908],{"class":136},[127,1105,1008],{"class":136},[127,1107,1108],{"class":136}," HomeView.vue\n",[127,1110,1111,1113],{"class":129,"line":728},[127,1112,527],{"class":133},[127,1114,1018],{"class":136},[127,1116,1118,1120,1122],{"class":129,"line":1117},24,[127,1119,527],{"class":133},[127,1121,530],{"class":136},[127,1123,1124],{"class":136}," store\u002F\n",[127,1126,1128,1130,1132,1134],{"class":129,"line":1127},25,[127,1129,527],{"class":133},[127,1131,908],{"class":136},[127,1133,530],{"class":136},[127,1135,913],{"class":136},[127,1137,1139,1141,1143,1145,1147],{"class":129,"line":1138},26,[127,1140,527],{"class":133},[127,1142,908],{"class":136},[127,1144,908],{"class":136},[127,1146,609],{"class":136},[127,1148,1149],{"class":136}," auth.store.js\n",[127,1151,1153,1155,1157,1159],{"class":129,"line":1152},27,[127,1154,527],{"class":133},[127,1156,908],{"class":136},[127,1158,530],{"class":136},[127,1160,950],{"class":136},[127,1162,1164,1166,1168,1170,1172],{"class":129,"line":1163},28,[127,1165,527],{"class":133},[127,1167,908],{"class":136},[127,1169,908],{"class":136},[127,1171,609],{"class":136},[127,1173,1174],{"class":136}," dashboard.store.js\n",[127,1176,1178,1180,1182,1184],{"class":129,"line":1177},29,[127,1179,527],{"class":133},[127,1181,908],{"class":136},[127,1183,609],{"class":136},[127,1185,987],{"class":136},[127,1187,1189,1191,1193,1195],{"class":129,"line":1188},30,[127,1190,527],{"class":133},[127,1192,908],{"class":136},[127,1194,1008],{"class":136},[127,1196,1197],{"class":136}," ui.store.js\n",[127,1199,1201,1203],{"class":129,"line":1200},31,[127,1202,527],{"class":133},[127,1204,1018],{"class":136},[127,1206,1208,1210,1212],{"class":129,"line":1207},32,[127,1209,527],{"class":133},[127,1211,530],{"class":136},[127,1213,1214],{"class":136}," router\u002F\n",[127,1216,1218,1220,1222,1224],{"class":129,"line":1217},33,[127,1219,527],{"class":133},[127,1221,908],{"class":136},[127,1223,530],{"class":136},[127,1225,1226],{"class":136}," auth.routes.js\n",[127,1228,1230,1232,1234,1236],{"class":129,"line":1229},34,[127,1231,527],{"class":133},[127,1233,908],{"class":136},[127,1235,530],{"class":136},[127,1237,1238],{"class":136}," dashboard.routes.js\n",[127,1240,1242,1244,1246,1248],{"class":129,"line":1241},35,[127,1243,527],{"class":133},[127,1245,908],{"class":136},[127,1247,609],{"class":136},[127,1249,1250],{"class":136}," index.js\n",[127,1252,1254,1256],{"class":129,"line":1253},36,[127,1255,527],{"class":133},[127,1257,1018],{"class":136},[127,1259,1261,1263,1265],{"class":129,"line":1260},37,[127,1262,527],{"class":133},[127,1264,530],{"class":136},[127,1266,1267],{"class":136}," ...\n",[127,1269,1271,1273],{"class":129,"line":1270},38,[127,1272,483],{"class":133},[127,1274,1267],{"class":136},[11,1276,1277,1280,1281,1284],{},[36,1278,1279],{},"Puedes usar un enfoque similar a este"," en apps pequeñas o medianas, con poca gente trabajando, en las que quieres un poco más de orden sin complicarte demasiado y sin cambiar demasiado la estructura original que propone Vue. ",[36,1282,1283],{},"La limitante"," es que a medida que la app crece, puede volverse difícil manejar dependencias entre módulos y mantener el código organizado, porque todo está disperso en varias carpetas.",[29,1286,1287],{},[32,1288,1289],{},"En otros casos, puedes optar por una estructura basada en funcionalidades o módulos, donde cada uno tiene su propia carpeta que contiene componentes, vistas, y lógica relacionada. Por ejemplo:",[118,1291,1293],{"className":120,"code":1292,"language":122,"meta":123,"style":123},"my-vue-app\u002F\n├── src\u002F\n│   ├── modules\u002F\n│   │   ├── auth\u002F                     # Si el módulo es pequeño, puedes omitir la división en carpetas\n│   │   │   ├── components\u002F\n│   │   │   │   └── LoginForm.vue\n│   │   │   ├── views\u002F\n│   │   │   │   └── LoginView.vue\n│   │   │   ├── store\u002F\n│   │   │   │   └── auth.store.js\n│   │   │   ├── router\u002F\n│   │   │   │   └── auth.routes.js\n│   │   │   └── index.js\n│   │   │\n│   │   ├── dashboard\u002F\n│   │   │   ├── components\u002F\n│   │   │   ├── views\u002F\n│   │   │   ├── store\u002F\n│   │   │   ├── router\u002F\n│   │   │   └── index.js\n│   │   │\n│   │   └── users\u002F\n│   │       ├── components\u002F\n│   │       ├── views\u002F\n│   │       ├── store\u002F\n│   │       ├── router\u002F\n│   │       └── index.js\n│   │\n│   ├── shared\u002F\n│   │   ├── components\u002F\n│   │   │   ├── BaseButton.vue\n│   │   │   └── BaseModal.vue\n│   │   ├── composables\u002F\n│   │   │   └── useFetch.js\n│   │   ├── store\u002F\n│   │   │   └── ui.store.js\n│   │   ├── utils\u002F\n│   │   │   └── formatDate.js\n│   │   └── constants\u002F\n│   │       └── roles.js\n│   │\n│   ├── router\u002F\n│   │   └── index.js                # Archivo principal del router que importa las rutas de los módulos\n│   │                               # (los guards van aquí)\n│   ├── ...\n├── ...\n",[54,1294,1295,1299,1305,1314,1328,1340,1354,1366,1380,1392,1406,1418,1432,1444,1452,1462,1474,1486,1498,1510,1522,1530,1541,1551,1561,1571,1581,1591,1597,1605,1615,1627,1639,1650,1663,1673,1685,1696,1709,1721,1733,1740,1749,1764,1774,1783],{"__ignoreMap":123},[127,1296,1297],{"class":129,"line":130},[127,1298,478],{"class":133},[127,1300,1301,1303],{"class":129,"line":339},[127,1302,483],{"class":133},[127,1304,883],{"class":136},[127,1306,1307,1309,1311],{"class":129,"line":357},[127,1308,527],{"class":133},[127,1310,530],{"class":136},[127,1312,1313],{"class":136}," modules\u002F\n",[127,1315,1316,1318,1320,1322,1325],{"class":129,"line":378},[127,1317,527],{"class":133},[127,1319,908],{"class":136},[127,1321,530],{"class":136},[127,1323,1324],{"class":136}," auth\u002F",[127,1326,1327],{"class":489},"                     # Si el módulo es pequeño, puedes omitir la división en carpetas\n",[127,1329,1330,1332,1334,1336,1338],{"class":129,"line":513},[127,1331,527],{"class":133},[127,1333,908],{"class":136},[127,1335,908],{"class":136},[127,1337,530],{"class":136},[127,1339,901],{"class":136},[127,1341,1342,1344,1346,1348,1350,1352],{"class":129,"line":524},[127,1343,527],{"class":133},[127,1345,908],{"class":136},[127,1347,908],{"class":136},[127,1349,908],{"class":136},[127,1351,609],{"class":136},[127,1353,926],{"class":136},[127,1355,1356,1358,1360,1362,1364],{"class":129,"line":539},[127,1357,527],{"class":133},[127,1359,908],{"class":136},[127,1361,908],{"class":136},[127,1363,530],{"class":136},[127,1365,1027],{"class":136},[127,1367,1368,1370,1372,1374,1376,1378],{"class":129,"line":552},[127,1369,527],{"class":133},[127,1371,908],{"class":136},[127,1373,908],{"class":136},[127,1375,908],{"class":136},[127,1377,609],{"class":136},[127,1379,1050],{"class":136},[127,1381,1382,1384,1386,1388,1390],{"class":129,"line":565},[127,1383,527],{"class":133},[127,1385,908],{"class":136},[127,1387,908],{"class":136},[127,1389,530],{"class":136},[127,1391,1124],{"class":136},[127,1393,1394,1396,1398,1400,1402,1404],{"class":129,"line":578},[127,1395,527],{"class":133},[127,1397,908],{"class":136},[127,1399,908],{"class":136},[127,1401,908],{"class":136},[127,1403,609],{"class":136},[127,1405,1149],{"class":136},[127,1407,1408,1410,1412,1414,1416],{"class":129,"line":591},[127,1409,527],{"class":133},[127,1411,908],{"class":136},[127,1413,908],{"class":136},[127,1415,530],{"class":136},[127,1417,1214],{"class":136},[127,1419,1420,1422,1424,1426,1428,1430],{"class":129,"line":604},[127,1421,527],{"class":133},[127,1423,908],{"class":136},[127,1425,908],{"class":136},[127,1427,908],{"class":136},[127,1429,609],{"class":136},[127,1431,1226],{"class":136},[127,1433,1434,1436,1438,1440,1442],{"class":129,"line":618},[127,1435,527],{"class":133},[127,1437,908],{"class":136},[127,1439,908],{"class":136},[127,1441,609],{"class":136},[127,1443,1250],{"class":136},[127,1445,1446,1448,1450],{"class":129,"line":629},[127,1447,527],{"class":133},[127,1449,908],{"class":136},[127,1451,1018],{"class":136},[127,1453,1454,1456,1458,1460],{"class":129,"line":640},[127,1455,527],{"class":133},[127,1457,908],{"class":136},[127,1459,530],{"class":136},[127,1461,950],{"class":136},[127,1463,1464,1466,1468,1470,1472],{"class":129,"line":651},[127,1465,527],{"class":133},[127,1467,908],{"class":136},[127,1469,908],{"class":136},[127,1471,530],{"class":136},[127,1473,901],{"class":136},[127,1475,1476,1478,1480,1482,1484],{"class":129,"line":662},[127,1477,527],{"class":133},[127,1479,908],{"class":136},[127,1481,908],{"class":136},[127,1483,530],{"class":136},[127,1485,1027],{"class":136},[127,1487,1488,1490,1492,1494,1496],{"class":129,"line":673},[127,1489,527],{"class":133},[127,1491,908],{"class":136},[127,1493,908],{"class":136},[127,1495,530],{"class":136},[127,1497,1124],{"class":136},[127,1499,1500,1502,1504,1506,1508],{"class":129,"line":684},[127,1501,527],{"class":133},[127,1503,908],{"class":136},[127,1505,908],{"class":136},[127,1507,530],{"class":136},[127,1509,1214],{"class":136},[127,1511,1512,1514,1516,1518,1520],{"class":129,"line":695},[127,1513,527],{"class":133},[127,1515,908],{"class":136},[127,1517,908],{"class":136},[127,1519,609],{"class":136},[127,1521,1250],{"class":136},[127,1523,1524,1526,1528],{"class":129,"line":706},[127,1525,527],{"class":133},[127,1527,908],{"class":136},[127,1529,1018],{"class":136},[127,1531,1532,1534,1536,1538],{"class":129,"line":717},[127,1533,527],{"class":133},[127,1535,908],{"class":136},[127,1537,609],{"class":136},[127,1539,1540],{"class":136}," users\u002F\n",[127,1542,1543,1545,1547,1549],{"class":129,"line":728},[127,1544,527],{"class":133},[127,1546,908],{"class":136},[127,1548,996],{"class":136},[127,1550,901],{"class":136},[127,1552,1553,1555,1557,1559],{"class":129,"line":1117},[127,1554,527],{"class":133},[127,1556,908],{"class":136},[127,1558,996],{"class":136},[127,1560,1027],{"class":136},[127,1562,1563,1565,1567,1569],{"class":129,"line":1127},[127,1564,527],{"class":133},[127,1566,908],{"class":136},[127,1568,996],{"class":136},[127,1570,1124],{"class":136},[127,1572,1573,1575,1577,1579],{"class":129,"line":1138},[127,1574,527],{"class":133},[127,1576,908],{"class":136},[127,1578,996],{"class":136},[127,1580,1214],{"class":136},[127,1582,1583,1585,1587,1589],{"class":129,"line":1152},[127,1584,527],{"class":133},[127,1586,908],{"class":136},[127,1588,1008],{"class":136},[127,1590,1250],{"class":136},[127,1592,1593,1595],{"class":129,"line":1163},[127,1594,527],{"class":133},[127,1596,1018],{"class":136},[127,1598,1599,1601,1603],{"class":129,"line":1177},[127,1600,527],{"class":133},[127,1602,530],{"class":136},[127,1604,987],{"class":136},[127,1606,1607,1609,1611,1613],{"class":129,"line":1188},[127,1608,527],{"class":133},[127,1610,908],{"class":136},[127,1612,530],{"class":136},[127,1614,901],{"class":136},[127,1616,1617,1619,1621,1623,1625],{"class":129,"line":1200},[127,1618,527],{"class":133},[127,1620,908],{"class":136},[127,1622,908],{"class":136},[127,1624,530],{"class":136},[127,1626,999],{"class":136},[127,1628,1629,1631,1633,1635,1637],{"class":129,"line":1207},[127,1630,527],{"class":133},[127,1632,908],{"class":136},[127,1634,908],{"class":136},[127,1636,609],{"class":136},[127,1638,1011],{"class":136},[127,1640,1641,1643,1645,1647],{"class":129,"line":1217},[127,1642,527],{"class":133},[127,1644,908],{"class":136},[127,1646,530],{"class":136},[127,1648,1649],{"class":136}," composables\u002F\n",[127,1651,1652,1654,1656,1658,1660],{"class":129,"line":1229},[127,1653,527],{"class":133},[127,1655,908],{"class":136},[127,1657,908],{"class":136},[127,1659,609],{"class":136},[127,1661,1662],{"class":136}," useFetch.js\n",[127,1664,1665,1667,1669,1671],{"class":129,"line":1241},[127,1666,527],{"class":133},[127,1668,908],{"class":136},[127,1670,530],{"class":136},[127,1672,1124],{"class":136},[127,1674,1675,1677,1679,1681,1683],{"class":129,"line":1253},[127,1676,527],{"class":133},[127,1678,908],{"class":136},[127,1680,908],{"class":136},[127,1682,609],{"class":136},[127,1684,1197],{"class":136},[127,1686,1687,1689,1691,1693],{"class":129,"line":1260},[127,1688,527],{"class":133},[127,1690,908],{"class":136},[127,1692,530],{"class":136},[127,1694,1695],{"class":136}," utils\u002F\n",[127,1697,1698,1700,1702,1704,1706],{"class":129,"line":1270},[127,1699,527],{"class":133},[127,1701,908],{"class":136},[127,1703,908],{"class":136},[127,1705,609],{"class":136},[127,1707,1708],{"class":136}," formatDate.js\n",[127,1710,1712,1714,1716,1718],{"class":129,"line":1711},39,[127,1713,527],{"class":133},[127,1715,908],{"class":136},[127,1717,609],{"class":136},[127,1719,1720],{"class":136}," constants\u002F\n",[127,1722,1724,1726,1728,1730],{"class":129,"line":1723},40,[127,1725,527],{"class":133},[127,1727,908],{"class":136},[127,1729,1008],{"class":136},[127,1731,1732],{"class":136}," roles.js\n",[127,1734,1736,1738],{"class":129,"line":1735},41,[127,1737,527],{"class":133},[127,1739,1018],{"class":136},[127,1741,1743,1745,1747],{"class":129,"line":1742},42,[127,1744,527],{"class":133},[127,1746,530],{"class":136},[127,1748,1214],{"class":136},[127,1750,1752,1754,1756,1758,1761],{"class":129,"line":1751},43,[127,1753,527],{"class":133},[127,1755,908],{"class":136},[127,1757,609],{"class":136},[127,1759,1760],{"class":136}," index.js",[127,1762,1763],{"class":489},"                # Archivo principal del router que importa las rutas de los módulos\n",[127,1765,1767,1769,1771],{"class":129,"line":1766},44,[127,1768,527],{"class":133},[127,1770,908],{"class":136},[127,1772,1773],{"class":489},"                               # (los guards van aquí)\n",[127,1775,1777,1779,1781],{"class":129,"line":1776},45,[127,1778,527],{"class":133},[127,1780,530],{"class":136},[127,1782,1267],{"class":136},[127,1784,1786,1788],{"class":129,"line":1785},46,[127,1787,483],{"class":133},[127,1789,1267],{"class":136},[11,1791,1792,1793,1796],{},"Cada módulo o funcionalidad concentra ",[36,1794,1795],{},"todo lo que necesita en un solo lugar",", lo que simplifica la navegación y facilita el mantenimiento del código. Este enfoque resulta especialmente beneficioso en aplicaciones grandes o complejas.",[11,1798,1799,1800,1803],{},"La carpeta ",[54,1801,1802],{},"shared\u002F"," nos sirve para almacenar componentes, composables, utilidades y constantes que son reutilizables en toda la aplicación (solo ten cuidado de no sobrecargarla).",[11,1805,1806,1807,1810],{},"La base de este enfoque consiste en dividir la aplicación en módulos independientes dentro de ",[54,1808,1809],{},"\u002Fsrc\u002Fmodules",", cada uno con su propia estructura interna.",[413,1812,1813],{},[11,1814,1815,1816,1821],{},"Al final, la elección depende del tamaño y complejidad de tu proyecto, así como de las ",[36,1817,1818],{},[160,1819,1820],{},"preferencias de tu equipo",", asi que no hay una única forma correcta de hacerlo. Estos son solo ejemplos para inspirarte.",[18,1823],{},[21,1825,1827],{"id":1826},"entendiendo-como-se-monta-la-app-vue","Entendiendo como se monta la app Vue",[11,1829,1830,1831,1834,1835,1837],{},"El punto de entrada de la aplicación Vue en sí, es el archivo ",[54,1832,1833],{},"src\u002Fmain.js",", aquí es donde se inicializa, se configuran los plugins y se monta en el DOM. Si vemos el archivo ",[54,1836,1833],{},":",[118,1839,1843],{"className":1840,"code":1841,"language":1842,"meta":123,"style":123},"language-javascript shiki shiki-themes vitesse-light vitesse-dark","import '.\u002Fassets\u002Fmain.css';\n\nimport { createApp } from 'vue';\nimport { createPinia } from 'pinia';\n\nimport App from '.\u002FApp.vue';\nimport router from '.\u002Frouter';\n\nconst app = createApp(App);\n\napp.use(createPinia());\napp.use(router);\n\napp.mount('#app');\n","javascript",[54,1844,1845,1865,1871,1897,1919,1923,1941,1959,1963,1986,1990,2008,2023,2027],{"__ignoreMap":123},[127,1846,1847,1851,1855,1858,1861],{"class":129,"line":130},[127,1848,1850],{"class":1849},"sTPum","import",[127,1852,1854],{"class":1853},"scnC2"," '",[127,1856,1857],{"class":136},".\u002Fassets\u002Fmain.css",[127,1859,1860],{"class":1853},"'",[127,1862,1864],{"class":1863},"si6no",";\n",[127,1866,1867],{"class":129,"line":339},[127,1868,1870],{"emptyLinePlaceholder":1869},true,"\n",[127,1872,1873,1875,1878,1882,1885,1888,1890,1893,1895],{"class":129,"line":357},[127,1874,1850],{"class":1849},[127,1876,1877],{"class":1863}," {",[127,1879,1881],{"class":1880},"s9nN2"," createApp",[127,1883,1884],{"class":1863}," }",[127,1886,1887],{"class":1849}," from",[127,1889,1854],{"class":1853},[127,1891,1892],{"class":136},"vue",[127,1894,1860],{"class":1853},[127,1896,1864],{"class":1863},[127,1898,1899,1901,1903,1906,1908,1910,1912,1915,1917],{"class":129,"line":378},[127,1900,1850],{"class":1849},[127,1902,1877],{"class":1863},[127,1904,1905],{"class":1880}," createPinia",[127,1907,1884],{"class":1863},[127,1909,1887],{"class":1849},[127,1911,1854],{"class":1853},[127,1913,1914],{"class":136},"pinia",[127,1916,1860],{"class":1853},[127,1918,1864],{"class":1863},[127,1920,1921],{"class":129,"line":513},[127,1922,1870],{"emptyLinePlaceholder":1869},[127,1924,1925,1927,1930,1932,1934,1937,1939],{"class":129,"line":524},[127,1926,1850],{"class":1849},[127,1928,1929],{"class":1880}," App",[127,1931,1887],{"class":1849},[127,1933,1854],{"class":1853},[127,1935,1936],{"class":136},".\u002FApp.vue",[127,1938,1860],{"class":1853},[127,1940,1864],{"class":1863},[127,1942,1943,1945,1948,1950,1952,1955,1957],{"class":129,"line":539},[127,1944,1850],{"class":1849},[127,1946,1947],{"class":1880}," router",[127,1949,1887],{"class":1849},[127,1951,1854],{"class":1853},[127,1953,1954],{"class":136},".\u002Frouter",[127,1956,1860],{"class":1853},[127,1958,1864],{"class":1863},[127,1960,1961],{"class":129,"line":552},[127,1962,1870],{"emptyLinePlaceholder":1869},[127,1964,1965,1969,1972,1975,1977,1980,1983],{"class":129,"line":565},[127,1966,1968],{"class":1967},"s5TCs","const",[127,1970,1971],{"class":1880}," app",[127,1973,1974],{"class":1863}," =",[127,1976,1881],{"class":133},[127,1978,1979],{"class":1863},"(",[127,1981,1982],{"class":1880},"App",[127,1984,1985],{"class":1863},");\n",[127,1987,1988],{"class":129,"line":578},[127,1989,1870],{"emptyLinePlaceholder":1869},[127,1991,1992,1995,1997,2000,2002,2005],{"class":129,"line":591},[127,1993,1994],{"class":1880},"app",[127,1996,101],{"class":1863},[127,1998,1999],{"class":133},"use",[127,2001,1979],{"class":1863},[127,2003,2004],{"class":133},"createPinia",[127,2006,2007],{"class":1863},"());\n",[127,2009,2010,2012,2014,2016,2018,2021],{"class":129,"line":604},[127,2011,1994],{"class":1880},[127,2013,101],{"class":1863},[127,2015,1999],{"class":133},[127,2017,1979],{"class":1863},[127,2019,2020],{"class":1880},"router",[127,2022,1985],{"class":1863},[127,2024,2025],{"class":129,"line":618},[127,2026,1870],{"emptyLinePlaceholder":1869},[127,2028,2029,2031,2033,2036,2038,2040,2043,2045],{"class":129,"line":629},[127,2030,1994],{"class":1880},[127,2032,101],{"class":1863},[127,2034,2035],{"class":133},"mount",[127,2037,1979],{"class":1863},[127,2039,1860],{"class":1853},[127,2041,2042],{"class":136},"#app",[127,2044,1860],{"class":1853},[127,2046,1985],{"class":1863},[11,2048,2049],{},"Aquí estamos haciendo lo siguiente:",[191,2051,2052,2059,2068,2073,2079,2089,2096,2102],{},[32,2053,2054,2055,2058],{},"Importamos los estilos globales desde ",[54,2056,2057],{},"main.css",". Este archivo contiene cualquier estilo que quieras aplicar globalmente.",[32,2060,2061,2062,864,2065,2067],{},"Importamos las funciones ",[54,2063,2064],{},"createApp",[54,2066,2004],{}," para crear nuevas instancias de Vue y Pinia.",[32,2069,2070,2071,101],{},"Importamos el componente raíz ",[54,2072,842],{},[32,2074,2075,2076,101],{},"Importamos la configuración de nuestras rutas desde ",[54,2077,2078],{},"src\u002Frouter\u002Findex.js",[32,2080,2081,2082,2085,2086,2088],{},"Creamos la instancia de la aplicación con ",[54,2083,2084],{},"createApp(App)",", pasando el componente raíz ",[54,2087,1982],{}," como argumento, indicando que este será el punto de partida de nuestra aplicación Vue, básicamente le estamos diciendo a Vue: \"Aquí está el componente principal, toda la aplicación la construirás a partir de él\".",[32,2090,2091,2092,2095],{},"Usamos ",[54,2093,2094],{},"app.use(createPinia())"," para registrar la instancia de Pinia, habilitando el manejo de estado global en nuestra aplicación.",[32,2097,2091,2098,2101],{},[54,2099,2100],{},"app.use(router)"," para registrar la instancia de Vue Router y habilitar la navegación entre vistas.",[32,2103,2104,2105,2107,2108,101],{},"Finalmente, montamos la aplicación Vue en el elemento del DOM con el id ",[54,2106,1994],{}," usando ",[54,2109,2110],{},"app.mount('#app')",[11,2112,2113,2114,2117],{},"Ahora, abre el archivo ",[54,2115,2116],{},"index.html"," ubicado en la raíz del proyecto:",[118,2119,2123],{"className":2120,"code":2121,"language":2122,"meta":123,"style":123},"language-html shiki shiki-themes vitesse-light vitesse-dark","\u003C!DOCTYPE html>\n\u003Chtml lang=\"\">\n  \u003Chead>\n    \u003Cmeta charset=\"UTF-8\" \u002F>\n    \u003Clink rel=\"icon\" href=\"\u002Ffavicon.ico\" \u002F>\n    \u003Cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" \u002F>\n    \u003Ctitle>Vite App\u003C\u002Ftitle>\n  \u003C\u002Fhead>\n  \u003Cbody>\n    \u003Cdiv id=\"app\">\u003C\u002Fdiv>\n    \u003Cscript type=\"module\" src=\"\u002Fsrc\u002Fmain.js\">\u003C\u002Fscript>\n  \u003C\u002Fbody>\n\u003C\u002Fhtml>\n","html",[54,2124,2125,2139,2157,2167,2191,2224,2256,2277,2286,2295,2320,2357,2365],{"__ignoreMap":123},[127,2126,2127,2130,2133,2136],{"class":129,"line":130},[127,2128,2129],{"class":1863},"\u003C!",[127,2131,2132],{"class":1849},"DOCTYPE",[127,2134,2135],{"class":1880}," html",[127,2137,2138],{"class":1863},">\n",[127,2140,2141,2144,2146,2149,2152,2155],{"class":129,"line":339},[127,2142,2143],{"class":1863},"\u003C",[127,2145,2122],{"class":1849},[127,2147,2148],{"class":1880}," lang",[127,2150,2151],{"class":1863},"=",[127,2153,2154],{"class":1853},"\"\"",[127,2156,2138],{"class":1863},[127,2158,2159,2162,2165],{"class":129,"line":357},[127,2160,2161],{"class":1863},"  \u003C",[127,2163,2164],{"class":1849},"head",[127,2166,2138],{"class":1863},[127,2168,2169,2172,2175,2178,2180,2183,2186,2188],{"class":129,"line":378},[127,2170,2171],{"class":1863},"    \u003C",[127,2173,2174],{"class":1849},"meta",[127,2176,2177],{"class":1880}," charset",[127,2179,2151],{"class":1863},[127,2181,2182],{"class":1853},"\"",[127,2184,2185],{"class":136},"UTF-8",[127,2187,2182],{"class":1853},[127,2189,2190],{"class":1863}," \u002F>\n",[127,2192,2193,2195,2198,2201,2203,2205,2208,2210,2213,2215,2217,2220,2222],{"class":129,"line":513},[127,2194,2171],{"class":1863},[127,2196,2197],{"class":1849},"link",[127,2199,2200],{"class":1880}," rel",[127,2202,2151],{"class":1863},[127,2204,2182],{"class":1853},[127,2206,2207],{"class":136},"icon",[127,2209,2182],{"class":1853},[127,2211,2212],{"class":1880}," href",[127,2214,2151],{"class":1863},[127,2216,2182],{"class":1853},[127,2218,2219],{"class":136},"\u002Ffavicon.ico",[127,2221,2182],{"class":1853},[127,2223,2190],{"class":1863},[127,2225,2226,2228,2230,2233,2235,2237,2240,2242,2245,2247,2249,2252,2254],{"class":129,"line":524},[127,2227,2171],{"class":1863},[127,2229,2174],{"class":1849},[127,2231,2232],{"class":1880}," name",[127,2234,2151],{"class":1863},[127,2236,2182],{"class":1853},[127,2238,2239],{"class":136},"viewport",[127,2241,2182],{"class":1853},[127,2243,2244],{"class":1880}," content",[127,2246,2151],{"class":1863},[127,2248,2182],{"class":1853},[127,2250,2251],{"class":136},"width=device-width, initial-scale=1.0",[127,2253,2182],{"class":1853},[127,2255,2190],{"class":1863},[127,2257,2258,2260,2263,2266,2270,2273,2275],{"class":129,"line":539},[127,2259,2171],{"class":1863},[127,2261,2262],{"class":1849},"title",[127,2264,2265],{"class":1863},">",[127,2267,2269],{"class":2268},"s8w-G","Vite App",[127,2271,2272],{"class":1863},"\u003C\u002F",[127,2274,2262],{"class":1849},[127,2276,2138],{"class":1863},[127,2278,2279,2282,2284],{"class":129,"line":552},[127,2280,2281],{"class":1863},"  \u003C\u002F",[127,2283,2164],{"class":1849},[127,2285,2138],{"class":1863},[127,2287,2288,2290,2293],{"class":129,"line":565},[127,2289,2161],{"class":1863},[127,2291,2292],{"class":1849},"body",[127,2294,2138],{"class":1863},[127,2296,2297,2299,2302,2305,2307,2309,2311,2313,2316,2318],{"class":129,"line":578},[127,2298,2171],{"class":1863},[127,2300,2301],{"class":1849},"div",[127,2303,2304],{"class":1880}," id",[127,2306,2151],{"class":1863},[127,2308,2182],{"class":1853},[127,2310,1994],{"class":136},[127,2312,2182],{"class":1853},[127,2314,2315],{"class":1863},">\u003C\u002F",[127,2317,2301],{"class":1849},[127,2319,2138],{"class":1863},[127,2321,2322,2324,2327,2330,2332,2334,2337,2339,2342,2344,2346,2349,2351,2353,2355],{"class":129,"line":591},[127,2323,2171],{"class":1863},[127,2325,2326],{"class":1849},"script",[127,2328,2329],{"class":1880}," type",[127,2331,2151],{"class":1863},[127,2333,2182],{"class":1853},[127,2335,2336],{"class":136},"module",[127,2338,2182],{"class":1853},[127,2340,2341],{"class":1880}," src",[127,2343,2151],{"class":1863},[127,2345,2182],{"class":1853},[127,2347,2348],{"class":136},"\u002Fsrc\u002Fmain.js",[127,2350,2182],{"class":1853},[127,2352,2315],{"class":1863},[127,2354,2326],{"class":1849},[127,2356,2138],{"class":1863},[127,2358,2359,2361,2363],{"class":129,"line":604},[127,2360,2281],{"class":1863},[127,2362,2292],{"class":1849},[127,2364,2138],{"class":1863},[127,2366,2367,2369,2371],{"class":129,"line":618},[127,2368,2272],{"class":1863},[127,2370,2122],{"class":1849},[127,2372,2138],{"class":1863},[11,2374,2375,2376,2379,2380,2382,2383,2386,2387,2389],{},"Aquí vemos que el archivo HTML tiene un ",[54,2377,2378],{},"\u003Cdiv>"," con el id ",[54,2381,1994],{},", que es donde Vue montará nuestra aplicación. El ",[54,2384,2385],{},"\u003Cscript>"," que le sigue carga nuestro archivo ",[54,2388,848],{},", que es donde inicializamos todo.",[11,2391,2392,2393,1837],{},"Abre el archivo ",[54,2394,2395],{},"src\u002FApp.vue",[118,2397,2400],{"className":2398,"code":2399,"language":1892,"meta":123,"style":123},"language-vue shiki shiki-themes vitesse-light vitesse-dark","\u003Cscript setup>\nimport { RouterLink, RouterView } from 'vue-router';\nimport HelloWorld from '.\u002Fcomponents\u002FHelloWorld.vue';\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cheader>\n    \u003Cimg alt=\"Vue logo\" class=\"logo\" src=\"@\u002Fassets\u002Flogo.svg\" width=\"125\" height=\"125\" \u002F>\n\n    \u003Cdiv class=\"wrapper\">\n      \u003CHelloWorld msg=\"You did it!\" \u002F>\n\n      \u003Cnav>\n        \u003CRouterLink to=\"\u002F\">Home\u003C\u002FRouterLink>\n        \u003CRouterLink to=\"\u002Fabout\">About\u003C\u002FRouterLink>\n      \u003C\u002Fnav>\n    \u003C\u002Fdiv>\n  \u003C\u002Fheader>\n\n  \u003CRouterView \u002F>\n\u003C\u002Ftemplate>\n\n\u003Cstyle scoped>\n\u002F* Estilos CSS *\u002F\n\u003C\u002Fstyle>\n",[54,2401,2402,2413,2441,2459,2467,2471,2480,2489,2555,2559,2578,2600,2604,2613,2644,2672,2681,2690,2698,2702,2711,2719,2723,2735,2740],{"__ignoreMap":123},[127,2403,2404,2406,2408,2411],{"class":129,"line":130},[127,2405,2143],{"class":1863},[127,2407,2326],{"class":1849},[127,2409,2410],{"class":1880}," setup",[127,2412,2138],{"class":1863},[127,2414,2415,2417,2419,2422,2425,2428,2430,2432,2434,2437,2439],{"class":129,"line":339},[127,2416,1850],{"class":1849},[127,2418,1877],{"class":1863},[127,2420,2421],{"class":1880}," RouterLink",[127,2423,2424],{"class":1863},",",[127,2426,2427],{"class":1880}," RouterView",[127,2429,1884],{"class":1863},[127,2431,1887],{"class":1849},[127,2433,1854],{"class":1853},[127,2435,2436],{"class":136},"vue-router",[127,2438,1860],{"class":1853},[127,2440,1864],{"class":1863},[127,2442,2443,2445,2448,2450,2452,2455,2457],{"class":129,"line":357},[127,2444,1850],{"class":1849},[127,2446,2447],{"class":1880}," HelloWorld",[127,2449,1887],{"class":1849},[127,2451,1854],{"class":1853},[127,2453,2454],{"class":136},".\u002Fcomponents\u002FHelloWorld.vue",[127,2456,1860],{"class":1853},[127,2458,1864],{"class":1863},[127,2460,2461,2463,2465],{"class":129,"line":378},[127,2462,2272],{"class":1863},[127,2464,2326],{"class":1849},[127,2466,2138],{"class":1863},[127,2468,2469],{"class":129,"line":513},[127,2470,1870],{"emptyLinePlaceholder":1869},[127,2472,2473,2475,2478],{"class":129,"line":524},[127,2474,2143],{"class":1863},[127,2476,2477],{"class":1849},"template",[127,2479,2138],{"class":1863},[127,2481,2482,2484,2487],{"class":129,"line":539},[127,2483,2161],{"class":1863},[127,2485,2486],{"class":1849},"header",[127,2488,2138],{"class":1863},[127,2490,2491,2493,2495,2498,2500,2502,2505,2507,2510,2512,2514,2517,2519,2521,2523,2525,2528,2530,2533,2535,2537,2540,2542,2545,2547,2549,2551,2553],{"class":129,"line":552},[127,2492,2171],{"class":1863},[127,2494,155],{"class":1849},[127,2496,2497],{"class":1880}," alt",[127,2499,2151],{"class":1863},[127,2501,2182],{"class":1853},[127,2503,2504],{"class":136},"Vue logo",[127,2506,2182],{"class":1853},[127,2508,2509],{"class":1880}," class",[127,2511,2151],{"class":1863},[127,2513,2182],{"class":1853},[127,2515,2516],{"class":136},"logo",[127,2518,2182],{"class":1853},[127,2520,2341],{"class":1880},[127,2522,2151],{"class":1863},[127,2524,2182],{"class":1853},[127,2526,2527],{"class":136},"@\u002Fassets\u002Flogo.svg",[127,2529,2182],{"class":1853},[127,2531,2532],{"class":1880}," width",[127,2534,2151],{"class":1863},[127,2536,2182],{"class":1853},[127,2538,2539],{"class":136},"125",[127,2541,2182],{"class":1853},[127,2543,2544],{"class":1880}," height",[127,2546,2151],{"class":1863},[127,2548,2182],{"class":1853},[127,2550,2539],{"class":136},[127,2552,2182],{"class":1853},[127,2554,2190],{"class":1863},[127,2556,2557],{"class":129,"line":565},[127,2558,1870],{"emptyLinePlaceholder":1869},[127,2560,2561,2563,2565,2567,2569,2571,2574,2576],{"class":129,"line":578},[127,2562,2171],{"class":1863},[127,2564,2301],{"class":1849},[127,2566,2509],{"class":1880},[127,2568,2151],{"class":1863},[127,2570,2182],{"class":1853},[127,2572,2573],{"class":136},"wrapper",[127,2575,2182],{"class":1853},[127,2577,2138],{"class":1863},[127,2579,2580,2583,2586,2589,2591,2593,2596,2598],{"class":129,"line":591},[127,2581,2582],{"class":1863},"      \u003C",[127,2584,2585],{"class":1849},"HelloWorld",[127,2587,2588],{"class":1880}," msg",[127,2590,2151],{"class":1863},[127,2592,2182],{"class":1853},[127,2594,2595],{"class":136},"You did it!",[127,2597,2182],{"class":1853},[127,2599,2190],{"class":1863},[127,2601,2602],{"class":129,"line":604},[127,2603,1870],{"emptyLinePlaceholder":1869},[127,2605,2606,2608,2611],{"class":129,"line":618},[127,2607,2582],{"class":1863},[127,2609,2610],{"class":1849},"nav",[127,2612,2138],{"class":1863},[127,2614,2615,2618,2621,2624,2626,2628,2631,2633,2635,2638,2640,2642],{"class":129,"line":629},[127,2616,2617],{"class":1863},"        \u003C",[127,2619,2620],{"class":1849},"RouterLink",[127,2622,2623],{"class":1880}," to",[127,2625,2151],{"class":1863},[127,2627,2182],{"class":1853},[127,2629,2630],{"class":136},"\u002F",[127,2632,2182],{"class":1853},[127,2634,2265],{"class":1863},[127,2636,2637],{"class":2268},"Home",[127,2639,2272],{"class":1863},[127,2641,2620],{"class":1849},[127,2643,2138],{"class":1863},[127,2645,2646,2648,2650,2652,2654,2656,2659,2661,2663,2666,2668,2670],{"class":129,"line":640},[127,2647,2617],{"class":1863},[127,2649,2620],{"class":1849},[127,2651,2623],{"class":1880},[127,2653,2151],{"class":1863},[127,2655,2182],{"class":1853},[127,2657,2658],{"class":136},"\u002Fabout",[127,2660,2182],{"class":1853},[127,2662,2265],{"class":1863},[127,2664,2665],{"class":2268},"About",[127,2667,2272],{"class":1863},[127,2669,2620],{"class":1849},[127,2671,2138],{"class":1863},[127,2673,2674,2677,2679],{"class":129,"line":651},[127,2675,2676],{"class":1863},"      \u003C\u002F",[127,2678,2610],{"class":1849},[127,2680,2138],{"class":1863},[127,2682,2683,2686,2688],{"class":129,"line":662},[127,2684,2685],{"class":1863},"    \u003C\u002F",[127,2687,2301],{"class":1849},[127,2689,2138],{"class":1863},[127,2691,2692,2694,2696],{"class":129,"line":673},[127,2693,2281],{"class":1863},[127,2695,2486],{"class":1849},[127,2697,2138],{"class":1863},[127,2699,2700],{"class":129,"line":684},[127,2701,1870],{"emptyLinePlaceholder":1869},[127,2703,2704,2706,2709],{"class":129,"line":695},[127,2705,2161],{"class":1863},[127,2707,2708],{"class":1849},"RouterView",[127,2710,2190],{"class":1863},[127,2712,2713,2715,2717],{"class":129,"line":706},[127,2714,2272],{"class":1863},[127,2716,2477],{"class":1849},[127,2718,2138],{"class":1863},[127,2720,2721],{"class":129,"line":717},[127,2722,1870],{"emptyLinePlaceholder":1869},[127,2724,2725,2727,2730,2733],{"class":129,"line":728},[127,2726,2143],{"class":1863},[127,2728,2729],{"class":1849},"style",[127,2731,2732],{"class":1880}," scoped",[127,2734,2138],{"class":1863},[127,2736,2737],{"class":129,"line":1117},[127,2738,2739],{"class":489},"\u002F* Estilos CSS *\u002F\n",[127,2741,2742,2744,2746],{"class":129,"line":1127},[127,2743,2272],{"class":1863},[127,2745,2729],{"class":1849},[127,2747,2138],{"class":1863},[11,2749,2750,2751,2753,2754,2756,2757,2760],{},"Aquí vemos que ",[54,2752,842],{}," contiene un encabezado (header) con un logo, un componente ",[54,2755,2585],{},", y un menú de navegación con enlaces a las rutas definidas. El ",[54,2758,2759],{},"\u003CRouterView \u002F>"," es donde se renderizarán las vistas correspondientes según la ruta actual, gracias a Vue Router.",[11,2762,2763,2764,1837],{},"Exploremos la configuración del router. Abre el archivo ",[54,2765,2078],{},[118,2767,2769],{"className":1840,"code":2768,"language":1842,"meta":123,"style":123},"import { createRouter, createWebHistory } from 'vue-router';\nimport HomeView from '..\u002Fviews\u002FHomeView.vue';\n\nconst router = createRouter({\n  history: createWebHistory(import.meta.env.BASE_URL),\n  routes: [\n    {\n      path: '\u002F',\n      name: 'home',\n      component: HomeView,\n    },\n    {\n      path: '\u002Fabout',\n      name: 'about',\n      \u002F* Esta ruta usa lazy loading *\u002F\n      component: () => import('..\u002Fviews\u002FAboutView.vue'),\n    },\n  ],\n});\n\nexport default router;\n",[54,2770,2771,2797,2815,2819,2832,2862,2872,2877,2893,2909,2920,2925,2929,2943,2958,2963,2989,2993,2998,3003,3007],{"__ignoreMap":123},[127,2772,2773,2775,2777,2780,2782,2785,2787,2789,2791,2793,2795],{"class":129,"line":130},[127,2774,1850],{"class":1849},[127,2776,1877],{"class":1863},[127,2778,2779],{"class":1880}," createRouter",[127,2781,2424],{"class":1863},[127,2783,2784],{"class":1880}," createWebHistory",[127,2786,1884],{"class":1863},[127,2788,1887],{"class":1849},[127,2790,1854],{"class":1853},[127,2792,2436],{"class":136},[127,2794,1860],{"class":1853},[127,2796,1864],{"class":1863},[127,2798,2799,2801,2804,2806,2808,2811,2813],{"class":129,"line":339},[127,2800,1850],{"class":1849},[127,2802,2803],{"class":1880}," HomeView",[127,2805,1887],{"class":1849},[127,2807,1854],{"class":1853},[127,2809,2810],{"class":136},"..\u002Fviews\u002FHomeView.vue",[127,2812,1860],{"class":1853},[127,2814,1864],{"class":1863},[127,2816,2817],{"class":129,"line":357},[127,2818,1870],{"emptyLinePlaceholder":1869},[127,2820,2821,2823,2825,2827,2829],{"class":129,"line":378},[127,2822,1968],{"class":1967},[127,2824,1947],{"class":1880},[127,2826,1974],{"class":1863},[127,2828,2779],{"class":133},[127,2830,2831],{"class":1863},"({\n",[127,2833,2834,2837,2839,2841,2843,2845,2847,2849,2851,2854,2856,2859],{"class":129,"line":513},[127,2835,2836],{"class":332},"  history",[127,2838,1837],{"class":1863},[127,2840,2784],{"class":133},[127,2842,1979],{"class":1863},[127,2844,1850],{"class":1849},[127,2846,101],{"class":1863},[127,2848,2174],{"class":332},[127,2850,101],{"class":1863},[127,2852,2853],{"class":1880},"env",[127,2855,101],{"class":1863},[127,2857,2858],{"class":1880},"BASE_URL",[127,2860,2861],{"class":1863},"),\n",[127,2863,2864,2867,2869],{"class":129,"line":524},[127,2865,2866],{"class":332},"  routes",[127,2868,1837],{"class":1863},[127,2870,2871],{"class":1863}," [\n",[127,2873,2874],{"class":129,"line":539},[127,2875,2876],{"class":1863},"    {\n",[127,2878,2879,2882,2884,2886,2888,2890],{"class":129,"line":552},[127,2880,2881],{"class":332},"      path",[127,2883,1837],{"class":1863},[127,2885,1854],{"class":1853},[127,2887,2630],{"class":136},[127,2889,1860],{"class":1853},[127,2891,2892],{"class":1863},",\n",[127,2894,2895,2898,2900,2902,2905,2907],{"class":129,"line":565},[127,2896,2897],{"class":332},"      name",[127,2899,1837],{"class":1863},[127,2901,1854],{"class":1853},[127,2903,2904],{"class":136},"home",[127,2906,1860],{"class":1853},[127,2908,2892],{"class":1863},[127,2910,2911,2914,2916,2918],{"class":129,"line":578},[127,2912,2913],{"class":332},"      component",[127,2915,1837],{"class":1863},[127,2917,2803],{"class":1880},[127,2919,2892],{"class":1863},[127,2921,2922],{"class":129,"line":591},[127,2923,2924],{"class":1863},"    },\n",[127,2926,2927],{"class":129,"line":604},[127,2928,2876],{"class":1863},[127,2930,2931,2933,2935,2937,2939,2941],{"class":129,"line":618},[127,2932,2881],{"class":332},[127,2934,1837],{"class":1863},[127,2936,1854],{"class":1853},[127,2938,2658],{"class":136},[127,2940,1860],{"class":1853},[127,2942,2892],{"class":1863},[127,2944,2945,2947,2949,2951,2954,2956],{"class":129,"line":629},[127,2946,2897],{"class":332},[127,2948,1837],{"class":1863},[127,2950,1854],{"class":1853},[127,2952,2953],{"class":136},"about",[127,2955,1860],{"class":1853},[127,2957,2892],{"class":1863},[127,2959,2960],{"class":129,"line":640},[127,2961,2962],{"class":489},"      \u002F* Esta ruta usa lazy loading *\u002F\n",[127,2964,2965,2967,2969,2972,2975,2978,2980,2982,2985,2987],{"class":129,"line":651},[127,2966,2913],{"class":133},[127,2968,1837],{"class":1863},[127,2970,2971],{"class":1863}," ()",[127,2973,2974],{"class":1863}," =>",[127,2976,2977],{"class":1967}," import",[127,2979,1979],{"class":1863},[127,2981,1860],{"class":1853},[127,2983,2984],{"class":136},"..\u002Fviews\u002FAboutView.vue",[127,2986,1860],{"class":1853},[127,2988,2861],{"class":1863},[127,2990,2991],{"class":129,"line":662},[127,2992,2924],{"class":1863},[127,2994,2995],{"class":129,"line":673},[127,2996,2997],{"class":1863},"  ],\n",[127,2999,3000],{"class":129,"line":684},[127,3001,3002],{"class":1863},"});\n",[127,3004,3005],{"class":129,"line":695},[127,3006,1870],{"emptyLinePlaceholder":1869},[127,3008,3009,3012,3015,3017],{"class":129,"line":706},[127,3010,3011],{"class":1849},"export",[127,3013,3014],{"class":1849}," default",[127,3016,1947],{"class":1880},[127,3018,1864],{"class":1863},[11,3020,3021,3022,3025,3026,3029,3030,3032,3033,3035,3036,3038,3039,3041,3042,3047],{},"Aquí estamos importando las funciones necesarias de Vue Router y definiendo una ruta básica para la vista ",[54,3023,3024],{},"HomeView"," y otra para ",[54,3027,3028],{},"AboutView",". La ruta ",[54,3031,2630],{}," renderiza ",[54,3034,3024],{},", y la ruta ",[54,3037,2658],{}," carga ",[54,3040,3028],{}," utilizando carga diferida (",[41,3043,3046],{"href":3044,"target":43,"rel":3045},"https:\u002F\u002Fmedium.com\u002F@drewcauchi\u002Flazy-loading-in-vue-js-bb32018d2c2d",[46,47],"lazy loading",").",[11,3049,3050],{},"Repasemos el flujo completo:",[191,3052,3053,3061,3070],{},[32,3054,3055,3056,3058,3059,101],{},"El archivo ",[54,3057,2116],{}," es lo que el navegador nos muestra, y lo primero que hace es cargar ",[54,3060,848],{},[32,3062,3063,3064,3066,3067,3069],{},"En ",[54,3065,848],{},", se crea la aplicación Vue con ",[54,3068,842],{}," como componente raíz (a parte de importar estilos, configurar Pinia, Vue Router y otras configuraciones).",[32,3071,3072,3074,3075,3077],{},[54,3073,842],{}," define la estructura principal de la aplicación (como un layout principal) y utiliza ",[54,3076,2759],{}," para renderizar las vistas según la ruta actual.",[11,3079,3080,3084],{},[155,3081],{"alt":3082,"src":3083},"Flujo de una app Vue","\u002Fblog\u002Fgetting-started-vue-vite\u002Fes\u002Fexplaining-vue-app.webp",[160,3085,3082],{},[11,3087,3088,3089,3091,3092,3094],{},"Esto quiere decir que todo lo que veas dentro de ",[54,3090,842],{}," estará siempre presente (como el header y el menú de navegación), mientras que el contenido principal se mostrará dentro de ",[54,3093,2759],{}," y cambiará dependiendo de la ruta actual, gracias a nuestro router.",[11,3096,3097,3098,3100,3101,101],{},"Normalmente, en aplicaciones más complejas, ",[54,3099,842],{}," también contendrá otros elementos comunes como un footer, barras laterales, modales globales, etc.\nY cuando se necesita, se crean layouts específicos para diferentes módulos de la aplicación, por ejemplo, un layout para las vistas de administración y otro para las vistas públicas como el inicio de sesión. Puedes explorar más en ",[41,3102,3105],{"href":3103,"target":43,"rel":3104},"https:\u002F\u002Fvueschool.io\u002Farticles\u002Fvuejs-tutorials\u002Fcomposing-layouts-with-vue-router\u002F",[46,47],"este recurso de Vue School",[18,3107],{},[11,3109,3110],{},"A este punto ya tenemos una idea clara de cómo se estructura y monta una aplicación Vue 3 con Vite. Puedes comenzar a explorar y modificar los componentes, vistas y rutas para familiarizarte más con el framework. Ahora seguiremos explorando otros conceptos y herramientas importantes del ecosistema.",[18,3112],{},[21,3114,3116],{"id":3115},"pinia-para-manejo-de-estado-global","Pinia para manejo de estado global",[11,3118,3119],{},"Pinia nos sirve para manejar el estado global de nuestra aplicación: datos que deben ser accesibles desde cualquier parte de la aplicación, datos que necesitamos compartir entre múltiples componentes o vistas.",[11,3121,3122],{},"Por ejemplo, cuando necesitamos tener acceso a la información del usuario autenticado en diferentes partes de la app, o si queremos manejar un carrito de compras que pueda ser consultado desde distintos componentes.",[11,3124,3125,3126,1837],{},"Veamos un ejemplo básico. Crea el archivo ",[54,3127,3128],{},"src\u002Fstore\u002Fauth.store.js",[118,3130,3132],{"className":1840,"code":3131,"language":1842,"meta":123,"style":123},"import { defineStore } from 'pinia';\nexport const useAuthStore = defineStore('auth', {\n  state: () => ({\n    user: null,\n    token: null,\n  }),\n  actions: {\n    login(userData, token) {\n      this.user = userData;\n      this.token = token;\n    },\n    logout() {\n      this.user = null;\n      this.token = null;\n    },\n  },\n});\n",[54,3133,3134,3155,3183,3197,3209,3220,3225,3234,3254,3272,3287,3291,3301,3315,3329,3333,3338],{"__ignoreMap":123},[127,3135,3136,3138,3140,3143,3145,3147,3149,3151,3153],{"class":129,"line":130},[127,3137,1850],{"class":1849},[127,3139,1877],{"class":1863},[127,3141,3142],{"class":1880}," defineStore",[127,3144,1884],{"class":1863},[127,3146,1887],{"class":1849},[127,3148,1854],{"class":1853},[127,3150,1914],{"class":136},[127,3152,1860],{"class":1853},[127,3154,1864],{"class":1863},[127,3156,3157,3159,3162,3165,3167,3169,3171,3173,3176,3178,3180],{"class":129,"line":339},[127,3158,3011],{"class":1849},[127,3160,3161],{"class":1967}," const",[127,3163,3164],{"class":1880}," useAuthStore",[127,3166,1974],{"class":1863},[127,3168,3142],{"class":133},[127,3170,1979],{"class":1863},[127,3172,1860],{"class":1853},[127,3174,3175],{"class":136},"auth",[127,3177,1860],{"class":1853},[127,3179,2424],{"class":1863},[127,3181,3182],{"class":1863}," {\n",[127,3184,3185,3188,3190,3192,3194],{"class":129,"line":357},[127,3186,3187],{"class":133},"  state",[127,3189,1837],{"class":1863},[127,3191,2971],{"class":1863},[127,3193,2974],{"class":1863},[127,3195,3196],{"class":1863}," ({\n",[127,3198,3199,3202,3204,3207],{"class":129,"line":378},[127,3200,3201],{"class":332},"    user",[127,3203,1837],{"class":1863},[127,3205,3206],{"class":1967}," null",[127,3208,2892],{"class":1863},[127,3210,3211,3214,3216,3218],{"class":129,"line":513},[127,3212,3213],{"class":332},"    token",[127,3215,1837],{"class":1863},[127,3217,3206],{"class":1967},[127,3219,2892],{"class":1863},[127,3221,3222],{"class":129,"line":524},[127,3223,3224],{"class":1863},"  }),\n",[127,3226,3227,3230,3232],{"class":129,"line":539},[127,3228,3229],{"class":332},"  actions",[127,3231,1837],{"class":1863},[127,3233,3182],{"class":1863},[127,3235,3236,3239,3241,3244,3246,3249,3252],{"class":129,"line":552},[127,3237,3238],{"class":133},"    login",[127,3240,1979],{"class":1863},[127,3242,3243],{"class":1880},"userData",[127,3245,2424],{"class":1863},[127,3247,3248],{"class":1880}," token",[127,3250,3251],{"class":1863},")",[127,3253,3182],{"class":1863},[127,3255,3256,3260,3262,3265,3267,3270],{"class":129,"line":565},[127,3257,3259],{"class":3258},"sfsYZ","      this",[127,3261,101],{"class":1863},[127,3263,3264],{"class":1880},"user",[127,3266,1974],{"class":1863},[127,3268,3269],{"class":1880}," userData",[127,3271,1864],{"class":1863},[127,3273,3274,3276,3278,3281,3283,3285],{"class":129,"line":578},[127,3275,3259],{"class":3258},[127,3277,101],{"class":1863},[127,3279,3280],{"class":1880},"token",[127,3282,1974],{"class":1863},[127,3284,3248],{"class":1880},[127,3286,1864],{"class":1863},[127,3288,3289],{"class":129,"line":591},[127,3290,2924],{"class":1863},[127,3292,3293,3296,3299],{"class":129,"line":604},[127,3294,3295],{"class":133},"    logout",[127,3297,3298],{"class":1863},"()",[127,3300,3182],{"class":1863},[127,3302,3303,3305,3307,3309,3311,3313],{"class":129,"line":618},[127,3304,3259],{"class":3258},[127,3306,101],{"class":1863},[127,3308,3264],{"class":1880},[127,3310,1974],{"class":1863},[127,3312,3206],{"class":1967},[127,3314,1864],{"class":1863},[127,3316,3317,3319,3321,3323,3325,3327],{"class":129,"line":629},[127,3318,3259],{"class":3258},[127,3320,101],{"class":1863},[127,3322,3280],{"class":1880},[127,3324,1974],{"class":1863},[127,3326,3206],{"class":1967},[127,3328,1864],{"class":1863},[127,3330,3331],{"class":129,"line":640},[127,3332,2924],{"class":1863},[127,3334,3335],{"class":129,"line":651},[127,3336,3337],{"class":1863},"  },\n",[127,3339,3340],{"class":129,"line":662},[127,3341,3002],{"class":1863},[11,3343,3344,3345,3347,3348,864,3350,3352,3353,1837],{},"Aquí estamos definiendo una store llamada ",[54,3346,3175],{}," que tiene un estado con las propiedades ",[54,3349,3264],{},[54,3351,3280],{},", y dos acciones para iniciar sesión y cerrar sesión.\nAhora, veamos cómo usar esta store en un componente. Crea un componente Vue, por ejemplo ",[54,3354,3355],{},"src\u002Fcomponents\u002FAuth.vue",[118,3357,3359],{"className":2398,"code":3358,"language":1892,"meta":123,"style":123},"\u003Ctemplate>\n  \u003Cdiv>\n    \u003Cdiv v-if=\"authStore.user\">\n      \u003Cp>Welcome, {{ authStore.user.name }}!\u003C\u002Fp>\n      \u003Cbutton @click=\"logout\">Logout\u003C\u002Fbutton>\n    \u003C\u002Fdiv>\n    \u003Cdiv v-else>\n      \u003Cbutton @click=\"login\">Login\u003C\u002Fbutton>\n    \u003C\u002Fdiv>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\u003Cscript setup>\nimport { useAuthStore } from '..\u002Fstore\u002Fauth.store';\nconst authStore = useAuthStore();\nconst login = () => {\n  \u002F\u002F Simulamos un inicio de sesión\n  const userData = { name: 'John Doe', email: 'john.doe@example.com' };\n  const token = 'fake-jwt-token';\n  authStore.login(userData, token);\n};\n\nconst logout = () => {\n  authStore.logout();\n};\n\u003C\u002Fscript>\n",[54,3360,3361,3369,3377,3397,3414,3444,3452,3463,3491,3499,3507,3515,3525,3546,3560,3575,3580,3619,3636,3655,3660,3664,3679,3689,3693],{"__ignoreMap":123},[127,3362,3363,3365,3367],{"class":129,"line":130},[127,3364,2143],{"class":1863},[127,3366,2477],{"class":1849},[127,3368,2138],{"class":1863},[127,3370,3371,3373,3375],{"class":129,"line":339},[127,3372,2161],{"class":1863},[127,3374,2301],{"class":1849},[127,3376,2138],{"class":1863},[127,3378,3379,3381,3383,3386,3388,3390,3393,3395],{"class":129,"line":357},[127,3380,2171],{"class":1863},[127,3382,2301],{"class":1849},[127,3384,3385],{"class":1880}," v-if",[127,3387,2151],{"class":1863},[127,3389,2182],{"class":1853},[127,3391,3392],{"class":136},"authStore.user",[127,3394,2182],{"class":1853},[127,3396,2138],{"class":1863},[127,3398,3399,3401,3403,3405,3408,3410,3412],{"class":129,"line":378},[127,3400,2582],{"class":1863},[127,3402,11],{"class":1849},[127,3404,2265],{"class":1863},[127,3406,3407],{"class":2268},"Welcome, {{ authStore.user.name }}!",[127,3409,2272],{"class":1863},[127,3411,11],{"class":1849},[127,3413,2138],{"class":1863},[127,3415,3416,3418,3421,3424,3426,3428,3431,3433,3435,3438,3440,3442],{"class":129,"line":513},[127,3417,2582],{"class":1863},[127,3419,3420],{"class":1849},"button",[127,3422,3423],{"class":1880}," @click",[127,3425,2151],{"class":1863},[127,3427,2182],{"class":1853},[127,3429,3430],{"class":136},"logout",[127,3432,2182],{"class":1853},[127,3434,2265],{"class":1863},[127,3436,3437],{"class":2268},"Logout",[127,3439,2272],{"class":1863},[127,3441,3420],{"class":1849},[127,3443,2138],{"class":1863},[127,3445,3446,3448,3450],{"class":129,"line":524},[127,3447,2685],{"class":1863},[127,3449,2301],{"class":1849},[127,3451,2138],{"class":1863},[127,3453,3454,3456,3458,3461],{"class":129,"line":539},[127,3455,2171],{"class":1863},[127,3457,2301],{"class":1849},[127,3459,3460],{"class":1880}," v-else",[127,3462,2138],{"class":1863},[127,3464,3465,3467,3469,3471,3473,3475,3478,3480,3482,3485,3487,3489],{"class":129,"line":552},[127,3466,2582],{"class":1863},[127,3468,3420],{"class":1849},[127,3470,3423],{"class":1880},[127,3472,2151],{"class":1863},[127,3474,2182],{"class":1853},[127,3476,3477],{"class":136},"login",[127,3479,2182],{"class":1853},[127,3481,2265],{"class":1863},[127,3483,3484],{"class":2268},"Login",[127,3486,2272],{"class":1863},[127,3488,3420],{"class":1849},[127,3490,2138],{"class":1863},[127,3492,3493,3495,3497],{"class":129,"line":565},[127,3494,2685],{"class":1863},[127,3496,2301],{"class":1849},[127,3498,2138],{"class":1863},[127,3500,3501,3503,3505],{"class":129,"line":578},[127,3502,2281],{"class":1863},[127,3504,2301],{"class":1849},[127,3506,2138],{"class":1863},[127,3508,3509,3511,3513],{"class":129,"line":591},[127,3510,2272],{"class":1863},[127,3512,2477],{"class":1849},[127,3514,2138],{"class":1863},[127,3516,3517,3519,3521,3523],{"class":129,"line":604},[127,3518,2143],{"class":1863},[127,3520,2326],{"class":1849},[127,3522,2410],{"class":1880},[127,3524,2138],{"class":1863},[127,3526,3527,3529,3531,3533,3535,3537,3539,3542,3544],{"class":129,"line":618},[127,3528,1850],{"class":1849},[127,3530,1877],{"class":1863},[127,3532,3164],{"class":1880},[127,3534,1884],{"class":1863},[127,3536,1887],{"class":1849},[127,3538,1854],{"class":1853},[127,3540,3541],{"class":136},"..\u002Fstore\u002Fauth.store",[127,3543,1860],{"class":1853},[127,3545,1864],{"class":1863},[127,3547,3548,3550,3553,3555,3557],{"class":129,"line":629},[127,3549,1968],{"class":1967},[127,3551,3552],{"class":1880}," authStore",[127,3554,1974],{"class":1863},[127,3556,3164],{"class":133},[127,3558,3559],{"class":1863},"();\n",[127,3561,3562,3564,3567,3569,3571,3573],{"class":129,"line":640},[127,3563,1968],{"class":1967},[127,3565,3566],{"class":133}," login",[127,3568,1974],{"class":1863},[127,3570,2971],{"class":1863},[127,3572,2974],{"class":1863},[127,3574,3182],{"class":1863},[127,3576,3577],{"class":129,"line":651},[127,3578,3579],{"class":489},"  \u002F\u002F Simulamos un inicio de sesión\n",[127,3581,3582,3585,3587,3589,3591,3593,3595,3597,3600,3602,3604,3607,3609,3611,3614,3616],{"class":129,"line":662},[127,3583,3584],{"class":1967},"  const",[127,3586,3269],{"class":1880},[127,3588,1974],{"class":1863},[127,3590,1877],{"class":1863},[127,3592,2232],{"class":332},[127,3594,1837],{"class":1863},[127,3596,1854],{"class":1853},[127,3598,3599],{"class":136},"John Doe",[127,3601,1860],{"class":1853},[127,3603,2424],{"class":1863},[127,3605,3606],{"class":332}," email",[127,3608,1837],{"class":1863},[127,3610,1854],{"class":1853},[127,3612,3613],{"class":136},"john.doe@example.com",[127,3615,1860],{"class":1853},[127,3617,3618],{"class":1863}," };\n",[127,3620,3621,3623,3625,3627,3629,3632,3634],{"class":129,"line":673},[127,3622,3584],{"class":1967},[127,3624,3248],{"class":1880},[127,3626,1974],{"class":1863},[127,3628,1854],{"class":1853},[127,3630,3631],{"class":136},"fake-jwt-token",[127,3633,1860],{"class":1853},[127,3635,1864],{"class":1863},[127,3637,3638,3641,3643,3645,3647,3649,3651,3653],{"class":129,"line":684},[127,3639,3640],{"class":1880},"  authStore",[127,3642,101],{"class":1863},[127,3644,3477],{"class":133},[127,3646,1979],{"class":1863},[127,3648,3243],{"class":1880},[127,3650,2424],{"class":1863},[127,3652,3248],{"class":1880},[127,3654,1985],{"class":1863},[127,3656,3657],{"class":129,"line":695},[127,3658,3659],{"class":1863},"};\n",[127,3661,3662],{"class":129,"line":706},[127,3663,1870],{"emptyLinePlaceholder":1869},[127,3665,3666,3668,3671,3673,3675,3677],{"class":129,"line":717},[127,3667,1968],{"class":1967},[127,3669,3670],{"class":133}," logout",[127,3672,1974],{"class":1863},[127,3674,2971],{"class":1863},[127,3676,2974],{"class":1863},[127,3678,3182],{"class":1863},[127,3680,3681,3683,3685,3687],{"class":129,"line":728},[127,3682,3640],{"class":1880},[127,3684,101],{"class":1863},[127,3686,3430],{"class":133},[127,3688,3559],{"class":1863},[127,3690,3691],{"class":129,"line":1117},[127,3692,3659],{"class":1863},[127,3694,3695,3697,3699],{"class":129,"line":1127},[127,3696,2272],{"class":1863},[127,3698,2326],{"class":1849},[127,3700,2138],{"class":1863},[11,3702,3703,3704,3707,3708,3710,3711,864,3713,3715],{},"Aquí estamos importando la store ",[54,3705,3706],{},"useAuthStore"," y usándola para acceder al estado ",[54,3709,3264],{}," y las acciones ",[54,3712,3477],{},[54,3714,3430],{},".\nGracias a Pinia, el estado del usuario se mantiene consistente en todas partes, y cualquier cambio (como iniciar o cerrar sesión) se refleja automáticamente en todos los componentes que usan esta store.",[11,3717,3718],{},"Algunos casos reales de uso:",[29,3720,3721,3727,3733],{},[32,3722,3723,3726],{},[36,3724,3725],{},"Autenticación de usuarios",": Creas una store para manejar el estado del usuario autenticado, con datos como el token, nombre, roles, etc. Puedes crear acciones para iniciar sesión, cerrar sesión y actualizar la información del usuario.",[32,3728,3729,3732],{},[36,3730,3731],{},"Carrito de compras",": Creas una store para manejar los productos en el carrito, con acciones para agregar, eliminar y actualizar productos. Este estado puede ser accedido desde cualquier parte de la aplicación, como la página de productos y la página del carrito.",[32,3734,3735,3738],{},[36,3736,3737],{},"Preferencias de usuario",": Creas una store para manejar las preferencias del usuario, como el tema (claro\u002Foscuro), idioma, etc. Puedes crear acciones para actualizar estas preferencias y reflejarlas en toda la aplicación.",[11,3740,3741,3742,101],{},"Puedes explorar más sobre Pinia en la ",[41,3743,458],{"href":819,"target":43,"rel":3744},[46,47],[18,3746],{},[21,3748,3750],{"id":3749},"composables","Composables",[11,3752,3753],{},"Los composables son funciones reutilizables que encapsulan lógica específica, con estado, y pueden ser usados entre diferentes componentes.",[11,3755,3756,3757,3760],{},"Nos permiten organizar mejor nuestro código, promoviendo la reutilización y la separación de responsabilidades. Normalmente toda lógica con estado la pondríamos dentro de un ",[54,3758,3759],{},"\u003Cscript setup>"," en un componente Vue, pero si esa lógica es algo que podría ser útil en varios componentes, podemos extraerla a un composable.",[11,3762,3763,3764,1837],{},"Veamos un ejemplo bastante básico. Crea un archivo llamado ",[54,3765,3766],{},"src\u002Fcomposables\u002FuseClipboard.js",[118,3768,3770],{"className":1840,"code":3769,"language":1842,"meta":123,"style":123},"import { ref } from 'vue';\n\nexport function useClipboard() {\n  const copied = ref(false);\n\n  const copyToClipboard = async (text) => {\n    try {\n      await navigator.clipboard.writeText(text);\n      copied.value = true;\n      setTimeout(() => {\n        copied.value = false;\n      }, 2000);\n    } catch (error) {\n      console.error('Failed to copy: ', error);\n    }\n  };\n\n  return {\n    copied,\n    copyToClipboard,\n  };\n}\n",[54,3771,3772,3793,3797,3811,3828,3832,3856,3863,3887,3904,3916,3932,3943,3960,3985,3990,3995,3999,4006,4013,4020,4024],{"__ignoreMap":123},[127,3773,3774,3776,3778,3781,3783,3785,3787,3789,3791],{"class":129,"line":130},[127,3775,1850],{"class":1849},[127,3777,1877],{"class":1863},[127,3779,3780],{"class":1880}," ref",[127,3782,1884],{"class":1863},[127,3784,1887],{"class":1849},[127,3786,1854],{"class":1853},[127,3788,1892],{"class":136},[127,3790,1860],{"class":1853},[127,3792,1864],{"class":1863},[127,3794,3795],{"class":129,"line":339},[127,3796,1870],{"emptyLinePlaceholder":1869},[127,3798,3799,3801,3804,3807,3809],{"class":129,"line":357},[127,3800,3011],{"class":1849},[127,3802,3803],{"class":1967}," function",[127,3805,3806],{"class":133}," useClipboard",[127,3808,3298],{"class":1863},[127,3810,3182],{"class":1863},[127,3812,3813,3815,3818,3820,3822,3824,3826],{"class":129,"line":378},[127,3814,3584],{"class":1967},[127,3816,3817],{"class":1880}," copied",[127,3819,1974],{"class":1863},[127,3821,3780],{"class":133},[127,3823,1979],{"class":1863},[127,3825,762],{"class":1849},[127,3827,1985],{"class":1863},[127,3829,3830],{"class":129,"line":513},[127,3831,1870],{"emptyLinePlaceholder":1869},[127,3833,3834,3836,3839,3841,3844,3847,3850,3852,3854],{"class":129,"line":524},[127,3835,3584],{"class":1967},[127,3837,3838],{"class":133}," copyToClipboard",[127,3840,1974],{"class":1863},[127,3842,3843],{"class":1967}," async",[127,3845,3846],{"class":1863}," (",[127,3848,3849],{"class":1880},"text",[127,3851,3251],{"class":1863},[127,3853,2974],{"class":1863},[127,3855,3182],{"class":1863},[127,3857,3858,3861],{"class":129,"line":539},[127,3859,3860],{"class":1849},"    try",[127,3862,3182],{"class":1863},[127,3864,3865,3868,3871,3873,3876,3878,3881,3883,3885],{"class":129,"line":552},[127,3866,3867],{"class":1849},"      await",[127,3869,3870],{"class":1880}," navigator",[127,3872,101],{"class":1863},[127,3874,3875],{"class":1880},"clipboard",[127,3877,101],{"class":1863},[127,3879,3880],{"class":133},"writeText",[127,3882,1979],{"class":1863},[127,3884,3849],{"class":1880},[127,3886,1985],{"class":1863},[127,3888,3889,3892,3894,3897,3899,3902],{"class":129,"line":565},[127,3890,3891],{"class":1880},"      copied",[127,3893,101],{"class":1863},[127,3895,3896],{"class":1880},"value",[127,3898,1974],{"class":1863},[127,3900,3901],{"class":1849}," true",[127,3903,1864],{"class":1863},[127,3905,3906,3909,3912,3914],{"class":129,"line":578},[127,3907,3908],{"class":133},"      setTimeout",[127,3910,3911],{"class":1863},"(()",[127,3913,2974],{"class":1863},[127,3915,3182],{"class":1863},[127,3917,3918,3921,3923,3925,3927,3930],{"class":129,"line":591},[127,3919,3920],{"class":1880},"        copied",[127,3922,101],{"class":1863},[127,3924,3896],{"class":1880},[127,3926,1974],{"class":1863},[127,3928,3929],{"class":1849}," false",[127,3931,1864],{"class":1863},[127,3933,3934,3937,3941],{"class":129,"line":604},[127,3935,3936],{"class":1863},"      },",[127,3938,3940],{"class":3939},"sqbOQ"," 2000",[127,3942,1985],{"class":1863},[127,3944,3945,3948,3951,3953,3956,3958],{"class":129,"line":618},[127,3946,3947],{"class":1863},"    }",[127,3949,3950],{"class":1849}," catch",[127,3952,3846],{"class":1863},[127,3954,3955],{"class":1880},"error",[127,3957,3251],{"class":1863},[127,3959,3182],{"class":1863},[127,3961,3962,3965,3967,3969,3971,3973,3976,3978,3980,3983],{"class":129,"line":629},[127,3963,3964],{"class":1880},"      console",[127,3966,101],{"class":1863},[127,3968,3955],{"class":133},[127,3970,1979],{"class":1863},[127,3972,1860],{"class":1853},[127,3974,3975],{"class":136},"Failed to copy: ",[127,3977,1860],{"class":1853},[127,3979,2424],{"class":1863},[127,3981,3982],{"class":1880}," error",[127,3984,1985],{"class":1863},[127,3986,3987],{"class":129,"line":640},[127,3988,3989],{"class":1863},"    }\n",[127,3991,3992],{"class":129,"line":651},[127,3993,3994],{"class":1863},"  };\n",[127,3996,3997],{"class":129,"line":662},[127,3998,1870],{"emptyLinePlaceholder":1869},[127,4000,4001,4004],{"class":129,"line":673},[127,4002,4003],{"class":1849},"  return",[127,4005,3182],{"class":1863},[127,4007,4008,4011],{"class":129,"line":684},[127,4009,4010],{"class":1880},"    copied",[127,4012,2892],{"class":1863},[127,4014,4015,4018],{"class":129,"line":695},[127,4016,4017],{"class":1880},"    copyToClipboard",[127,4019,2892],{"class":1863},[127,4021,4022],{"class":129,"line":706},[127,4023,3994],{"class":1863},[127,4025,4026],{"class":129,"line":717},[127,4027,4028],{"class":1863},"}\n",[11,4030,4031,4032,4035,4036,4039,4040,4043],{},"Aquí estamos definiendo un composable llamado ",[54,4033,4034],{},"useClipboard"," que proporciona una función para copiar texto al portapapeles y un estado ",[36,4037,4038],{},"reactivo"," ",[54,4041,4042],{},"copied"," que indica si el texto fue copiado exitosamente.",[11,4045,4046,4047,1837],{},"Al implementarlo podríamos tener algo como esto. Crea un componente llamado ",[54,4048,4049],{},"src\u002Fcomponents\u002FClipboardExample.vue",[118,4051,4053],{"className":2398,"code":4052,"language":1892,"meta":123,"style":123},"\u003Ctemplate>\n  \u003Cdiv>\n    \u003Cinput v-model=\"textToCopy\" placeholder=\"Type something to copy\" \u002F>\n    \u003Cbutton @click=\"copyToClipboard(textToCopy)\">Copy to Clipboard\u003C\u002Fbutton>\n    \u003Cp v-if=\"copied\">Text copied!\u003C\u002Fp>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n\u003Cscript setup>\nimport { ref } from 'vue';\nimport { useClipboard } from '..\u002Fcomposables\u002FuseClipboard';\nconst { copied, copyToClipboard } = useClipboard();\nconst textToCopy = ref('');\n\u003C\u002Fscript>\n",[54,4054,4055,4063,4071,4104,4132,4159,4167,4175,4185,4205,4226,4246,4264],{"__ignoreMap":123},[127,4056,4057,4059,4061],{"class":129,"line":130},[127,4058,2143],{"class":1863},[127,4060,2477],{"class":1849},[127,4062,2138],{"class":1863},[127,4064,4065,4067,4069],{"class":129,"line":339},[127,4066,2161],{"class":1863},[127,4068,2301],{"class":1849},[127,4070,2138],{"class":1863},[127,4072,4073,4075,4078,4081,4083,4085,4088,4090,4093,4095,4097,4100,4102],{"class":129,"line":357},[127,4074,2171],{"class":1863},[127,4076,4077],{"class":1849},"input",[127,4079,4080],{"class":1880}," v-model",[127,4082,2151],{"class":1863},[127,4084,2182],{"class":1853},[127,4086,4087],{"class":136},"textToCopy",[127,4089,2182],{"class":1853},[127,4091,4092],{"class":1880}," placeholder",[127,4094,2151],{"class":1863},[127,4096,2182],{"class":1853},[127,4098,4099],{"class":136},"Type something to copy",[127,4101,2182],{"class":1853},[127,4103,2190],{"class":1863},[127,4105,4106,4108,4110,4112,4114,4116,4119,4121,4123,4126,4128,4130],{"class":129,"line":378},[127,4107,2171],{"class":1863},[127,4109,3420],{"class":1849},[127,4111,3423],{"class":1880},[127,4113,2151],{"class":1863},[127,4115,2182],{"class":1853},[127,4117,4118],{"class":136},"copyToClipboard(textToCopy)",[127,4120,2182],{"class":1853},[127,4122,2265],{"class":1863},[127,4124,4125],{"class":2268},"Copy to Clipboard",[127,4127,2272],{"class":1863},[127,4129,3420],{"class":1849},[127,4131,2138],{"class":1863},[127,4133,4134,4136,4138,4140,4142,4144,4146,4148,4150,4153,4155,4157],{"class":129,"line":513},[127,4135,2171],{"class":1863},[127,4137,11],{"class":1849},[127,4139,3385],{"class":1880},[127,4141,2151],{"class":1863},[127,4143,2182],{"class":1853},[127,4145,4042],{"class":136},[127,4147,2182],{"class":1853},[127,4149,2265],{"class":1863},[127,4151,4152],{"class":2268},"Text copied!",[127,4154,2272],{"class":1863},[127,4156,11],{"class":1849},[127,4158,2138],{"class":1863},[127,4160,4161,4163,4165],{"class":129,"line":524},[127,4162,2281],{"class":1863},[127,4164,2301],{"class":1849},[127,4166,2138],{"class":1863},[127,4168,4169,4171,4173],{"class":129,"line":539},[127,4170,2272],{"class":1863},[127,4172,2477],{"class":1849},[127,4174,2138],{"class":1863},[127,4176,4177,4179,4181,4183],{"class":129,"line":552},[127,4178,2143],{"class":1863},[127,4180,2326],{"class":1849},[127,4182,2410],{"class":1880},[127,4184,2138],{"class":1863},[127,4186,4187,4189,4191,4193,4195,4197,4199,4201,4203],{"class":129,"line":565},[127,4188,1850],{"class":1849},[127,4190,1877],{"class":1863},[127,4192,3780],{"class":1880},[127,4194,1884],{"class":1863},[127,4196,1887],{"class":1849},[127,4198,1854],{"class":1853},[127,4200,1892],{"class":136},[127,4202,1860],{"class":1853},[127,4204,1864],{"class":1863},[127,4206,4207,4209,4211,4213,4215,4217,4219,4222,4224],{"class":129,"line":578},[127,4208,1850],{"class":1849},[127,4210,1877],{"class":1863},[127,4212,3806],{"class":1880},[127,4214,1884],{"class":1863},[127,4216,1887],{"class":1849},[127,4218,1854],{"class":1853},[127,4220,4221],{"class":136},"..\u002Fcomposables\u002FuseClipboard",[127,4223,1860],{"class":1853},[127,4225,1864],{"class":1863},[127,4227,4228,4230,4232,4234,4236,4238,4240,4242,4244],{"class":129,"line":591},[127,4229,1968],{"class":1967},[127,4231,1877],{"class":1863},[127,4233,3817],{"class":1880},[127,4235,2424],{"class":1863},[127,4237,3838],{"class":1880},[127,4239,1884],{"class":1863},[127,4241,1974],{"class":1863},[127,4243,3806],{"class":133},[127,4245,3559],{"class":1863},[127,4247,4248,4250,4253,4255,4257,4259,4262],{"class":129,"line":604},[127,4249,1968],{"class":1967},[127,4251,4252],{"class":1880}," textToCopy",[127,4254,1974],{"class":1863},[127,4256,3780],{"class":133},[127,4258,1979],{"class":1863},[127,4260,4261],{"class":1853},"''",[127,4263,1985],{"class":1863},[127,4265,4266,4268,4270],{"class":129,"line":618},[127,4267,2272],{"class":1863},[127,4269,2326],{"class":1849},[127,4271,2138],{"class":1863},[11,4273,4274,4275,4277,4278,4280],{},"Y luego importa este componente en ",[54,4276,842],{}," y añádelo debajo del componente ",[54,4279,2585],{}," para probarlo:",[118,4282,4284],{"className":2398,"code":4283,"language":1892,"meta":123,"style":123},"\u003Cscript setup>\nimport { RouterLink, RouterView } from 'vue-router';\nimport HelloWorld from '.\u002Fcomponents\u002FHelloWorld.vue';\nimport ClipboardExample from '.\u002Fcomponents\u002FClipboardExample.vue';\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cheader>\n    \u003Cimg alt=\"Vue logo\" class=\"logo\" src=\"@\u002Fassets\u002Flogo.svg\" width=\"125\" height=\"125\" \u002F>\n\n    \u003Cdiv class=\"wrapper\">\n      \u003CHelloWorld msg=\"You did it!\" \u002F>\n      \u003CClipboardExample \u002F>\n      \u003C!-- Aquí -->\n      \u003Cnav>\n        \u003CRouterLink to=\"\u002F\">Home\u003C\u002FRouterLink>\n        \u003CRouterLink to=\"\u002Fabout\">About\u003C\u002FRouterLink>\n      \u003C\u002Fnav>\n    \u003C\u002Fdiv>\n  \u003C\u002Fheader>\n\n  \u003CRouterView \u002F>\n\u003C\u002Ftemplate>\n",[54,4285,4286,4296,4320,4336,4354,4362,4366,4374,4382,4440,4444,4462,4480,4489,4494,4502,4528,4554,4562,4570,4578,4582,4590],{"__ignoreMap":123},[127,4287,4288,4290,4292,4294],{"class":129,"line":130},[127,4289,2143],{"class":1863},[127,4291,2326],{"class":1849},[127,4293,2410],{"class":1880},[127,4295,2138],{"class":1863},[127,4297,4298,4300,4302,4304,4306,4308,4310,4312,4314,4316,4318],{"class":129,"line":339},[127,4299,1850],{"class":1849},[127,4301,1877],{"class":1863},[127,4303,2421],{"class":1880},[127,4305,2424],{"class":1863},[127,4307,2427],{"class":1880},[127,4309,1884],{"class":1863},[127,4311,1887],{"class":1849},[127,4313,1854],{"class":1853},[127,4315,2436],{"class":136},[127,4317,1860],{"class":1853},[127,4319,1864],{"class":1863},[127,4321,4322,4324,4326,4328,4330,4332,4334],{"class":129,"line":357},[127,4323,1850],{"class":1849},[127,4325,2447],{"class":1880},[127,4327,1887],{"class":1849},[127,4329,1854],{"class":1853},[127,4331,2454],{"class":136},[127,4333,1860],{"class":1853},[127,4335,1864],{"class":1863},[127,4337,4338,4340,4343,4345,4347,4350,4352],{"class":129,"line":378},[127,4339,1850],{"class":1849},[127,4341,4342],{"class":1880}," ClipboardExample",[127,4344,1887],{"class":1849},[127,4346,1854],{"class":1853},[127,4348,4349],{"class":136},".\u002Fcomponents\u002FClipboardExample.vue",[127,4351,1860],{"class":1853},[127,4353,1864],{"class":1863},[127,4355,4356,4358,4360],{"class":129,"line":513},[127,4357,2272],{"class":1863},[127,4359,2326],{"class":1849},[127,4361,2138],{"class":1863},[127,4363,4364],{"class":129,"line":524},[127,4365,1870],{"emptyLinePlaceholder":1869},[127,4367,4368,4370,4372],{"class":129,"line":539},[127,4369,2143],{"class":1863},[127,4371,2477],{"class":1849},[127,4373,2138],{"class":1863},[127,4375,4376,4378,4380],{"class":129,"line":552},[127,4377,2161],{"class":1863},[127,4379,2486],{"class":1849},[127,4381,2138],{"class":1863},[127,4383,4384,4386,4388,4390,4392,4394,4396,4398,4400,4402,4404,4406,4408,4410,4412,4414,4416,4418,4420,4422,4424,4426,4428,4430,4432,4434,4436,4438],{"class":129,"line":565},[127,4385,2171],{"class":1863},[127,4387,155],{"class":1849},[127,4389,2497],{"class":1880},[127,4391,2151],{"class":1863},[127,4393,2182],{"class":1853},[127,4395,2504],{"class":136},[127,4397,2182],{"class":1853},[127,4399,2509],{"class":1880},[127,4401,2151],{"class":1863},[127,4403,2182],{"class":1853},[127,4405,2516],{"class":136},[127,4407,2182],{"class":1853},[127,4409,2341],{"class":1880},[127,4411,2151],{"class":1863},[127,4413,2182],{"class":1853},[127,4415,2527],{"class":136},[127,4417,2182],{"class":1853},[127,4419,2532],{"class":1880},[127,4421,2151],{"class":1863},[127,4423,2182],{"class":1853},[127,4425,2539],{"class":136},[127,4427,2182],{"class":1853},[127,4429,2544],{"class":1880},[127,4431,2151],{"class":1863},[127,4433,2182],{"class":1853},[127,4435,2539],{"class":136},[127,4437,2182],{"class":1853},[127,4439,2190],{"class":1863},[127,4441,4442],{"class":129,"line":578},[127,4443,1870],{"emptyLinePlaceholder":1869},[127,4445,4446,4448,4450,4452,4454,4456,4458,4460],{"class":129,"line":591},[127,4447,2171],{"class":1863},[127,4449,2301],{"class":1849},[127,4451,2509],{"class":1880},[127,4453,2151],{"class":1863},[127,4455,2182],{"class":1853},[127,4457,2573],{"class":136},[127,4459,2182],{"class":1853},[127,4461,2138],{"class":1863},[127,4463,4464,4466,4468,4470,4472,4474,4476,4478],{"class":129,"line":604},[127,4465,2582],{"class":1863},[127,4467,2585],{"class":1849},[127,4469,2588],{"class":1880},[127,4471,2151],{"class":1863},[127,4473,2182],{"class":1853},[127,4475,2595],{"class":136},[127,4477,2182],{"class":1853},[127,4479,2190],{"class":1863},[127,4481,4482,4484,4487],{"class":129,"line":618},[127,4483,2582],{"class":1863},[127,4485,4486],{"class":1849},"ClipboardExample",[127,4488,2190],{"class":1863},[127,4490,4491],{"class":129,"line":629},[127,4492,4493],{"class":489},"      \u003C!-- Aquí -->\n",[127,4495,4496,4498,4500],{"class":129,"line":640},[127,4497,2582],{"class":1863},[127,4499,2610],{"class":1849},[127,4501,2138],{"class":1863},[127,4503,4504,4506,4508,4510,4512,4514,4516,4518,4520,4522,4524,4526],{"class":129,"line":651},[127,4505,2617],{"class":1863},[127,4507,2620],{"class":1849},[127,4509,2623],{"class":1880},[127,4511,2151],{"class":1863},[127,4513,2182],{"class":1853},[127,4515,2630],{"class":136},[127,4517,2182],{"class":1853},[127,4519,2265],{"class":1863},[127,4521,2637],{"class":2268},[127,4523,2272],{"class":1863},[127,4525,2620],{"class":1849},[127,4527,2138],{"class":1863},[127,4529,4530,4532,4534,4536,4538,4540,4542,4544,4546,4548,4550,4552],{"class":129,"line":662},[127,4531,2617],{"class":1863},[127,4533,2620],{"class":1849},[127,4535,2623],{"class":1880},[127,4537,2151],{"class":1863},[127,4539,2182],{"class":1853},[127,4541,2658],{"class":136},[127,4543,2182],{"class":1853},[127,4545,2265],{"class":1863},[127,4547,2665],{"class":2268},[127,4549,2272],{"class":1863},[127,4551,2620],{"class":1849},[127,4553,2138],{"class":1863},[127,4555,4556,4558,4560],{"class":129,"line":673},[127,4557,2676],{"class":1863},[127,4559,2610],{"class":1849},[127,4561,2138],{"class":1863},[127,4563,4564,4566,4568],{"class":129,"line":684},[127,4565,2685],{"class":1863},[127,4567,2301],{"class":1849},[127,4569,2138],{"class":1863},[127,4571,4572,4574,4576],{"class":129,"line":695},[127,4573,2281],{"class":1863},[127,4575,2486],{"class":1849},[127,4577,2138],{"class":1863},[127,4579,4580],{"class":129,"line":706},[127,4581,1870],{"emptyLinePlaceholder":1869},[127,4583,4584,4586,4588],{"class":129,"line":717},[127,4585,2161],{"class":1863},[127,4587,2708],{"class":1849},[127,4589,2190],{"class":1863},[127,4591,4592,4594,4596],{"class":129,"line":728},[127,4593,2272],{"class":1863},[127,4595,2477],{"class":1849},[127,4597,2138],{"class":1863},[11,4599,4600,4601,4603],{},"El estado ",[54,4602,4042],{}," nos permite mostrar un mensaje cuando el texto ha sido copiado exitosamente.",[11,4605,4606],{},"¿Que logramos con esto?",[29,4608,4609,4618,4624],{},[32,4610,4611,4614,4615,4617],{},[36,4612,4613],{},"Reutilización",": Podemos usar ",[54,4616,4034],{}," en cualquier componente que necesite funcionalidad de copiar al portapapeles, sin duplicar código.",[32,4619,4620,4623],{},[36,4621,4622],{},"Organización",": La lógica relacionada con el portapapeles está encapsulada en un solo lugar.",[32,4625,4626,4629],{},[36,4627,4628],{},"Mantenimiento",": Si necesitamos cambiar la forma en que copiamos al portapapeles, solo tenemos que modificar el composable, no todos los componentes que lo usan.",[768,4631,4633],{"id":4632},"cuál-es-la-diferencia-entre-un-composable-y-una-store-de-pinia","¿Cuál es la diferencia entre un composable y una store de Pinia?",[11,4635,4636,4639,4640,4643],{},[36,4637,4638],{},"Estado global vs estado local",": Las stores de Pinia están diseñadas para manejar un estado global en la aplicación, datos que deben ser ",[36,4641,4642],{},"accesibles y compartidos"," desde cualquier parte.",[11,4645,4646,4647,4650,4651,4653],{},"Los composables, por otro lado, manejan lógica y estado que puede ser reutilizado en múltiples componentes, pero que ",[36,4648,4649],{},"nada de eso es compartido",". Por ejemplo, si tengo varios componentes que necesitan funcionalidad para copiar al portapapeles (y que necesitan algún control de estado), usaría un composable, y el estado ",[54,4652,4042],{}," sería local en cada instancia del composable. En cambio, si necesito saber en varios lugares si actualmente se ha realizado una copia al portapapeles a nivel de aplicación, usaría una store de Pinia, porque aquí si se darían cuenta todos los componentes y todos podrían reaccionar a ese cambio.",[11,4655,4656,4657,4659,4660,4662],{},"Pongámoslo como un ejemplo: gracias a la variable ",[54,4658,4042],{}," puedo mostrar algo dentro del mismo componente, como el mensaje de \"Texto copiado\", ahora, si quisiera que por ejemplo el layout de mi aplicación muestre un ícono en la barra de navegación cada vez que se copie algo al portapapeles, entonces sería mejor que utilizara una store de Pinia para manejar ese estado globalmente, así al copiar desde mi componente ",[54,4661,4486],{},", el layout también se daría cuenta del cambio y podría mostrar el ícono.",[768,4664,4666],{"id":4665},"cuál-es-la-diferencia-entre-un-composable-y-un-archivo-de-utilidades-utils","¿Cuál es la diferencia entre un composable y un archivo de utilidades (utils)?",[11,4668,4669,4670,4672],{},"Las funciones de utilidades son generalmente más simples y no tienen estado, reciben entradas (algunas) y devuelven salidas sin efectos secundarios. Por ejemplo, si no necesitáramos el estado ",[54,4671,4042],{}," y solo quisiéramos una función para copiar texto, podríamos crear una simple función de utilidad en lugar de un composable:",[118,4674,4676],{"className":1840,"code":4675,"language":1842,"meta":123,"style":123},"export function copyToClipboard(text) {\n  return navigator.clipboard.writeText(text);\n}\n",[54,4677,4678,4694,4714],{"__ignoreMap":123},[127,4679,4680,4682,4684,4686,4688,4690,4692],{"class":129,"line":130},[127,4681,3011],{"class":1849},[127,4683,3803],{"class":1967},[127,4685,3838],{"class":133},[127,4687,1979],{"class":1863},[127,4689,3849],{"class":1880},[127,4691,3251],{"class":1863},[127,4693,3182],{"class":1863},[127,4695,4696,4698,4700,4702,4704,4706,4708,4710,4712],{"class":129,"line":339},[127,4697,4003],{"class":1849},[127,4699,3870],{"class":1880},[127,4701,101],{"class":1863},[127,4703,3875],{"class":1880},[127,4705,101],{"class":1863},[127,4707,3880],{"class":133},[127,4709,1979],{"class":1863},[127,4711,3849],{"class":1880},[127,4713,1985],{"class":1863},[127,4715,4716],{"class":129,"line":357},[127,4717,4028],{"class":1863},[11,4719,4720],{},"Lecturas recomendadas:",[29,4722,4723,4730,4737],{},[32,4724,4725],{},[41,4726,4729],{"href":4727,"target":43,"rel":4728},"https:\u002F\u002Fvuejs.org\u002Fguide\u002Freusability\u002Fcomposables.html",[46,47],"Composables - Vue.js Documentation",[32,4731,4732],{},[41,4733,4736],{"href":4734,"target":43,"rel":4735},"https:\u002F\u002Fdev.to\u002Fjacobandrewsky\u002Fgood-practices-and-design-patterns-for-vue-composables-24lk",[46,47],"Good Practices and Design Patterns for Vue Composables",[32,4738,4739],{},[41,4740,4743],{"href":4741,"target":43,"rel":4742},"https:\u002F\u002Frobconery.com\u002Ffrontend\u002Fwhat-should-be-a-plugin-vs-a-composable-vs-a-store-in-nuxt\u002F",[46,47],"What should be a Plugin vs a Composable vs a Store in Nuxt",[768,4745,4747],{"id":4746},"vueuse","VueUse",[11,4749,4750,4754],{},[41,4751,4747],{"href":4752,"target":43,"rel":4753},"https:\u002F\u002Fvueuse.org\u002F",[46,47]," es una colección de composables para Vue 3. Proporciona una amplia gama de funcionalidades listas para usar, desde manejo de estado hasta interacciones con el DOM y APIs del navegador. Puedes explorar la documentación oficial para ver todos los composables disponibles y cómo usarlos en tus proyectos.",[11,4756,4757,4760],{},[155,4758],{"alt":4747,"src":4759},"\u002Fblog\u002Fgetting-started-vue-vite\u002Fshared\u002Fvue-use.webp",[160,4761,4747],{},[11,4763,4764],{},"Algunos ejemplos populares de composables en VueUse incluyen:",[29,4766,4767,4773,4779,4785,4791],{},[32,4768,4769,4772],{},[54,4770,4771],{},"useBreakpoints",": para poder manejar breakpoints en tu aplicación y ayudar con el diseño responsivo.",[32,4774,4775,4778],{},[54,4776,4777],{},"useFetch",": para realizar solicitudes HTTP de manera sencilla.",[32,4780,4781,4784],{},[54,4782,4783],{},"useLocalStorage",": para sincronizar datos con el almacenamiento local del navegador.",[32,4786,4787,4790],{},[54,4788,4789],{},"useDark",": para manejar temas oscuros y claros en la aplicación.",[32,4792,4793,4795],{},[54,4794,4034],{},": para copiar texto al portapapeles (similar al que creamos antes).",[11,4797,4798],{},"Es una colección muy útil que puede ahorrarte tiempo si necesitas alguna de estas funcionalidades.\nSolo ten cuidado de no sobrecargar tu proyecto con dependencias innecesarias, instala solo lo que realmente vayas a usar y solo si realmente necesitas una librería para ella.",[18,4800],{},[21,4802,4804],{"id":4803},"eslint-y-prettier","ESLint y Prettier",[11,4806,4807,4808,4811],{},"Acostúmbrate a usar ",[36,4809,4810],{},"ESLint",", es demasiado útil para mantener la calidad del código y evitar errores comunes.\nLa configuración generada por Vite es un buen punto de partida, pero siempre recomiendo personalizarla.",[11,4813,4814,4815,4819,4820,101],{},"Puedes explorar las reglas disponibles en la documentación oficial ",[41,4816,4810],{"href":4817,"target":43,"rel":4818},"https:\u002F\u002Feslint.org\u002Fdocs\u002Frules\u002F",[46,47]," y de ",[41,4821,4824],{"href":4822,"target":43,"rel":4823},"https:\u002F\u002Feslint.vuejs.org\u002Frules\u002F",[46,47],"eslint-plugin-vue",[11,4826,4827],{},"Todas las reglas pueden ser configuradas como \"off\", \"warn\" o \"error\", dependiendo de la severidad que quieras asignarles:",[118,4829,4833],{"className":4830,"code":4831,"language":4832,"meta":123,"style":123},"language-js shiki shiki-themes vitesse-light vitesse-dark","\"no-console\": \"warn\", \u002F\u002F Muestra una advertencia si se usa console.log\n\"eqeqeq\": \"error\", \u002F\u002F Fuerza el uso de === y !== en lugar de == y !=\n\"vue\u002Fmulti-word-component-names\": \"off\", \u002F\u002F Desactiva la regla que obliga a usar nombres de componentes con múltiples palabras\n","js",[54,4834,4835,4859,4881],{"__ignoreMap":123},[127,4836,4837,4839,4842,4844,4847,4849,4852,4854,4856],{"class":129,"line":130},[127,4838,2182],{"class":1853},[127,4840,4841],{"class":136},"no-console",[127,4843,2182],{"class":1853},[127,4845,4846],{"class":2268},": ",[127,4848,2182],{"class":1853},[127,4850,4851],{"class":136},"warn",[127,4853,2182],{"class":1853},[127,4855,2424],{"class":1863},[127,4857,4858],{"class":489}," \u002F\u002F Muestra una advertencia si se usa console.log\n",[127,4860,4861,4863,4866,4868,4870,4872,4874,4876,4878],{"class":129,"line":339},[127,4862,2182],{"class":1853},[127,4864,4865],{"class":136},"eqeqeq",[127,4867,2182],{"class":1853},[127,4869,4846],{"class":2268},[127,4871,2182],{"class":1853},[127,4873,3955],{"class":136},[127,4875,2182],{"class":1853},[127,4877,2424],{"class":1863},[127,4879,4880],{"class":489}," \u002F\u002F Fuerza el uso de === y !== en lugar de == y !=\n",[127,4882,4883,4885,4888,4890,4892,4894,4897,4899,4901],{"class":129,"line":357},[127,4884,2182],{"class":1853},[127,4886,4887],{"class":136},"vue\u002Fmulti-word-component-names",[127,4889,2182],{"class":1853},[127,4891,4846],{"class":2268},[127,4893,2182],{"class":1853},[127,4895,4896],{"class":136},"off",[127,4898,2182],{"class":1853},[127,4900,2424],{"class":1863},[127,4902,4903],{"class":489}," \u002F\u002F Desactiva la regla que obliga a usar nombres de componentes con múltiples palabras\n",[11,4905,4906,4907,4910,4911,101],{},"En el proyecto que creamos, puedes usar el comando ",[54,4908,4909],{},"npm run lint"," para revisar todo tu código según la configuración del archivo ",[54,4912,4913],{},"eslint.config.js",[11,4915,4916,4919],{},[36,4917,4918],{},"Sobre Prettier",", existe cierto debate sobre su uso, a mucha gente no le gusta porque puede imponer un estilo que no les agrada, así que pruébalo, explóralo y úsalo solo si te sientes cómodo con él.\nEn lugar de Prettier, para intentar siempre mantener un estilo consistente, puedes usar alternativas como EditorConfig, las propias reglas de ESLint o la configuración del editor de código que estés usando.",[11,4921,4922],{},"Si usas algunas de estas herramientas puedes explorar sus extensiones:",[29,4924,4925,4932,4939],{},[32,4926,4927],{},[41,4928,4931],{"href":4929,"target":43,"rel":4930},"https:\u002F\u002Fmarketplace.visualstudio.com\u002Fitems?itemName=dbaeumer.vscode-eslint",[46,47],"ESLint extension for VS Code",[32,4933,4934],{},[41,4935,4938],{"href":4936,"target":43,"rel":4937},"https:\u002F\u002Fmarketplace.visualstudio.com\u002Fitems?itemName=esbenp.prettier-vscode",[46,47],"Prettier - Code formatter",[32,4940,4941],{},[41,4942,4945],{"href":4943,"target":43,"rel":4944},"https:\u002F\u002Fmarketplace.visualstudio.com\u002Fitems?itemName=EditorConfig.EditorConfig",[46,47],"EditorConfig for VS Code",[18,4947],{},[21,4949,4951],{"id":4950},"extra-instalando-tailwind-css-v4","EXTRA: Instalando Tailwind CSS v4",[11,4953,4954,4955,4960],{},"CSS puro está más que bien, puede lograr resultados increíbles (a veces incluso ",[41,4956,4959],{"href":4957,"target":43,"rel":4958},"https:\u002F\u002Fgithub.com\u002Fyou-dont-need\u002FYou-Dont-Need-JavaScript",[46,47],"sin necesitar JavaScript","), pero un opción que tienes para acelerar tu desarrollo y mantener un estilo consistente es Tailwind CSS.",[11,4962,4963,4964,4969],{},"Siguiendo los pasos oficiales de la ",[41,4965,4968],{"href":4966,"target":43,"rel":4967},"https:\u002F\u002Ftailwindcss.com\u002Fdocs\u002Finstallation\u002Fusing-vite",[46,47],"documentación de Tailwind CSS",", instalemos Tailwind CSS v4 en nuestro proyecto Vue con Vite.",[11,4971,4972],{},"Primero (estando dentro de la carpeta del proyecto), instala Tailwind CSS y su plugin para Vite:",[118,4974,4976],{"className":120,"code":4975,"language":122,"meta":123,"style":123},"npm install tailwindcss @tailwindcss\u002Fvite\n",[54,4977,4978],{"__ignoreMap":123},[127,4979,4980,4982,4985,4988],{"class":129,"line":130},[127,4981,56],{"class":133},[127,4983,4984],{"class":136}," install",[127,4986,4987],{"class":136}," tailwindcss",[127,4989,4990],{"class":136}," @tailwindcss\u002Fvite\n",[11,4992,4993,4994,1837],{},"Luego, agregamos el plugin a nuestro archivo ",[54,4995,4996],{},"vite.config.js",[118,4998,5000],{"className":1840,"code":4999,"language":1842,"meta":123,"style":123},"import { fileURLToPath, URL } from 'node:url';\n\nimport { defineConfig } from 'vite';\nimport vue from '@vitejs\u002Fplugin-vue';\nimport vueDevTools from 'vite-plugin-vue-devtools';\nimport tailwindcss from '@tailwindcss\u002Fvite'; \u002F\u002F Importamos el plugin\n\n\u002F\u002F https:\u002F\u002Fvite.dev\u002Fconfig\u002F\nexport default defineConfig({\n  plugins: [\n    vue(),\n    vueDevTools(),\n    tailwindcss(), \u002F\u002F Agregamos a la configuración de Vite\n  ],\n  resolve: {\n    alias: {\n      '@': fileURLToPath(new URL('.\u002Fsrc', import.meta.url)),\n    },\n  },\n});\n",[54,5001,5002,5029,5033,5055,5073,5091,5112,5116,5121,5131,5140,5148,5155,5166,5170,5179,5188,5234,5238,5242],{"__ignoreMap":123},[127,5003,5004,5006,5008,5011,5013,5016,5018,5020,5022,5025,5027],{"class":129,"line":130},[127,5005,1850],{"class":1849},[127,5007,1877],{"class":1863},[127,5009,5010],{"class":1880}," fileURLToPath",[127,5012,2424],{"class":1863},[127,5014,5015],{"class":1880}," URL",[127,5017,1884],{"class":1863},[127,5019,1887],{"class":1849},[127,5021,1854],{"class":1853},[127,5023,5024],{"class":136},"node:url",[127,5026,1860],{"class":1853},[127,5028,1864],{"class":1863},[127,5030,5031],{"class":129,"line":339},[127,5032,1870],{"emptyLinePlaceholder":1869},[127,5034,5035,5037,5039,5042,5044,5046,5048,5051,5053],{"class":129,"line":357},[127,5036,1850],{"class":1849},[127,5038,1877],{"class":1863},[127,5040,5041],{"class":1880}," defineConfig",[127,5043,1884],{"class":1863},[127,5045,1887],{"class":1849},[127,5047,1854],{"class":1853},[127,5049,5050],{"class":136},"vite",[127,5052,1860],{"class":1853},[127,5054,1864],{"class":1863},[127,5056,5057,5059,5062,5064,5066,5069,5071],{"class":129,"line":378},[127,5058,1850],{"class":1849},[127,5060,5061],{"class":1880}," vue",[127,5063,1887],{"class":1849},[127,5065,1854],{"class":1853},[127,5067,5068],{"class":136},"@vitejs\u002Fplugin-vue",[127,5070,1860],{"class":1853},[127,5072,1864],{"class":1863},[127,5074,5075,5077,5080,5082,5084,5087,5089],{"class":129,"line":513},[127,5076,1850],{"class":1849},[127,5078,5079],{"class":1880}," vueDevTools",[127,5081,1887],{"class":1849},[127,5083,1854],{"class":1853},[127,5085,5086],{"class":136},"vite-plugin-vue-devtools",[127,5088,1860],{"class":1853},[127,5090,1864],{"class":1863},[127,5092,5093,5095,5097,5099,5101,5104,5106,5109],{"class":129,"line":524},[127,5094,1850],{"class":1849},[127,5096,4987],{"class":1880},[127,5098,1887],{"class":1849},[127,5100,1854],{"class":1853},[127,5102,5103],{"class":136},"@tailwindcss\u002Fvite",[127,5105,1860],{"class":1853},[127,5107,5108],{"class":1863},";",[127,5110,5111],{"class":489}," \u002F\u002F Importamos el plugin\n",[127,5113,5114],{"class":129,"line":539},[127,5115,1870],{"emptyLinePlaceholder":1869},[127,5117,5118],{"class":129,"line":552},[127,5119,5120],{"class":489},"\u002F\u002F https:\u002F\u002Fvite.dev\u002Fconfig\u002F\n",[127,5122,5123,5125,5127,5129],{"class":129,"line":565},[127,5124,3011],{"class":1849},[127,5126,3014],{"class":1849},[127,5128,5041],{"class":133},[127,5130,2831],{"class":1863},[127,5132,5133,5136,5138],{"class":129,"line":578},[127,5134,5135],{"class":332},"  plugins",[127,5137,1837],{"class":1863},[127,5139,2871],{"class":1863},[127,5141,5142,5145],{"class":129,"line":591},[127,5143,5144],{"class":133},"    vue",[127,5146,5147],{"class":1863},"(),\n",[127,5149,5150,5153],{"class":129,"line":604},[127,5151,5152],{"class":133},"    vueDevTools",[127,5154,5147],{"class":1863},[127,5156,5157,5160,5163],{"class":129,"line":618},[127,5158,5159],{"class":133},"    tailwindcss",[127,5161,5162],{"class":1863},"(),",[127,5164,5165],{"class":489}," \u002F\u002F Agregamos a la configuración de Vite\n",[127,5167,5168],{"class":129,"line":629},[127,5169,2997],{"class":1863},[127,5171,5172,5175,5177],{"class":129,"line":640},[127,5173,5174],{"class":332},"  resolve",[127,5176,1837],{"class":1863},[127,5178,3182],{"class":1863},[127,5180,5181,5184,5186],{"class":129,"line":651},[127,5182,5183],{"class":332},"    alias",[127,5185,1837],{"class":1863},[127,5187,3182],{"class":1863},[127,5189,5190,5193,5196,5198,5200,5202,5204,5207,5209,5211,5213,5216,5218,5220,5222,5224,5226,5228,5231],{"class":129,"line":662},[127,5191,5192],{"class":1853},"      '",[127,5194,5195],{"class":136},"@",[127,5197,1860],{"class":1853},[127,5199,1837],{"class":1863},[127,5201,5010],{"class":133},[127,5203,1979],{"class":1863},[127,5205,5206],{"class":1967},"new",[127,5208,5015],{"class":133},[127,5210,1979],{"class":1863},[127,5212,1860],{"class":1853},[127,5214,5215],{"class":136},".\u002Fsrc",[127,5217,1860],{"class":1853},[127,5219,2424],{"class":1863},[127,5221,2977],{"class":1849},[127,5223,101],{"class":1863},[127,5225,2174],{"class":332},[127,5227,101],{"class":1863},[127,5229,5230],{"class":1880},"url",[127,5232,5233],{"class":1863},")),\n",[127,5235,5236],{"class":129,"line":673},[127,5237,2924],{"class":1863},[127,5239,5240],{"class":129,"line":684},[127,5241,3337],{"class":1863},[127,5243,5244],{"class":129,"line":695},[127,5245,3002],{"class":1863},[11,5247,5248,5249,5252],{},"Luego en el archivo ",[54,5250,5251],{},"src\u002Fassets\u002Fmain.css",", reemplaza todo el contenido por lo siguiente:",[118,5254,5258],{"className":5255,"code":5256,"language":5257,"meta":123,"style":123},"language-css shiki shiki-themes vitesse-light vitesse-dark","@import '.\u002Fbase.css';\n\n@import 'tailwindcss';\n","css",[54,5259,5260,5275,5279],{"__ignoreMap":123},[127,5261,5262,5264,5266,5268,5271,5273],{"class":129,"line":130},[127,5263,5195],{"class":1863},[127,5265,1850],{"class":1849},[127,5267,1854],{"class":1853},[127,5269,5270],{"class":136},".\u002Fbase.css",[127,5272,1860],{"class":1853},[127,5274,1864],{"class":1863},[127,5276,5277],{"class":129,"line":339},[127,5278,1870],{"emptyLinePlaceholder":1869},[127,5280,5281,5283,5285,5287,5290,5292],{"class":129,"line":357},[127,5282,5195],{"class":1863},[127,5284,1850],{"class":1849},[127,5286,1854],{"class":1853},[127,5288,5289],{"class":136},"tailwindcss",[127,5291,1860],{"class":1853},[127,5293,1864],{"class":1863},[11,5295,5296,5297,5300],{},"Aprovechamos a limpiar el archivo ",[54,5298,5299],{},"src\u002Fassets\u002Fbase.css"," y dejar solo lo necesario:",[118,5302,5304],{"className":5255,"code":5303,"language":5257,"meta":123,"style":123},"*,\n*::before,\n*::after {\n  box-sizing: border-box;\n  margin: 0;\n  font-weight: normal;\n}\n\nbody {\n  min-height: 100vh;\n  color: #333;\n  background: #fff;\n  transition:\n    color 0.5s,\n    background-color 0.5s;\n  line-height: 1.6;\n  font-family: Inter, sans-serif;\n  font-size: 15px;\n  text-rendering: optimizeLegibility;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n",[54,5305,5306,5313,5325,5336,5348,5360,5372,5376,5380,5386,5401,5416,5430,5438,5451,5463,5475,5492,5507,5519,5531,5543],{"__ignoreMap":123},[127,5307,5308,5311],{"class":129,"line":130},[127,5309,5310],{"class":1849},"*",[127,5312,2892],{"class":1863},[127,5314,5315,5317,5320,5323],{"class":129,"line":339},[127,5316,5310],{"class":1849},[127,5318,5319],{"class":1863},"::",[127,5321,5322],{"class":1880},"before",[127,5324,2892],{"class":1863},[127,5326,5327,5329,5331,5334],{"class":129,"line":357},[127,5328,5310],{"class":1849},[127,5330,5319],{"class":1863},[127,5332,5333],{"class":1880},"after",[127,5335,3182],{"class":1863},[127,5337,5338,5341,5343,5346],{"class":129,"line":378},[127,5339,5340],{"class":332},"  box-sizing",[127,5342,1837],{"class":1863},[127,5344,5345],{"class":3258}," border-box",[127,5347,1864],{"class":1863},[127,5349,5350,5353,5355,5358],{"class":129,"line":513},[127,5351,5352],{"class":332},"  margin",[127,5354,1837],{"class":1863},[127,5356,5357],{"class":3939}," 0",[127,5359,1864],{"class":1863},[127,5361,5362,5365,5367,5370],{"class":129,"line":524},[127,5363,5364],{"class":332},"  font-weight",[127,5366,1837],{"class":1863},[127,5368,5369],{"class":3258}," normal",[127,5371,1864],{"class":1863},[127,5373,5374],{"class":129,"line":539},[127,5375,4028],{"class":1863},[127,5377,5378],{"class":129,"line":552},[127,5379,1870],{"emptyLinePlaceholder":1869},[127,5381,5382,5384],{"class":129,"line":565},[127,5383,2292],{"class":1849},[127,5385,3182],{"class":1863},[127,5387,5388,5391,5393,5396,5399],{"class":129,"line":578},[127,5389,5390],{"class":332},"  min-height",[127,5392,1837],{"class":1863},[127,5394,5395],{"class":3939}," 100",[127,5397,5398],{"class":1967},"vh",[127,5400,1864],{"class":1863},[127,5402,5403,5406,5408,5411,5414],{"class":129,"line":591},[127,5404,5405],{"class":332},"  color",[127,5407,1837],{"class":1863},[127,5409,5410],{"class":1863}," #",[127,5412,5413],{"class":3258},"333",[127,5415,1864],{"class":1863},[127,5417,5418,5421,5423,5425,5428],{"class":129,"line":604},[127,5419,5420],{"class":332},"  background",[127,5422,1837],{"class":1863},[127,5424,5410],{"class":1863},[127,5426,5427],{"class":3258},"fff",[127,5429,1864],{"class":1863},[127,5431,5432,5435],{"class":129,"line":618},[127,5433,5434],{"class":332},"  transition",[127,5436,5437],{"class":1863},":\n",[127,5439,5440,5443,5446,5449],{"class":129,"line":629},[127,5441,5442],{"class":3258},"    color",[127,5444,5445],{"class":3939}," 0.5",[127,5447,5448],{"class":1967},"s",[127,5450,2892],{"class":1863},[127,5452,5453,5456,5459,5461],{"class":129,"line":640},[127,5454,5455],{"class":2268},"    background-color ",[127,5457,5458],{"class":3939},"0.5",[127,5460,5448],{"class":1967},[127,5462,1864],{"class":1863},[127,5464,5465,5468,5470,5473],{"class":129,"line":651},[127,5466,5467],{"class":332},"  line-height",[127,5469,1837],{"class":1863},[127,5471,5472],{"class":3939}," 1.6",[127,5474,1864],{"class":1863},[127,5476,5477,5480,5482,5485,5487,5490],{"class":129,"line":662},[127,5478,5479],{"class":332},"  font-family",[127,5481,1837],{"class":1863},[127,5483,5484],{"class":2268}," Inter",[127,5486,2424],{"class":1863},[127,5488,5489],{"class":3258}," sans-serif",[127,5491,1864],{"class":1863},[127,5493,5494,5497,5499,5502,5505],{"class":129,"line":673},[127,5495,5496],{"class":332},"  font-size",[127,5498,1837],{"class":1863},[127,5500,5501],{"class":3939}," 15",[127,5503,5504],{"class":1967},"px",[127,5506,1864],{"class":1863},[127,5508,5509,5512,5514,5517],{"class":129,"line":684},[127,5510,5511],{"class":332},"  text-rendering",[127,5513,1837],{"class":1863},[127,5515,5516],{"class":3258}," optimizeLegibility",[127,5518,1864],{"class":1863},[127,5520,5521,5524,5526,5529],{"class":129,"line":695},[127,5522,5523],{"class":332},"  -webkit-font-smoothing",[127,5525,1837],{"class":1863},[127,5527,5528],{"class":3258}," antialiased",[127,5530,1864],{"class":1863},[127,5532,5533,5536,5538,5541],{"class":129,"line":706},[127,5534,5535],{"class":332},"  -moz-osx-font-smoothing",[127,5537,1837],{"class":1863},[127,5539,5540],{"class":3258}," grayscale",[127,5542,1864],{"class":1863},[127,5544,5545],{"class":129,"line":717},[127,5546,4028],{"class":1863},[11,5548,5549,5550,5553],{},"Ahora probemos que todo funciona correctamente. Primero, detén el servidor de desarrollo si está corriendo (",[54,5551,5552],{},"Ctrl + C"," en la terminal) y luego vuelve a iniciarlo:",[118,5555,5556],{"className":120,"code":384,"language":122,"meta":123,"style":123},[54,5557,5558],{"__ignoreMap":123},[127,5559,5560,5562,5564],{"class":129,"line":130},[127,5561,56],{"class":133},[127,5563,372],{"class":136},[127,5565,395],{"class":136},[11,5567,2392,5568,5570],{},[54,5569,2395],{}," y reemplaza todo el contenido por lo siguiente:",[118,5572,5574],{"className":2398,"code":5573,"language":1892,"meta":123,"style":123},"\u003Cscript setup>\nimport { RouterLink, RouterView } from 'vue-router';\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cdiv class=\"flex h-screen flex-col bg-gray-50\">\n    \u003C!-- App Bar -->\n    \u003Cheader class=\"flex h-16 items-center justify-between bg-white px-6 shadow-sm\">\n      \u003Cdiv class=\"text-xl font-bold text-gray-800\">My Project\u003C\u002Fdiv>\n      \u003Cnav class=\"flex gap-4\" aria-label=\"Main Navigation\">\n        \u003Ca href=\"#\" class=\"text-gray-600 hover:text-gray-900\">Home\u003C\u002Fa>\n        \u003Ca href=\"#\" class=\"text-gray-600 hover:text-gray-900\">Profile\u003C\u002Fa>\n      \u003C\u002Fnav>\n    \u003C\u002Fheader>\n\n    \u003Cdiv class=\"flex flex-1 overflow-hidden\">\n      \u003C!-- Sidebar -->\n      \u003Caside class=\"w-64 overflow-y-auto bg-white border-r border-gray-200\">\n        \u003Cnav class=\"p-4 space-y-2\" aria-label=\"Sidebar Navigation\">\n          \u003CRouterLink\n            to=\"\u002F\"\n            class=\"block rounded-md px-4 py-2 text-gray-700 hover:bg-gray-100\"\n            exact-active-class=\"text-indigo-700 font-bold\"\n          >\n            Home\n          \u003C\u002FRouterLink>\n          \u003CRouterLink\n            to=\"\u002Fabout\"\n            class=\"block rounded-md px-4 py-2 text-gray-700 hover:bg-gray-100\"\n            exact-active-class=\"text-indigo-700 font-bold\"\n          >\n            About\n          \u003C\u002FRouterLink>\n        \u003C\u002Fnav>\n      \u003C\u002Faside>\n\n      \u003C!-- Main Content -->\n      \u003Cmain class=\"flex-1 overflow-y-auto p-6\">\n        \u003CRouterView \u002F>\n      \u003C\u002Fmain>\n    \u003C\u002Fdiv>\n\n    \u003C!-- Footer -->\n    \u003Cfooter\n      class=\"flex h-12 items-center justify-center bg-white border-t border-gray-200 text-sm text-gray-500\"\n    >\n      &copy; 2025 My Project. All rights reserved.\n    \u003C\u002Ffooter>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n",[54,5575,5576,5586,5610,5618,5622,5630,5649,5654,5673,5701,5732,5770,5807,5815,5823,5827,5846,5851,5871,5901,5909,5923,5937,5951,5956,5961,5970,5976,5988,6000,6012,6016,6021,6029,6038,6046,6050,6055,6075,6083,6091,6099,6103,6108,6115,6129,6134,6148,6158,6167],{"__ignoreMap":123},[127,5577,5578,5580,5582,5584],{"class":129,"line":130},[127,5579,2143],{"class":1863},[127,5581,2326],{"class":1849},[127,5583,2410],{"class":1880},[127,5585,2138],{"class":1863},[127,5587,5588,5590,5592,5594,5596,5598,5600,5602,5604,5606,5608],{"class":129,"line":339},[127,5589,1850],{"class":1849},[127,5591,1877],{"class":1863},[127,5593,2421],{"class":1880},[127,5595,2424],{"class":1863},[127,5597,2427],{"class":1880},[127,5599,1884],{"class":1863},[127,5601,1887],{"class":1849},[127,5603,1854],{"class":1853},[127,5605,2436],{"class":136},[127,5607,1860],{"class":1853},[127,5609,1864],{"class":1863},[127,5611,5612,5614,5616],{"class":129,"line":357},[127,5613,2272],{"class":1863},[127,5615,2326],{"class":1849},[127,5617,2138],{"class":1863},[127,5619,5620],{"class":129,"line":378},[127,5621,1870],{"emptyLinePlaceholder":1869},[127,5623,5624,5626,5628],{"class":129,"line":513},[127,5625,2143],{"class":1863},[127,5627,2477],{"class":1849},[127,5629,2138],{"class":1863},[127,5631,5632,5634,5636,5638,5640,5642,5645,5647],{"class":129,"line":524},[127,5633,2161],{"class":1863},[127,5635,2301],{"class":1849},[127,5637,2509],{"class":1880},[127,5639,2151],{"class":1863},[127,5641,2182],{"class":1853},[127,5643,5644],{"class":136},"flex h-screen flex-col bg-gray-50",[127,5646,2182],{"class":1853},[127,5648,2138],{"class":1863},[127,5650,5651],{"class":129,"line":539},[127,5652,5653],{"class":489},"    \u003C!-- App Bar -->\n",[127,5655,5656,5658,5660,5662,5664,5666,5669,5671],{"class":129,"line":552},[127,5657,2171],{"class":1863},[127,5659,2486],{"class":1849},[127,5661,2509],{"class":1880},[127,5663,2151],{"class":1863},[127,5665,2182],{"class":1853},[127,5667,5668],{"class":136},"flex h-16 items-center justify-between bg-white px-6 shadow-sm",[127,5670,2182],{"class":1853},[127,5672,2138],{"class":1863},[127,5674,5675,5677,5679,5681,5683,5685,5688,5690,5692,5695,5697,5699],{"class":129,"line":565},[127,5676,2582],{"class":1863},[127,5678,2301],{"class":1849},[127,5680,2509],{"class":1880},[127,5682,2151],{"class":1863},[127,5684,2182],{"class":1853},[127,5686,5687],{"class":136},"text-xl font-bold text-gray-800",[127,5689,2182],{"class":1853},[127,5691,2265],{"class":1863},[127,5693,5694],{"class":2268},"My Project",[127,5696,2272],{"class":1863},[127,5698,2301],{"class":1849},[127,5700,2138],{"class":1863},[127,5702,5703,5705,5707,5709,5711,5713,5716,5718,5721,5723,5725,5728,5730],{"class":129,"line":578},[127,5704,2582],{"class":1863},[127,5706,2610],{"class":1849},[127,5708,2509],{"class":1880},[127,5710,2151],{"class":1863},[127,5712,2182],{"class":1853},[127,5714,5715],{"class":136},"flex gap-4",[127,5717,2182],{"class":1853},[127,5719,5720],{"class":1880}," aria-label",[127,5722,2151],{"class":1863},[127,5724,2182],{"class":1853},[127,5726,5727],{"class":136},"Main Navigation",[127,5729,2182],{"class":1853},[127,5731,2138],{"class":1863},[127,5733,5734,5736,5738,5740,5742,5744,5747,5749,5751,5753,5755,5758,5760,5762,5764,5766,5768],{"class":129,"line":591},[127,5735,2617],{"class":1863},[127,5737,41],{"class":1849},[127,5739,2212],{"class":1880},[127,5741,2151],{"class":1863},[127,5743,2182],{"class":1853},[127,5745,5746],{"class":136},"#",[127,5748,2182],{"class":1853},[127,5750,2509],{"class":1880},[127,5752,2151],{"class":1863},[127,5754,2182],{"class":1853},[127,5756,5757],{"class":136},"text-gray-600 hover:text-gray-900",[127,5759,2182],{"class":1853},[127,5761,2265],{"class":1863},[127,5763,2637],{"class":2268},[127,5765,2272],{"class":1863},[127,5767,41],{"class":1849},[127,5769,2138],{"class":1863},[127,5771,5772,5774,5776,5778,5780,5782,5784,5786,5788,5790,5792,5794,5796,5798,5801,5803,5805],{"class":129,"line":604},[127,5773,2617],{"class":1863},[127,5775,41],{"class":1849},[127,5777,2212],{"class":1880},[127,5779,2151],{"class":1863},[127,5781,2182],{"class":1853},[127,5783,5746],{"class":136},[127,5785,2182],{"class":1853},[127,5787,2509],{"class":1880},[127,5789,2151],{"class":1863},[127,5791,2182],{"class":1853},[127,5793,5757],{"class":136},[127,5795,2182],{"class":1853},[127,5797,2265],{"class":1863},[127,5799,5800],{"class":2268},"Profile",[127,5802,2272],{"class":1863},[127,5804,41],{"class":1849},[127,5806,2138],{"class":1863},[127,5808,5809,5811,5813],{"class":129,"line":618},[127,5810,2676],{"class":1863},[127,5812,2610],{"class":1849},[127,5814,2138],{"class":1863},[127,5816,5817,5819,5821],{"class":129,"line":629},[127,5818,2685],{"class":1863},[127,5820,2486],{"class":1849},[127,5822,2138],{"class":1863},[127,5824,5825],{"class":129,"line":640},[127,5826,1870],{"emptyLinePlaceholder":1869},[127,5828,5829,5831,5833,5835,5837,5839,5842,5844],{"class":129,"line":651},[127,5830,2171],{"class":1863},[127,5832,2301],{"class":1849},[127,5834,2509],{"class":1880},[127,5836,2151],{"class":1863},[127,5838,2182],{"class":1853},[127,5840,5841],{"class":136},"flex flex-1 overflow-hidden",[127,5843,2182],{"class":1853},[127,5845,2138],{"class":1863},[127,5847,5848],{"class":129,"line":662},[127,5849,5850],{"class":489},"      \u003C!-- Sidebar -->\n",[127,5852,5853,5855,5858,5860,5862,5864,5867,5869],{"class":129,"line":673},[127,5854,2582],{"class":1863},[127,5856,5857],{"class":1849},"aside",[127,5859,2509],{"class":1880},[127,5861,2151],{"class":1863},[127,5863,2182],{"class":1853},[127,5865,5866],{"class":136},"w-64 overflow-y-auto bg-white border-r border-gray-200",[127,5868,2182],{"class":1853},[127,5870,2138],{"class":1863},[127,5872,5873,5875,5877,5879,5881,5883,5886,5888,5890,5892,5894,5897,5899],{"class":129,"line":684},[127,5874,2617],{"class":1863},[127,5876,2610],{"class":1849},[127,5878,2509],{"class":1880},[127,5880,2151],{"class":1863},[127,5882,2182],{"class":1853},[127,5884,5885],{"class":136},"p-4 space-y-2",[127,5887,2182],{"class":1853},[127,5889,5720],{"class":1880},[127,5891,2151],{"class":1863},[127,5893,2182],{"class":1853},[127,5895,5896],{"class":136},"Sidebar Navigation",[127,5898,2182],{"class":1853},[127,5900,2138],{"class":1863},[127,5902,5903,5906],{"class":129,"line":695},[127,5904,5905],{"class":1863},"          \u003C",[127,5907,5908],{"class":1849},"RouterLink\n",[127,5910,5911,5914,5916,5918,5920],{"class":129,"line":706},[127,5912,5913],{"class":1880},"            to",[127,5915,2151],{"class":1863},[127,5917,2182],{"class":1853},[127,5919,2630],{"class":136},[127,5921,5922],{"class":1853},"\"\n",[127,5924,5925,5928,5930,5932,5935],{"class":129,"line":717},[127,5926,5927],{"class":1880},"            class",[127,5929,2151],{"class":1863},[127,5931,2182],{"class":1853},[127,5933,5934],{"class":136},"block rounded-md px-4 py-2 text-gray-700 hover:bg-gray-100",[127,5936,5922],{"class":1853},[127,5938,5939,5942,5944,5946,5949],{"class":129,"line":728},[127,5940,5941],{"class":1880},"            exact-active-class",[127,5943,2151],{"class":1863},[127,5945,2182],{"class":1853},[127,5947,5948],{"class":136},"text-indigo-700 font-bold",[127,5950,5922],{"class":1853},[127,5952,5953],{"class":129,"line":1117},[127,5954,5955],{"class":1863},"          >\n",[127,5957,5958],{"class":129,"line":1127},[127,5959,5960],{"class":2268},"            Home\n",[127,5962,5963,5966,5968],{"class":129,"line":1138},[127,5964,5965],{"class":1863},"          \u003C\u002F",[127,5967,2620],{"class":1849},[127,5969,2138],{"class":1863},[127,5971,5972,5974],{"class":129,"line":1152},[127,5973,5905],{"class":1863},[127,5975,5908],{"class":1849},[127,5977,5978,5980,5982,5984,5986],{"class":129,"line":1163},[127,5979,5913],{"class":1880},[127,5981,2151],{"class":1863},[127,5983,2182],{"class":1853},[127,5985,2658],{"class":136},[127,5987,5922],{"class":1853},[127,5989,5990,5992,5994,5996,5998],{"class":129,"line":1177},[127,5991,5927],{"class":1880},[127,5993,2151],{"class":1863},[127,5995,2182],{"class":1853},[127,5997,5934],{"class":136},[127,5999,5922],{"class":1853},[127,6001,6002,6004,6006,6008,6010],{"class":129,"line":1188},[127,6003,5941],{"class":1880},[127,6005,2151],{"class":1863},[127,6007,2182],{"class":1853},[127,6009,5948],{"class":136},[127,6011,5922],{"class":1853},[127,6013,6014],{"class":129,"line":1200},[127,6015,5955],{"class":1863},[127,6017,6018],{"class":129,"line":1207},[127,6019,6020],{"class":2268},"            About\n",[127,6022,6023,6025,6027],{"class":129,"line":1217},[127,6024,5965],{"class":1863},[127,6026,2620],{"class":1849},[127,6028,2138],{"class":1863},[127,6030,6031,6034,6036],{"class":129,"line":1229},[127,6032,6033],{"class":1863},"        \u003C\u002F",[127,6035,2610],{"class":1849},[127,6037,2138],{"class":1863},[127,6039,6040,6042,6044],{"class":129,"line":1241},[127,6041,2676],{"class":1863},[127,6043,5857],{"class":1849},[127,6045,2138],{"class":1863},[127,6047,6048],{"class":129,"line":1253},[127,6049,1870],{"emptyLinePlaceholder":1869},[127,6051,6052],{"class":129,"line":1260},[127,6053,6054],{"class":489},"      \u003C!-- Main Content -->\n",[127,6056,6057,6059,6062,6064,6066,6068,6071,6073],{"class":129,"line":1270},[127,6058,2582],{"class":1863},[127,6060,6061],{"class":1849},"main",[127,6063,2509],{"class":1880},[127,6065,2151],{"class":1863},[127,6067,2182],{"class":1853},[127,6069,6070],{"class":136},"flex-1 overflow-y-auto p-6",[127,6072,2182],{"class":1853},[127,6074,2138],{"class":1863},[127,6076,6077,6079,6081],{"class":129,"line":1711},[127,6078,2617],{"class":1863},[127,6080,2708],{"class":1849},[127,6082,2190],{"class":1863},[127,6084,6085,6087,6089],{"class":129,"line":1723},[127,6086,2676],{"class":1863},[127,6088,6061],{"class":1849},[127,6090,2138],{"class":1863},[127,6092,6093,6095,6097],{"class":129,"line":1735},[127,6094,2685],{"class":1863},[127,6096,2301],{"class":1849},[127,6098,2138],{"class":1863},[127,6100,6101],{"class":129,"line":1742},[127,6102,1870],{"emptyLinePlaceholder":1869},[127,6104,6105],{"class":129,"line":1751},[127,6106,6107],{"class":489},"    \u003C!-- Footer -->\n",[127,6109,6110,6112],{"class":129,"line":1766},[127,6111,2171],{"class":1863},[127,6113,6114],{"class":1849},"footer\n",[127,6116,6117,6120,6122,6124,6127],{"class":129,"line":1776},[127,6118,6119],{"class":1880},"      class",[127,6121,2151],{"class":1863},[127,6123,2182],{"class":1853},[127,6125,6126],{"class":136},"flex h-12 items-center justify-center bg-white border-t border-gray-200 text-sm text-gray-500",[127,6128,5922],{"class":1853},[127,6130,6131],{"class":129,"line":1785},[127,6132,6133],{"class":1863},"    >\n",[127,6135,6137,6140,6143,6145],{"class":129,"line":6136},47,[127,6138,6139],{"class":1863},"      &",[127,6141,6142],{"class":3258},"copy",[127,6144,5108],{"class":1863},[127,6146,6147],{"class":2268}," 2025 My Project. All rights reserved.\n",[127,6149,6151,6153,6156],{"class":129,"line":6150},48,[127,6152,2685],{"class":1863},[127,6154,6155],{"class":1849},"footer",[127,6157,2138],{"class":1863},[127,6159,6161,6163,6165],{"class":129,"line":6160},49,[127,6162,2281],{"class":1863},[127,6164,2301],{"class":1849},[127,6166,2138],{"class":1863},[127,6168,6170,6172,6174],{"class":129,"line":6169},50,[127,6171,2272],{"class":1863},[127,6173,2477],{"class":1849},[127,6175,2138],{"class":1863},[11,6177,6178,6179,6181],{},"Con esto hemos creado una estructura básica con un app bar, un sidebar, un área principal de contenido y un footer, todo estilizado con clases de Tailwind CSS.\nIdealmente cada bloque (AppBar, Sidebar, Footer) debería ser un componente separado para promover la reutilización y el mantenimiento, pero para este ejemplo lo dejamos todo en ",[54,6180,842],{}," para simplificar.",[11,6183,6184,6185,6188],{},"Verifica que todo funcione correctamente abriendo ",[54,6186,6187],{},"http:\u002F\u002Flocalhost:5173"," en tu navegador. Deberías ver la estructura básica con estilos aplicados.",[11,6190,6191,6192,6196,6197,101],{},"Con esto ya tienes Tailwind CSS v4 funcionando en tu proyecto. Explora su ",[41,6193,458],{"href":6194,"target":43,"rel":6195},"https:\u002F\u002Ftailwindcss.com",[46,47]," e instala su extensión para un mejor autocompletado en VS Code: ",[41,6198,6201],{"href":6199,"target":43,"rel":6200},"https:\u002F\u002Fmarketplace.visualstudio.com\u002Fitems?itemName=bradlc.vscode-tailwindcss",[46,47],"Tailwind CSS IntelliSense",[18,6203],{},[21,6205,6207],{"id":6206},"extra-subiendo-el-proyecto-a-github","EXTRA: Subiendo el proyecto a GitHub",[11,6209,6210],{},"Para esto tenemos muchas opciones. Antes de comenzar asumo que ya tienes una cuenta en GitHub y que tienes Git instalado en tu máquina.",[191,6212,6213],{},[32,6214,6215],{},"Primero inicializamos un repositorio Git en la carpeta del proyecto:",[118,6217,6219],{"className":120,"code":6218,"language":122,"meta":123,"style":123},"git init\n",[54,6220,6221],{"__ignoreMap":123},[127,6222,6223,6226],{"class":129,"line":130},[127,6224,6225],{"class":133},"git",[127,6227,6228],{"class":136}," init\n",[191,6230,6231],{"start":339},[32,6232,6233,6234,6237],{},"Luego creamos un archivo ",[54,6235,6236],{},".gitignore"," en la raíz del proyecto (es probable que ya lo tengas) y nos aseguraremos de tener las siguientes líneas para ignorar archivos y carpetas innecesarias:",[118,6239,6243],{"className":6240,"code":6242,"language":3849},[6241],"language-text","# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\n.DS_Store\ndist\ndist-ssr\ncoverage\n*.local\n\n# Editor directories and files\n.vscode\u002F*\n!.vscode\u002Fextensions.json\n.idea\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n\n*.tsbuildinfo\n\n.eslintcache\n\n# Cypress\n\u002Fcypress\u002Fvideos\u002F\n\u002Fcypress\u002Fscreenshots\u002F\n\n# Vitest\n__screenshots__\u002F\n\n",[54,6244,6242],{"__ignoreMap":123},[191,6246,6247],{"start":357},[32,6248,6249],{},"Ahora agregamos todos los archivos y hacemos el commit inicial:",[118,6251,6253],{"className":120,"code":6252,"language":122,"meta":123,"style":123},"git add .\n",[54,6254,6255],{"__ignoreMap":123},[127,6256,6257,6259,6262],{"class":129,"line":130},[127,6258,6225],{"class":133},[127,6260,6261],{"class":136}," add",[127,6263,6264],{"class":136}," .\n",[118,6266,6268],{"className":120,"code":6267,"language":122,"meta":123,"style":123},"git commit -m \"Initial commit\"\n",[54,6269,6270],{"__ignoreMap":123},[127,6271,6272,6274,6277,6280,6283,6286],{"class":129,"line":130},[127,6273,6225],{"class":133},[127,6275,6276],{"class":136}," commit",[127,6278,6279],{"class":3258}," -m",[127,6281,6282],{"class":1853}," \"",[127,6284,6285],{"class":136},"Initial commit",[127,6287,5922],{"class":1853},[191,6289,6290,6297],{"start":378},[32,6291,6292,6293,6296],{},"Ahora vamos a GitHub y creamos un nuevo repositorio. Puedes hacer esto haciendo clic en el botón \"+\" en la esquina superior derecha y seleccionando \"New repository\". Ponle un nombre a tu repositorio (por ejemplo, ",[54,6294,6295],{},"my-vue-app","), agrega una descripción si quieres, y déjalo como público o privado según prefieras. No agregues ningún archivo adicional (como README, .gitignore o licencia), ya los tenemos localmente.",[32,6298,6299],{},"Luego, seguimos las instrucciones que GitHub nos da para conectar nuestro repositorio local con el remoto. Normalmente son algo así:",[118,6301,6303],{"className":120,"code":6302,"language":122,"meta":123,"style":123},"git remote add origin https:\u002F\u002Fexample-url.git\n",[54,6304,6305],{"__ignoreMap":123},[127,6306,6307,6309,6312,6314,6317],{"class":129,"line":130},[127,6308,6225],{"class":133},[127,6310,6311],{"class":136}," remote",[127,6313,6261],{"class":136},[127,6315,6316],{"class":136}," origin",[127,6318,6319],{"class":136}," https:\u002F\u002Fexample-url.git\n",[118,6321,6323],{"className":120,"code":6322,"language":122,"meta":123,"style":123},"git branch -M main\n",[54,6324,6325],{"__ignoreMap":123},[127,6326,6327,6329,6332,6335],{"class":129,"line":130},[127,6328,6225],{"class":133},[127,6330,6331],{"class":136}," branch",[127,6333,6334],{"class":3258}," -M",[127,6336,6337],{"class":136}," main\n",[118,6339,6341],{"className":120,"code":6340,"language":122,"meta":123,"style":123},"git push -u origin main\n",[54,6342,6343],{"__ignoreMap":123},[127,6344,6345,6347,6350,6353,6355],{"class":129,"line":130},[127,6346,6225],{"class":133},[127,6348,6349],{"class":136}," push",[127,6351,6352],{"class":3258}," -u",[127,6354,6316],{"class":136},[127,6356,6337],{"class":136},[191,6358,6359],{"start":524},[32,6360,6361],{},"Verificamos status",[118,6363,6365],{"className":120,"code":6364,"language":122,"meta":123,"style":123},"git status\n",[54,6366,6367],{"__ignoreMap":123},[127,6368,6369,6371],{"class":129,"line":130},[127,6370,6225],{"class":133},[127,6372,6373],{"class":136}," status\n",[11,6375,6376,6377,6379,6380,6383],{},"Debe decir que estamos en la rama ",[54,6378,6061],{},", estamos sincronizados con el repositorio remoto ",[54,6381,6382],{},"origin\u002Fmain"," y que no hay nada para hacer commit.",[191,6385,6386],{"start":539},[32,6387,6388],{},"Finalmente, cada vez que hagamos cambios y queramos subirlos a GitHub, hacemos:",[118,6390,6392],{"className":120,"code":6391,"language":122,"meta":123,"style":123},"git add .\ngit commit -m \"Descripción de los cambios\"\ngit push\n",[54,6393,6394,6402,6417],{"__ignoreMap":123},[127,6395,6396,6398,6400],{"class":129,"line":130},[127,6397,6225],{"class":133},[127,6399,6261],{"class":136},[127,6401,6264],{"class":136},[127,6403,6404,6406,6408,6410,6412,6415],{"class":129,"line":339},[127,6405,6225],{"class":133},[127,6407,6276],{"class":136},[127,6409,6279],{"class":3258},[127,6411,6282],{"class":1853},[127,6413,6414],{"class":136},"Descripción de los cambios",[127,6416,5922],{"class":1853},[127,6418,6419,6421],{"class":129,"line":357},[127,6420,6225],{"class":133},[127,6422,6423],{"class":136}," push\n",[11,6425,6426],{},"¡Y eso es todo! Ahora tienes tu proyecto Vue 3 con Vite subido a GitHub.",[11,6428,6429],{},"Lo normal es que siempre uses un controlador de versiones como Git para manejar tu código, incluso en proyectos personales. Te ayudará a mantener un historial de cambios, colaborar con otros y proteger tu trabajo.",[11,6431,6432,6433,6438],{},"Te recomiendo explorar también sobre ",[41,6434,6437],{"href":6435,"target":43,"rel":6436},"https:\u002F\u002Fwww.conventionalcommits.org\u002Fen\u002Fv1.0.0\u002F",[46,47],"Conventional Commits"," para mantener mensajes de commit consistentes y significativos. Es algo que usan muchas empresas, equipos y proyectos open source.",[11,6440,6441],{},"Algunos recursos para aprender más sobre Git y GitHub:",[29,6443,6444,6451,6458],{},[32,6445,6446],{},[41,6447,6450],{"href":6448,"target":43,"rel":6449},"https:\u002F\u002Fgithub.com\u002Fdjayepro3\u002FGuide-Git-GitHub-VSCode",[46,47],"Git & GitHub with VS Code: A Beginner's Guide",[32,6452,6453],{},[41,6454,6457],{"href":6455,"target":43,"rel":6456},"https:\u002F\u002Fdocs.github.com\u002Fen\u002Fget-started\u002Fstart-your-journey",[46,47],"GitHub Quickstart Guide",[32,6459,6460],{},[41,6461,6464],{"href":6462,"target":43,"rel":6463},"https:\u002F\u002Fgit-scm.com\u002Fdoc",[46,47],"Git Documentation",[11,6466,6467],{},"Extensiones para VS Code:",[29,6469,6470,6477],{},[32,6471,6472],{},[41,6473,6476],{"href":6474,"target":43,"rel":6475},"https:\u002F\u002Fmarketplace.visualstudio.com\u002Fitems?itemName=eamodio.gitlens",[46,47],"Gitlens",[32,6478,6479],{},[41,6480,6483],{"href":6481,"target":43,"rel":6482},"https:\u002F\u002Fmarketplace.visualstudio.com\u002Fitems?itemName=mhutchie.git-graph",[46,47],"Git Graph",[18,6485],{},[21,6487,6489],{"id":6488},"extra-otras-extensiones-útiles-para-vs-code","EXTRA: Otras extensiones útiles para VS Code",[11,6491,6492],{},"Algunas extensiones que siempre recomiendo para VS Code (sin importar el tipo de proyecto):",[29,6494,6495,6503,6511,6519],{},[32,6496,6497,6502],{},[41,6498,6501],{"href":6499,"target":43,"rel":6500},"https:\u002F\u002Fmarketplace.visualstudio.com\u002Fitems?itemName=usernamehw.errorlens",[46,47],"Error Lens",": Resalta errores y advertencias directamente en el código, facilitando su identificación y corrección.",[32,6504,6505,6510],{},[41,6506,6509],{"href":6507,"target":43,"rel":6508},"https:\u002F\u002Fmarketplace.visualstudio.com\u002Fitems?itemName=naumovs.color-highlight",[46,47],"Color Highlight",": Resalta los colores definidos en tu código CSS, facilitando la visualización de los mismos.",[32,6512,6513,6518],{},[41,6514,6517],{"href":6515,"target":43,"rel":6516},"https:\u002F\u002Fmarketplace.visualstudio.com\u002Fitems?itemName=aaron-bond.better-comments",[46,47],"Better Comments",": Mejora la legibilidad de los comentarios en el código mediante colores y estilos.",[32,6520,6521,6526,6527,6532],{},[41,6522,6525],{"href":6523,"target":43,"rel":6524},"https:\u002F\u002Fmarketplace.visualstudio.com\u002Fitems?itemName=antfu.iconify",[46,47],"Iconify Intellisense",": Si quieres trabajar con iconos, esta extensión te permite buscar e insertar iconos de múltiples bibliotecas directamente en tu código. A parte de ello recomiendo explorar su librería ",[41,6528,6531],{"href":6529,"target":43,"rel":6530},"https:\u002F\u002Ficon-sets.iconify.design\u002F",[46,47],"Iconify"," dónde puedes encontrar una gran variedad de icon sets gratuitos.",[18,6534],{},[11,6536,6537],{},"Bueno, eso sería todo para esta guía introductoria sobre Vue 3 con Vite. Espero que te haya sido útil para comenzar tu viaje con este framework y su ecosistema.",[18,6539],{},[2729,6541,6542],{},"html pre.shiki code .s_xSY, html code.shiki .s_xSY{--shiki-default:#59873A;--shiki-dark:#80A665}html pre.shiki code .spP0B, html code.shiki .spP0B{--shiki-default:#B56959;--shiki-dark:#C98A7D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sHLBJ, html code.shiki .sHLBJ{--shiki-default:#998418;--shiki-dark:#B8A965}html pre.shiki code .snYqZ, html code.shiki .snYqZ{--shiki-default:#A0ADA0;--shiki-dark:#758575DD}html pre.shiki code .sTPum, html code.shiki .sTPum{--shiki-default:#1E754F;--shiki-dark:#4D9375}html pre.shiki code .scnC2, html code.shiki .scnC2{--shiki-default:#B5695977;--shiki-dark:#C98A7D77}html pre.shiki code .si6no, html code.shiki .si6no{--shiki-default:#999999;--shiki-dark:#666666}html pre.shiki code .s9nN2, html code.shiki .s9nN2{--shiki-default:#B07D48;--shiki-dark:#BD976A}html pre.shiki code .s5TCs, html code.shiki .s5TCs{--shiki-default:#AB5959;--shiki-dark:#CB7676}html pre.shiki code .s8w-G, html code.shiki .s8w-G{--shiki-default:#393A34;--shiki-dark:#DBD7CAEE}html pre.shiki code .sfsYZ, html code.shiki .sfsYZ{--shiki-default:#A65E2B;--shiki-dark:#C99076}html pre.shiki code .sqbOQ, html code.shiki .sqbOQ{--shiki-default:#2F798A;--shiki-dark:#4C9A91}",{"title":123,"searchDepth":357,"depth":357,"links":6544},[6545,6546,6547,6548,6552,6553,6554,6559,6560,6561,6562],{"id":23,"depth":339,"text":24},{"id":91,"depth":339,"text":92},{"id":112,"depth":339,"text":113},{"id":464,"depth":339,"text":465,"children":6549},[6550,6551],{"id":770,"depth":357,"text":771},{"id":852,"depth":357,"text":853},{"id":1826,"depth":339,"text":1827},{"id":3115,"depth":339,"text":3116},{"id":3749,"depth":339,"text":3750,"children":6555},[6556,6557,6558],{"id":4632,"depth":357,"text":4633},{"id":4665,"depth":357,"text":4666},{"id":4746,"depth":357,"text":4747},{"id":4803,"depth":339,"text":4804},{"id":4950,"depth":339,"text":4951},{"id":6206,"depth":339,"text":6207},{"id":6488,"depth":339,"text":6489},"2025-12-04","md","\u002Fblog\u002Fgetting-started-vue-vite\u002Fshared\u002Fvite+vue.webp","2025-12-22",{},"\u002Fblog\u002Fblog\u002Fgetting-started-vue-vite",{"title":5,"description":13},{"loc":6571,"priority":6572,"lastmod":6566},"\u002Fes\u002Fblog\u002Fgetting-started-vue-vite",0.7,"getting-started-vue-vite","blog\u002Fblog\u002Fgetting-started-vue-vite","Una guía completa para configurar tu primer proyecto Vue 3 con Vite, incluyendo mejores prácticas y herramientas modernas.",[6577,6578,6579],"Vue.js","Vite","Tailwind CSS","Bf_UMGO80INaHK2ReFgXeiuNNUWLLa8TjxgIErcTvgI",{"prev":6582,"next":6583},null,{"id":6584,"title":6585,"author":6,"body":6586,"date":7239,"description":6590,"extension":6564,"image":7240,"lastmod":7239,"meta":7241,"navigation":1869,"order":339,"path":7242,"seo":7243,"sitemap":7244,"slug":7246,"stem":7247,"summary":7248,"tags":7249,"__hash__":7255},"content_es\u002Fblog\u002Fblog\u002Fmachine-learning-fundamentals.md","Fundamentos de Aprendizaje Automático",{"type":8,"value":6587,"toc":7230},[6588,6591,6593,6595,6599,6615,6618,6642,6645,6660,6662,6666,6669,6737,6739,6743,6746,6867,6869,6974,6976,7025,7045,7047,7051,7054,7110,7114,7117,7126,7129,7140,7153,7155,7159,7185,7196,7198,7202,7205,7225,7227],[11,6589,6590],{},"Esta es la primera parte de una serie de artículos donde exploraremos el aprendizaje automático, desde sus conceptos básicos hasta redes neuronales y la creación de un modelo de machine learning. En esta primera parte, nos centraremos en los fundamentos del aprendizaje automático, incluyendo qué es, sus tipos y algunos algoritmos comunes.",[15,6592],{},[18,6594],{},[21,6596,6598],{"id":6597},"inteligencia-artificial-y-machine-learning","Inteligencia Artificial y Machine Learning",[11,6600,6601,6602,245,6605,864,6608,6611,6612,101],{},"Te despiertas un día, abres Netflix y te encuentras recomendada exactamente la serie que querías ver. Luego, abres Google escribes algo y el buscador completa tu frase antes de que termines de teclear. ¿Cómo hacen esto? La respuesta es: Inteligencia Artificial. La IA, es una disciplina enfocada en desarrollar sistemas capaces de realizar tareas que normalmente requieren inteligencia humana, como ",[36,6603,6604],{},"aprender",[36,6606,6607],{},"razonar",[36,6609,6610],{},"percibir"," nuestro entorno, asi como ",[36,6613,6614],{},"tomar decisiones",[11,6616,6617],{},"Existen tres tipos de IA:",[29,6619,6620,6626,6632],{},[32,6621,6622,6625],{},[36,6623,6624],{},"IA débil o estrecha (Artificial Narrow Intelligence o ANI)",": Es la IA que tenemos hoy en día. Está diseñada para realizar tareas específicas, como reconocimiento de voz, recomendaciones de productos o traducción automática. No tiene conciencia ni comprensión real, simplemente sigue algoritmos y patrones predefinidos. Los LLM como GPT, Claude o Gemini, son ejemplos de IA débil, ya que están diseñados para procesar y generar texto, \"solamente\" son modelos estadisticos que predicen texto, y  no tienen una comprensión profunda del mundo ni pueden realizar tareas fuera de su ámbito específico. Aunque parecen inteligentes, en realidad solo están imitando patrones de lenguaje basados en los datos con los que fueron entrenados.",[32,6627,6628,6631],{},[36,6629,6630],{},"IA general (Artifical General Intelligence o AGI)",": Es una IA hipotética que tendría la capacidad de entender, aprender y aplicar conocimientos en una amplia variedad de tareas, similar a la inteligencia humana. Aún no existe, pero es un objetivo a largo plazo en el campo de la IA.",[32,6633,6634,6637,6638,6641],{},[36,6635,6636],{},"IA superinteligente (Artificial Superintelligence o ASI)",": Es una IA que superaría la inteligencia humana en todos los aspectos, incluyendo creatividad, resolución de problemas y toma de decisiones. Es un concepto ",[36,6639,6640],{},"teórico"," que plantea muchas preguntas éticas y filosóficas sobre el futuro de la humanidad.",[11,6643,6644],{},"¿Dónde entra el Machine Learning? Es muy común confundir la IA con el Machine Learning, pero no son exactamente lo mismo. Podemos decir que la Inteligencia Artificial es un gran paraguas conceptual, y debajo de ese paraguas se encuentra el Machine Learning, un subcampo específico que permite a las computadoras aprender automáticamente a partir de datos, sin necesidad de que un humano las programe paso a paso.",[413,6646,6647,6650],{},[11,6648,6649],{},"Recursos recomendados:",[29,6651,6652],{},[32,6653,6654],{},[41,6655,6659],{"href":6656,"rel":6657},"https:\u002F\u002Fyoutu.be\u002FdKqwnCKrpVI?si=g6qqFa_1G_M5P3LS",[6658],"nofollow","Inteligencia Artificial vs Machine Learning vs Deep Learning | Machine Learning 101",[18,6661],{},[21,6663,6665],{"id":6664},"subcampos-de-la-ia","Subcampos de la IA",[11,6667,6668],{},"Dentro del gran paraguas de la IA, hay varios subcampos que se especializan en diferentes aspectos de la inteligencia artificial:",[29,6670,6671,6677,6683,6689,6695,6701,6707,6713,6719,6725,6731],{},[32,6672,6673,6676],{},[36,6674,6675],{},"Aprendizaje Automático (Machine Learning)",": Se centra en desarrollar algoritmos que permiten a las máquinas aprender de los datos y mejorar su rendimiento con el tiempo sin ser explícitamente programadas para cada tarea específica.",[32,6678,6679,6682],{},[36,6680,6681],{},"Aprendizaje Profundo (Deep Learning)",": Es una rama del aprendizaje automático que utiliza redes neuronales profundas para modelar y resolver problemas complejos. Es especialmente efectivo en tareas como reconocimiento de voz, visión por computadora y procesamiento del lenguaje natural.",[32,6684,6685,6688],{},[36,6686,6687],{},"Procesamiento del Lenguaje Natural (Natural Language Processing o NLP)",": Se enfoca en la interacción entre las computadoras y el lenguaje humano, permitiendo a las máquinas entender, interpretar y generar texto de manera natural. Es lo que hace posible que los chatbots como ChatGPT puedan mantener conversaciones coherentes con los usuarios.",[32,6690,6691,6694],{},[36,6692,6693],{},"Visión por Computadora (Computer Vision)",": Se ocupa de permitir que las máquinas comprendan y procesen imágenes y videos. Esto es fundamental para aplicaciones como el reconocimiento facial, la conducción autónoma y la detección de objetos.",[32,6696,6697,6700],{},[36,6698,6699],{},"Robótica",": Se dedica al diseño y construcción de robots que pueden realizar tareas físicas en el mundo real, desde la fabricación hasta la asistencia médica.",[32,6702,6703,6706],{},[36,6704,6705],{},"Sistemas Expertos",": Son programas que imitan la toma de decisiones de un experto humano en un dominio específico, utilizando reglas y lógica para resolver problemas complejos.",[32,6708,6709,6712],{},[36,6710,6711],{},"Razonamiento Automático",": Se enfoca en inferir conclusiones lógicas a partir de reglas formales, no es lo mismo que el aprendizaje automático, este campo incluye lógica simbólica, resolución de problemas y planificación automática.",[32,6714,6715,6718],{},[36,6716,6717],{},"Agentes Inteligentes",": Son sistemas que pueden percibir su entorno, razonar sobre él y tomar decisiones para alcanzar objetivos específicos. Pueden ser tan simples como un chatbot o tan complejos como un sistema de conducción autónoma (puede usar ML, reglas simples, razonamiento lógico, etc).",[32,6720,6721,6724],{},[36,6722,6723],{},"IA Distribuida",": Se refiere a sistemas de IA que operan en múltiples dispositivos o nodos, colaborando para resolver problemas de manera más eficiente. Esto es especialmente relevante en aplicaciones como el Internet de las Cosas (IoT) y la computación en la nube.",[32,6726,6727,6730],{},[36,6728,6729],{},"IA Explicable (XAI)",": Se centra en desarrollar modelos de IA que sean transparentes y comprensibles para los humanos, permitiendo a los usuarios entender cómo y por qué la IA toma ciertas decisiones.",[32,6732,6733,6736],{},[36,6734,6735],{},"Ética y Gobernanza de la IA",": Se ocupa de las implicaciones éticas, legales y sociales del desarrollo y uso de la IA, abordando temas como la privacidad, la equidad, la transparencia.",[18,6738],{},[21,6740,6742],{"id":6741},"como-aprende-una-máquina","Como aprende una máquina",[11,6744,6745],{},"Todo depende de los datos que le demos:",[29,6747,6748],{},[32,6749,6750,6753,6754,6757,6758,6761,6762,6765,6766,6820,6822,6823,6825,6826,6840,6842,6843,6849,6850,6852,6853],{},[36,6751,6752],{},"Aprendizaje Supervisado",": Aquí le damos a la máquina ejemplos claros con las respuestas correctas ya \"etiquetadas\". Por ejemplo, si queremos que la IA ayude en un diagnóstico médico, le damos miles de historiales médicos donde ya sabemos qué paciente estaba ",[36,6755,6756],{},"enfermo"," y qué paciente estaba ",[36,6759,6760],{},"sano",".\nLa máquina aprende a reconocer patrones en esos datos para poder predecir el diagnóstico de nuevos pacientes basándose en lo que ha aprendido.",[6763,6764],"br",{},"Un ejemplo sencillo sería algo así:",[6767,6768,6769,6788],"table",{},[6770,6771,6772],"thead",{},[6773,6774,6775,6779,6782,6785],"tr",{},[6776,6777,6778],"th",{},"Edad",[6776,6780,6781],{},"Síntomas",[6776,6783,6784],{},"Resultado de Pruebas",[6776,6786,6787],{},"Diagnóstico",[6789,6790,6791,6806],"tbody",{},[6773,6792,6793,6797,6800,6803],{},[6794,6795,6796],"td",{},"45",[6794,6798,6799],{},"Fiebre, Tos",[6794,6801,6802],{},"Positivo",[6794,6804,6805],{},"Enfermo",[6773,6807,6808,6811,6814,6817],{},[6794,6809,6810],{},"30",[6794,6812,6813],{},"Dolor de cabeza",[6794,6815,6816],{},"Negativo",[6794,6818,6819],{},"Sano",[6763,6821],{},"La etiqueta aquí es el \"Diagnóstico\", y la máquina aprende a asociar las características (Edad, Síntomas, Resultado de Pruebas) con esa etiqueta para hacer predicciones futuras.",[6763,6824],{},"Dentro del aprendizaje supervisado, hay dos tipos principales de tareas:",[29,6827,6828,6834],{},[32,6829,6830,6833],{},[36,6831,6832],{},"Clasificación",": Donde la máquina asigna una etiqueta a cada ejemplo. Como clasificar correos electrónicos como \"spam\" o \"no spam\".",[32,6835,6836,6839],{},[36,6837,6838],{},"Regresión",": Donde la máquina predice un valor continuo. Por ejemplo, predecir el precio de una casa basándose en características como el tamaño, la ubicación y el número de habitaciones.",[6763,6841],{},"Basicamente si la respuesta que queremos predecir es una categoría (o una ",[41,6844,6848],{"href":6845,"target":43,"rel":6846,"ariaLabel":6847},"https:\u002F\u002Fwww.probabilidadyestadistica.net\u002Fvariable-discreta",[46,47],"LinkedIn","variable discreta","), es clasificación, si la respuesta representa una cantidad medible en una escala continua, es regresión.\nY el requisito para que el aprendizaje supervisado funcione bien es tener un conjunto de datos grande y representativo, con etiquetas precisas. Si los datos son escasos o las etiquetas son incorrectas, la máquina no podrá aprender correctamente y sus predicciones serán inexactas.",[6763,6851],{},"Ejemplos de aplicaciones de ML son:",[29,6854,6855,6858,6861,6864],{},[32,6856,6857],{},"Detección de fraudes en transacciones financieras (clasificación)",[32,6859,6860],{},"Predicción de precios de acciones (regresión)",[32,6862,6863],{},"Reconocimiento de imágenes (clasificación)",[32,6865,6866],{},"Análisis de sentimientos en redes sociales (clasificación)",[18,6868],{},[29,6870,6871],{},[32,6872,6873,6876,6877,6879,6880,6919,6921,6922,6971,6973],{},[36,6874,6875],{},"Aprendizaje No Supervisado",": Imagina que te sueltan en un país desconocido y tienes que deducir cómo funciona la sociedad solo observando, es algo similar. Aquí, la máquina recibe datos sin etiquetas y debe encontrar patrones ocultos por sí sola. El sistema tendrá que analizar similitudes, diferencias y comportamientos para encontrar agrupaciones o patrones inusuales. No hay un \"profesor\" que le diga si está bien o mal.",[6763,6878],{},"Técnicas principales:",[191,6881,6882,6899,6913],{},[32,6883,6884,6887,6888],{},[36,6885,6886],{},"Clustering (Agrupamiento)",": Agrupa datos similares entre si.\nSe usa típicamente para segmentación de clientes, agrupar documentos por tema y organización automática de imágenes, etc. Algunos algoritmos:\n",[29,6889,6890,6893,6896],{},[32,6891,6892],{},"K-means clustering",[32,6894,6895],{},"DBSCAN",[32,6897,6898],{},"Hierarchical clustering",[32,6900,6901,6904,6905],{},[36,6902,6903],{},"Reducción de dimensionalidad",": Este busca reducir la cantidad de variables manteniendo la información importante. Usado para visualizar datos complejos y preparar datos para otros modelos.\n",[29,6906,6907,6910],{},[32,6908,6909],{},"Principal Component Analysis (PCA)",[32,6911,6912],{},"t-SNE",[32,6914,6915,6918],{},[36,6916,6917],{},"Detección de anomalías",": Identifica datos que se comportan diferente del resto. Útil para detectar fraudes, fallos en sistemas y comportamientos sospechosos.",[6763,6920],{},"Un ejemplo sencillo sería:",[6767,6923,6924,6936],{},[6770,6925,6926],{},[6773,6927,6928,6930,6933],{},[6776,6929,6778],{},[6776,6931,6932],{},"Ingresos Anuales",[6776,6934,6935],{},"Gastos Mensuales",[6789,6937,6938,6949,6960],{},[6773,6939,6940,6943,6946],{},[6794,6941,6942],{},"25",[6794,6944,6945],{},"$30,000",[6794,6947,6948],{},"$1,000",[6773,6950,6951,6954,6957],{},[6794,6952,6953],{},"40",[6794,6955,6956],{},"$80,000",[6794,6958,6959],{},"$3,000",[6773,6961,6962,6965,6968],{},[6794,6963,6964],{},"60",[6794,6966,6967],{},"$50,000",[6794,6969,6970],{},"$2,000",[6763,6972],{},"La máquina podría agrupar a los clientes en segmentos basados en sus ingresos y gastos, sin que le digamos explícitamente qué grupos existen.\nCon esto podemos identificar patrones de consumo, como por ejemplo, que los clientes jóvenes tienden a gastar menos que los clientes de mediana edad, o que hay un grupo de clientes con ingresos altos pero gastos bajos, lo que podría indicar un segmento de ahorro.",[18,6975],{},[29,6977,6978],{},[32,6979,6980,6983,6984,101,6989,6991,6992,7018,7020,7021],{},[36,6981,6982],{},"Aprendizaje por Refuerzo",": Piensa en cómo entrenas a una mascota con premios. La máquina (el agente) toma decisiones en un entorno y recibe \"recompensas\" o \"penalizaciones\". Así es como los sistemas de conducción autónoma de Tesla o los robots aprenden a navegar por el mundo físico. Un ejemplo que me gusta es el de un video donde ",[41,6985,6988],{"href":6986,"target":43,"rel":6987},"https:\u002F\u002Fyoutu.be\u002FPKDMGPf-PEA?si=tAEMO3cETdPrvi_t",[46,47],"entrenan a un agente para jugar Geometry Dash",[6763,6990],{},"En este tipo de aprendizaje se tienen cuatro componentes principales:",[191,6993,6994,7000,7006,7012],{},[32,6995,6996,6999],{},[36,6997,6998],{},"Agente",": Es el sistema que toma decisiones y aprende a través de la interacción con el entorno. Puede ser un robot, un programa de computadora o cualquier sistema que pueda percibir su entorno y actuar sobre él.",[32,7001,7002,7005],{},[36,7003,7004],{},"Entorno",": Es el mundo en el que el agente opera. Puede ser un entorno físico, como un robot en una habitación, o un entorno virtual, como un videojuego.",[32,7007,7008,7011],{},[36,7009,7010],{},"Recompensa",": Es la señal que el agente recibe después de tomar una acción. Puede ser positiva (recompensa) o negativa (penalización) y sirve para guiar el aprendizaje del agente.",[32,7013,7014,7017],{},[36,7015,7016],{},"Política",": Es la estrategia que el agente utiliza para decidir qué acción tomar en función de su estado actual y de las recompensas que ha recibido en el pasado.",[6763,7019],{},"Básicamente siguen un flujo como el siguiente:",[7022,7023],"mermaid-diagram",{"content":7024},"graph TD\n A[Agente] -->|Toma acción| B(Entorno)\n B -->|Proporciona recompensa| C[Recompensa]\n C -->|Actualiza política| A",[413,7026,7027,7029],{},[11,7028,6649],{},[29,7030,7031,7038],{},[32,7032,7033],{},[41,7034,7037],{"href":7035,"rel":7036},"https:\u002F\u002Fyoutu.be\u002FoT3arRRB2Cw?si=ykU9KQjQLxdn9ggj",[6658],"¿Qué es el Aprendizaje Supervisado y No Supervisado? | DotCSV",[32,7039,7040],{},[41,7041,7044],{"href":7042,"rel":7043},"https:\u002F\u002Fyoutu.be\u002FqBtB-xcJp4c?si=c2GuJBCFPorKGN44",[6658],"El APRENDIZAJE POR REFUERZO: la guía DEFINITIVA",[18,7046],{},[21,7048,7050],{"id":7049},"pipeline-de-un-proyecto-de-ia","Pipeline de un proyecto de IA",[11,7052,7053],{},"Un proyecto de IA generalmente sigue un proceso estructurado que incluye varias etapas clave:",[191,7055,7056,7062,7068,7074,7080,7086,7092,7098,7104],{},[32,7057,7058,7061],{},[36,7059,7060],{},"Definición del problema",": Es fundamental entender claramente el problema que se quiere resolver y los objetivos del proyecto. Esto incluye identificar las preguntas que se quieren responder, los resultados esperados y las métricas de éxito.",[32,7063,7064,7067],{},[36,7065,7066],{},"Recolección de datos",": Se recopilan los datos necesarios para entrenar el modelo de IA. Esto puede incluir datos estructurados (como bases de datos) o no estructurados (como texto, imágenes o videos). Es importante asegurarse de que los datos sean de alta calidad y representativos del problema que se quiere resolver.",[32,7069,7070,7073],{},[36,7071,7072],{},"Preprocesamiento de datos",": Los datos recopilados a menudo necesitan ser limpiados y transformados antes de ser utilizados para entrenar el modelo. Esto puede incluir la eliminación de valores faltantes, la normalización de datos, la codificación de variables categóricas y la división de los datos en conjuntos de entrenamiento y prueba.",[32,7075,7076,7079],{},[36,7077,7078],{},"Selección del modelo",": Se elige el algoritmo de aprendizaje automático más adecuado para el problema en cuestión. Esto puede depender de la naturaleza de los datos, la complejidad del problema y los recursos disponibles.",[32,7081,7082,7085],{},[36,7083,7084],{},"Entrenamiento del modelo",": Se utiliza el conjunto de datos de entrenamiento para entrenar el modelo de IA. Durante esta etapa, el modelo aprende a partir de los datos y ajusta sus parámetros para minimizar el error en las predicciones.",[32,7087,7088,7091],{},[36,7089,7090],{},"Evaluación del modelo",": Se evalúa el rendimiento del modelo utilizando el conjunto de prueba. Se utilizan métricas específicas para medir la precisión, la exactitud, la sensibilidad y otras características del modelo, dependiendo del tipo de problema (clasificación, regresión, etc.).",[32,7093,7094,7097],{},[36,7095,7096],{},"Ajuste de hiperparámetros",": Si el rendimiento del modelo no es satisfactorio, se pueden ajustar los hiperparámetros del modelo para mejorar su rendimiento. Esto puede incluir cambiar la arquitectura del modelo, ajustar la tasa de aprendizaje o modificar otros parámetros específicos del algoritmo.",[32,7099,7100,7103],{},[36,7101,7102],{},"Implementación",": Una vez que el modelo ha sido entrenado y evaluado, se implementa en un entorno de producción donde puede ser utilizado para hacer predicciones en tiempo real o procesar nuevos datos.",[32,7105,7106,7109],{},[36,7107,7108],{},"Mantenimiento y actualización",": Después de la implementación, es importante monitorear el rendimiento del modelo y actualizarlo regularmente para asegurarse de que siga siendo efectivo a medida que cambian los datos y las condiciones del entorno.",[21,7111,7113],{"id":7112},"memorizar-vs-aprender","Memorizar vs Aprender",[11,7115,7116],{},"Cuando hablamos de aprendizaje, ya sea humano o de máquinas, existe un concepto crucial que debemos entender: memorizar no es lo mismo que aprender.",[11,7118,7119,7122,7123,7125],{},[36,7120,7121],{},"Memorizar"," es como copiar y pegar información sin realmente entenderla. Por ejemplo, si memorizas la fórmula del área de un círculo (A = πr²) sin comprender qué significa cada parte, no podrás aplicarla correctamente en diferentes contextos. La memoria te salva en lo inmediato, pero no te da la capacidad de adaptarte a nuevas situaciones o resolver problemas que no has visto antes, en cambio, ",[36,7124,6604],{}," implica comprender los conceptos que están detrás y ser capaz de aplicarlos en situaciones nuevas.",[11,7127,7128],{},"En el mundo del aprendizaje automático, una máquina que solo memoriza los datos de entrenamiento puede tener un rendimiento excelente en esos datos específicos, pero luego fallar estrepitosamente cuando se utiliza en entornos reales. Por eso, en machine learning, el verdadero objetivo no es memorizar patrones específicos, sino generalizar: aprender reglas y relaciones que funcionen más allá de los ejemplos vistos.",[11,7130,7131,7132,7135,7136,7139],{},"Pero aprender tampoco es sencillo, a veces, las máquinas sufren de ",[36,7133,7134],{},"Overfitting"," (sobreajuste), que ocurre cuando un modelo \"memoriza\" los datos de entrenamiento a la perfección, pero fracasa rotundamente cuando se enfrenta a datos nuevos en el mundo real. Es exactamente igual que un estudiante que memoriza las respuestas de un examen sin entender realmente los conceptos. Por el contrario, si el modelo es demasiado simple y no aprende nada, sufre de ",[36,7137,7138],{},"Underfitting"," (subajuste), como un estudiante que no estudió lo suficiente.",[413,7141,7142,7144],{},[11,7143,6649],{},[29,7145,7146],{},[32,7147,7148],{},[41,7149,7152],{"href":7150,"rel":7151},"https:\u002F\u002Fyoutu.be\u002Fo3DztvnfAJg?si=lorMlPZqLAMa-EV3",[6658],"Subajuste y sobreajuste: explicados",[18,7154],{},[21,7156,7158],{"id":7157},"los-componentes-de-un-sistema-de-ia","Los componentes de un sistema de IA",[29,7160,7161,7173,7179],{},[32,7162,7163,7166,7167,7172],{},[36,7164,7165],{},"Datos",": Son la base de cualquier sistema de IA. Sin datos, no hay aprendizaje. Deben ser de alta calidad, relevantes y representativos del problema que se quiere resolver. Con un alto volumen y con el menor ",[41,7168,7171],{"href":7169,"target":43,"rel":7170},"https:\u002F\u002Fwww.innovatiana.com\u002Fes\u002Fpost\u002Fbias-estimation-in-machine-learning",[46,47],"sesgo"," posible.",[32,7174,7175,7178],{},[36,7176,7177],{},"Algoritmos",": Son las recetas que la máquina sigue para aprender de los datos. Hay muchos tipos de algoritmos, cada uno con sus propias fortalezas y debilidades, y deben ser seleccionados cuidadosamente según el problema específico que se quiere resolver, configurados y ajustados para obtener el mejor rendimiento posible.",[32,7180,7181,7184],{},[36,7182,7183],{},"Infraestructura",": Es el hardware y software necesario para procesar los datos y ejecutar los algoritmos. Esto incluye desde servidores (CPU, GPU, TPU) hasta plataformas de computación en la nube y herramientas de desarrollo (AWS, Azure, GCP), asi como almacenamiento de datos y sistemas de gestión de bases de datos.",[11,7186,7187,7188,7191,7192,7195],{},"A parte de estos componentes, tenemos la ",[36,7189,7190],{},"evaluación",", que es el proceso de medir el rendimiento del modelo de IA para asegurarse de que está funcionando correctamente y cumpliendo con los objetivos establecidos, asi como el rol de la ",[36,7193,7194],{},"ética y gobernanza",", que es fundamental para considerar las implicaciones éticas y sociales.",[18,7197],{},[21,7199,7201],{"id":7200},"la-ética-en-la-ia","La ética en la IA",[11,7203,7204],{},"A medida que la inteligencia artificial se vuelve más omnipresente en nuestras vidas, es crucial considerar las implicaciones éticas de su uso. Los modelos de machine learning pueden perpetuar sesgos existentes en los datos, lo que puede llevar a decisiones injustas o discriminatorias. Por ejemplo, si un modelo de contratación se entrena con datos históricos que reflejan prejuicios de género o raza, es probable que el modelo reproduzca esos sesgos en sus recomendaciones. Además, la privacidad de los datos es una preocupación importante. Es fundamental asegurarse de que los datos utilizados se recopilen y manejen de manera ética, respetando la privacidad y los derechos de las personas.",[29,7206,7207,7213,7219],{},[32,7208,7209,7212],{},[36,7210,7211],{},"Transparencia",": Los sistemas deben ser comprensibles y auditables para que los usuarios puedan entender cómo funcionan y por qué toman ciertas decisiones, una solución a esto es la IA explicable (XAI).",[32,7214,7215,7218],{},[36,7216,7217],{},"Explicabilidad",": Los modelos de IA deben ser capaces de explicar sus decisiones de manera clara y comprensible para los usuarios, lo que ayuda a generar confianza y permite a los usuarios entender las razones detrás de las recomendaciones o acciones del sistema.",[32,7220,7221,7224],{},[36,7222,7223],{},"Responsabilidad",": Se debe establecer claramente quién es responsable de las decisiones tomadas por los sistemas de IA, especialmente en casos donde las decisiones pueden tener un impacto significativo en la vida de las personas. Aqui entran en juego los marcos legales y regulaciones que deben ser desarrollados para garantizar que las empresas y desarrolladores de IA sean responsables de sus creaciones.",[18,7226],{},[11,7228,7229],{},"Hasta aquí la primera parte de esta serie de artículos sobre aprendizaje automático. En la próxima parte, exploraremos algunos paradigmas de machine learning y ciertos fundamentos matemáticos que son esenciales para entender cómo funcionan los algoritmos.",{"title":123,"searchDepth":357,"depth":357,"links":7231},[7232,7233,7234,7235,7236,7237,7238],{"id":6597,"depth":339,"text":6598},{"id":6664,"depth":339,"text":6665},{"id":6741,"depth":339,"text":6742},{"id":7049,"depth":339,"text":7050},{"id":7112,"depth":339,"text":7113},{"id":7157,"depth":339,"text":7158},{"id":7200,"depth":339,"text":7201},"2026-03-30","\u002Fblog\u002Fmachine-learning-fundamentals\u002Fshared\u002Fml-fundamentals.webp",{},"\u002Fblog\u002Fblog\u002Fmachine-learning-fundamentals",{"title":6585,"description":6590},{"loc":7245,"priority":6572,"lastmod":7239},"\u002Fes\u002Fblog\u002Fmachine-learning-fundamentals","machine-learning-fundamentals","blog\u002Fblog\u002Fmachine-learning-fundamentals","Conceptos básicos para iniciar en el mundo del aprendizaje automático",[7250,7251,7252,7253,7254],"Aprendizaje Automático","Inteligencia Artificial","Python","Data Science","Machine Learning","2v7h55fkUsJvxoYBntWpvJgjaGB1GovQylDStwlp07E",1776805792950]