diff --git a/src/guide/composition-api-introduction.md b/src/guide/composition-api-introduction.md index ffae321d2f..0f250908ae 100644 --- a/src/guide/composition-api-introduction.md +++ b/src/guide/composition-api-introduction.md @@ -1,16 +1,16 @@ -# Introduction +# Introducción -## Why Composition API? +## Por qué la API de Composición? -::: tip Note -Reaching this far in the documentation, you should already be familiar with both [the basics of Vue](introduction.md) and [creating components](component-basics.md). +::: tip Nota +Al haber llegado tan lejos en la documentación, usted ya debería estar familiarizado tanto con [los conceptos básicos de Vue](introduction.md) y con [crear componentes](component-basics.md). ::: -Watch a free video about the Composition API on Vue Mastery +Vea un video gratuito sobre la API de Composición en Vue Mastery -Creating Vue components allows us to extract repeatable parts of the interface coupled with its functionality into reusable pieces of code. This alone can get our application pretty far in terms of maintainability and flexibility. However, our collective experience has proved that this alone might not be enough, especially when your application is getting really big – think several hundred components. When dealing with such large applications, sharing and reusing code becomes especially important. +Crear componentes de Vue nos permite extraer partes repetibles de la interfaz junto con su funcionalidad en partes reusables de código. Esto puedo hacer que su aplicación llegue bastante lejos en términos de mantenibilidad y flexibilidad. Sin embargo, nuestra experiencia ha provado que solo esto puede no ser suficiente, especialmente cuando nuestra aplicación se está volviendo realmente grade - piense varios cientos de componentes. Al lidiar con este tipo de aplicaciones, compartir y reusar código se vuelve crucial. -Let’s imagine that in our app, we have a view to show a list of repositories of a certain user. On top of that, we want to apply search and filter capabilities. Our component handling this view could look like this: +Imaginemos que en nuestra aplicación, tenemos una vista que muestra una lista de repositorios de un cierto usuario. Sobre esto, quizas querramos agregar capacidad para buscar o filtrar la misma. Nuestra componente para dicha vista podría verse de la siguiente manera: ```js // src/components/UserRepositories.vue @@ -36,7 +36,7 @@ export default { }, methods: { getUserRepositories () { - // using `this.user` to fetch user repositories + // usando `this.user` para obtener los repositorios del usuarios }, // 1 updateFilters () { ... }, // 3 }, @@ -46,39 +46,39 @@ export default { } ``` -This component has several responsibilities: +Este componente tiene varias responsabilidades: -1. Getting repositories from a presumedly external API for that user name and refreshing it whenever the user changes -2. Searching for repositories using a `searchQuery` string -3. Filtering repositories using a `filters` object +1. Obtener los repositorios de una API presuntamente externa para ese nombre de usuario y refrescarlos siempre que el usuario cambie +2. Buscar repositorios utilizando el _string_ `searchQuery` +3. Filtrar repositorios utilizando el objeto `filters` -Organizing logics with component's options (`data`, `computed`, `methods`, `watch`) works in most cases. However, when our components get bigger, the list of **logical concerns** also grows. This can lead to components that are hard to read and understand, especially for people who didn't write them in the first place. +Orgnizar la lógica en las opciones del componente (`data`, `computed`, `methods`, `watch`) funciona en la mayoría de los casos. Sin embargo, cuando el componente crece, la lista de **responsabilidades lógicas** también crece. Esto puede llevar a componentes difíciles de leer y comprender, en especial para las personas que no las escribieron en primer lugar. -![Vue Option API: Code grouped by option type](https://user-images.githubusercontent.com/499550/62783021-7ce24400-ba89-11e9-9dd3-36f4f6b1fae2.png) +![Vue API de Opciones: código agrupado por tipo de opción](https://user-images.githubusercontent.com/499550/62783021-7ce24400-ba89-11e9-9dd3-36f4f6b1fae2.png) -Example presenting a large component where its **logical concerns** are grouped by colors. +Ejemplo presentado una componente grande donde sus **responsabilidades lógicas** están agrupadas por color. -Such fragmentation is what makes it difficult to understand and maintain a complex component. The separation of options obscures the underlying logical concerns. In addition, when working on a single logical concern, we have to constantly "jump" around option blocks for the relevant code. +Esta fragmentación es la que hace difícil entender y mantener un componente complejo. La separación en opciones oscurece las responsabilidades lógicas subyacentes. Agregado a esto, cuando se trabajo en una única responsabilidad lógica, tenemos que "saltar" constantemente a través de los diferentes bloques de opciones para hallar el código relevante. -It would be much nicer if we could collocate code related to the same logical concern. And this is exactly what the Composition API enables us to do. +Sería mucho mejor si pudieron colocar el código relacionado a la misma responsabilidad lógica junto. Y esto es exactamente lo que la API de Composición nos permite hacer. -## Basics of Composition API +## Aspectos Básicos de la API de Composición -Now that we know the **why** we can get to the **how**. To start working with the Composition API we first need a place where we can actually use it. In a Vue component, we call this place the `setup`. +Ahora que sabemos el **por qué** podemos entrar en el **cómo**. Para comenzar a trabajo con la API de Composición primero necesitamos un lugar donde la podamos utilizar. En un componente Vue, nosotros llamamos a este lugar el `setup`. -### `setup` Component Option +### Opción de Componente `setup` -Watch a free video on setup on Vue Mastery +Vea un video gratuito sobre setup en Vue Mastery -The new `setup` component option is executed **before** the component is created, once the `props` are resolved, and serves as the entry point for composition API's. +La nueva opción de componente `setup` se ejecuta **antes** de que el componente sea creado, una vez que las `props` fueron resultadas, y sirve como punto de entrada para la API de Composición. ::: warning -Because the component instance is not yet created when `setup` is executed, there is no `this` inside a `setup` option. This means, with the exception of `props`, you won't be able to access any properties declared in the component – **local state**, **computed properties** or **methods**. +Dado que la instancia de componente todavía no está creada cuando `setup` es ejecutado, no existe `this` dentro de la opción `setup`. Esto quiere decir que, con la excepción de las `props`, usted no tendra acceso a ninguna propiedad declarada en la componente -- **estado local**, **propiedades computadas** o **métodos**. ::: -The `setup` option should be a function that accepts `props` and `context` which we will talk about [later](composition-api-setup.html#arguments). Additionally, everything that we return from `setup` will be exposed to the rest of our component (computed properties, methods, lifecycle hooks and so on) as well as to the component's template. +La opción `setup` debe ser una función que acepte `props` y `context`, sobre los cuales hablaremos [luego](composition-api-setup.html#arguments). También, todo lo que sea retornado desde `setup` sera expuesto al resto de nuestro componente (propiedades computadas, métodos, _hooks_ del ciclo de video y más) así como a la plantilla del componente. -Let’s add `setup` to our component: +Agreguemos `setup` a nuestro componente: ```js // src/components/UserRepositories.vue @@ -91,21 +91,21 @@ export default { setup(props) { console.log(props) // { user: '' } - return {} // anything returned here will be available for the rest of the component + return {} // cualquier cosa retornada aquí estará disponible en el resto de nuestro componente } - // the "rest" of the component + // el "resto" de nuestro componente } ``` -Now let’s start with extracting the first logical concern (marked as "1" in the original snippet). +Ahora comencemos a extraer nuestra primer responsabilidad lógica (marcada como "1" en el _snippet_ original). -> 1. Getting repositories from a presumedly external API for that user name and refreshing it whenever the user changes +> 1. Obtener los repositorios de una API presuntamente externa para ese nombre de usuario y refrescarlos siempre que el usuario cambie -We will start with the most obvious parts: +Vamos a comenzar con las partes más obvias: -- The list of repositories -- The function to update the list of repositories -- Returning both the list and the function so they are accessible by other component options +- La lista de repositorios +- La función para actualizar la lista de repositorios +- Retornar tanto la lista como la función para que sean accesibles por el resto de las opciones del componente ```js // src/components/UserRepositories.vue `setup` function @@ -120,16 +120,16 @@ setup (props) { return { repositories, - getUserRepositories // functions returned behave the same as methods + getUserRepositories // funciones retornas se comportan igual que los métodos } } ``` -This is our starting point, except it's not working yet because our `repositories` variable is not reactive. This means from a user's perspective, the repository list would remain empty. Let's fix that! +Este es nuestro punto de partida, excepto que todavía no funciona dado que nuestra variable `repositories` no es reactiva. Esto quiere decir que, desde el punto de vista del usuarios, la lista de repositorios se mantendrá vacía. Arreglemoslo! -### Reactive Variables with `ref` +### Variables Reactivas con `ref` -In Vue 3.0 we can make any variable reactive anywhere with a new `ref` function, like this: +En Vue 3.0 podemos crear una variable reactiva en cualquier lado que la nueva función `ref`, de la siguiente manera: ```js import { ref } from 'vue' @@ -137,7 +137,7 @@ import { ref } from 'vue' const counter = ref(0) ``` -`ref` takes the argument and returns it wrapped within an object with a `value` property, which can then be used to access or mutate the value of the reactive variable: +`ref` toma el argumento y lo retorna envuelto en un objeto que una propiedad `value`, la cual puede ser usada luego para acceder o mutar el valor de la variable reactiva: ```js import { ref } from 'vue' @@ -151,17 +151,17 @@ counter.value++ console.log(counter.value) // 1 ``` -Wrapping values inside an object might seem unnecessary but is required to keep the behavior unified across different data types in JavaScript. That’s because in JavaScript, primitive types like `Number` or `String` are passed by value, not by reference: +Envolver valores dentro de un objeto puede parecer innecesario, pero es requerido para mantener un comportamiento unificado a través de diferentes tipos de datos en JavaScript. Esto se debe a que en JavaScript, las primitivas como `Number` o `String` son pasadas por valor, y no por referencia: -![Pass by reference vs pass by value](https://blog.penjee.com/wp-content/uploads/2015/02/pass-by-reference-vs-pass-by-value-animation.gif) +![Pasar por referencia vs pasar por valor](https://blog.penjee.com/wp-content/uploads/2015/02/pass-by-reference-vs-pass-by-value-animation.gif) -Having a wrapper object around any value allows us to safely pass it across our whole app without worrying about losing its reactivity somewhere along the way. +Tener un objeto que envuelve cualquier valor nos permite pasarlo de forma segura a través de toda la aplicación sin preocuparnos de perder la reactividad en el camino. -::: tip Note -In other words, `ref` creates a **Reactive Reference** to our value. The concept of working with **References** will be used often throughout the Composition API. +::: tip Nota +En otras palabras, `ref` crea una **Referencia Reactiva** a nuestro valor. El concepto de trabajo con **Referencias** será utilizado a menudo en toda la API de Composición. ::: -Back to our example, let's create a reactive `repositories` variable: +Volviendo a nuestro ejemplo, crearemos una variable reactive `repositories`: ```js // src/components/UserRepositories.vue `setup` function @@ -182,7 +182,7 @@ setup (props) { } ``` -Done! Now whenever we call `getUserRepositories`, `repositories` will be mutated and the view will be updated to reflect the change. Our component should now look like this: +Listo! Ahora siempre que llamemos `getUserRepositories`, `repositories` será mutada y la vista se actualizará para reflejar el cambio. Nuestro componente debería verse de la siguiente manera: ```js // src/components/UserRepositories.vue @@ -227,17 +227,17 @@ export default { } ``` -We have moved several pieces of our first logical concern into the `setup` method, nicely put close to each other. What’s left is calling `getUserRepositories` in the `mounted` hook and setting up a watcher to do that whenever the `user` prop changes. +Hemos movidas unas cuantas partes de nuestra primera responsabilidad lógica dentro del método `setup`, muy cerca una de la otra. Lo que nos queda es invocar `getUserRepositories` dentro del _hook_ `mounted` y configurar un _watcher_ para realizarlo cada vez que nuestra prop `user` cambie. -We will start with the lifecycle hook. +Comenzaremos por el _hook_ del ciclo de vida. -### Lifecycle Hook Registration Inside `setup` +### Registro de un _Hook_ del Ciclo de Vida dentro de `setup` -To make Composition API feature-complete compared to Options API, we also need a way to register lifecycle hooks inside `setup`. This is possible thanks to several new functions exported from Vue. Lifecycle hooks on composition API have the same name as for Options API but are prefixed with `on`: i.e. `mounted` would look like `onMounted`. +Para hacer que la API de composición fuese completa en comparación a la API de Opciones, también necesitamos una forma de registrar _hooks_ del ciclo de vida dentro de `setup`. Esto es posible gracias a nuevas funciones exportadas por Vue. Los _hooks_ del ciclo de vida en la API de composición tienen el mismo nombre al que tienen en la API de Opciones, pero tiene el prefijo `on`: por ejemplo, `mounted` sería `onMounted`. -These functions accept a callback that will be executed when the hook is called by the component. +Estas funciones aceptan un `callback` que será ejecutado cuando el _hook_ es llamad por el componente. -Let’s add it to our `setup` function: +Agreguemos esto a nuestra función `setup`: ```js // src/components/UserRepositories.vue `setup` function @@ -251,7 +251,7 @@ setup (props) { repositories.value = await fetchUserRepositories(props.user) } - onMounted(getUserRepositories) // on `mounted` call `getUserRepositories` + onMounted(getUserRepositories) // al "montarse" invoca `getUserRepositories` return { repositories, @@ -260,30 +260,30 @@ setup (props) { } ``` -Now we need to react to the changes made to the `user` prop. For that we will use the standalone `watch` function. +Ahora necesitamos reaccionar a los cambios de nuestra prop `user`. Para ello usaremos la función independiente `watch`. -### Reacting to Changes with `watch` +### Reaccionando a Cambios con `watch` -Just like how we set up a watcher on the `user` property inside our component using the `watch` option, we can do the same using the `watch` function imported from Vue. It accepts 3 arguments: +Al igual que configuramos un _watcher_ sobre la propiedad `user` dentro de nuestro componente utilizando la opción `watch`, podemos realizarlo utilizando la función `watch` importada desde Vue. Esta acepta 3 argumentos: -- A **Reactive Reference** or getter function that we want to watch -- A callback -- Optional configuration options +- Una **Referencia Reactiva** o función _getter_ que queremos observar +- Un _callback_ +- Configuración opcional -**Here’s a quick look at how it works.** +**Aquí hay un ejemplo de como funcionaría.** ```js import { ref, watch } from 'vue' const counter = ref(0) watch(counter, (newValue, oldValue) => { - console.log('The new counter value is: ' + counter.value) + console.log('El nuevo valor de counter es: ' + counter.value) }) ``` -Whenever `counter` is modified, for example `counter.value = 5`, the watch will trigger and execute the callback (second argument) which in this case will log `'The new counter value is: 5'` into our console. +Siempre que `counter` sea modificado, por ejemplo `counter.value = 5`, el `watch` invocará y ejecutará el _callback_ (segundo argumento) que en este caso escribirá `'El nuevo valor de counter es: 5'` en nuestra consola. -**Below is the Options API equivalent:** +**Debajo esta el equivalente utilizando la API de Opciones:** ```js export default { @@ -294,35 +294,35 @@ export default { }, watch: { counter(newValue, oldValue) { - console.log('The new counter value is: ' + this.counter) + console.log('El nuevo valor de counter es: ' + this.counter) } } } ``` -For more details on `watch`, refer to our [in-depth guide](). +Por más detalles sobre `watch`, vea nuestra [guía en profundidad](). -**Let’s now apply it to our example:** +**Ahora apliquemoslo a nuestro ejemplo:** ```js // src/components/UserRepositories.vue `setup` function import { fetchUserRepositories } from '@/api/repositories' import { ref, onMounted, watch, toRefs } from 'vue' -// in our component +// en nuestro componentes setup (props) { - // using `toRefs` to create a Reactive Reference to the `user` property of props + // utilizar `toRefs` para crear Referencias Reactivas para la prop `user` const { user } = toRefs(props) const repositories = ref([]) const getUserRepositories = async () => { - // update `props.user` to `user.value` to access the Reference value + // actualizar `props.user` a `user.value` para acceder al valor Referencia repositories.value = await fetchUserRepositories(user.value) } onMounted(getUserRepositories) - // set a watcher on the Reactive Reference to user prop + // configurar un watcher en la Referencia Reactica para la prop user watch(user, getUserRepositories) return { @@ -332,13 +332,13 @@ setup (props) { } ``` -You probably have noticed the use of `toRefs` at the top of our `setup`. This is to ensure our watcher will react to changes made to the `user` prop. +Probablemente haya notado el use de `toRefs` al comienzo de nuestro `setup`. Esto se realiza para asegurar que nuestro _watcher_ reaccione a los cambios realizados a la prop `user`. -With those changes in place, we've just moved the whole first logical concern into a single place. We can now do the same with the second concern – filtering based on `searchQuery`, this time with a computed property. +Con estos cambios, hemos movido toda la primer responsabilidad lógica a un único lugar. Ahora podemos realizar lo mismo con la segunda responsabilidad - filtrar según `searchQuery`, esta vez con una propiedad computada. -### Standalone `computed` properties +### Propiedad Computadas Independientes -Similar to `ref` and `watch`, computed properties can also be created outside of a Vue component with the `computed` function imported from Vue. Let’s get back to our counter example: +De forma similar a `ref` y `watch`, las propiedades computadas también pueden ser utilizada fuera de un componente Vue con la función `computed` importada desde Vue. Volvamos a ver nuestro contador de ejemplo: ```js import { ref, computed } from 'vue' @@ -351,29 +351,29 @@ console.log(counter.value) // 1 console.log(twiceTheCounter.value) // 2 ``` -Here, the `computed` function returns a _read-only_ **Reactive Reference** to the output of the getter-like callback passed as the first argument to `computed`. In order to access the **value** of the newly-created computed variable, we need to use the `.value` property just like with `ref`. +Aquí, la función `computed` retorna una **Referencia Reactiva** de _sólo lectura_ a la salida del _getter-like callback_ pasado como primer argumento a `computed`. Para poder acceder al **valor** de la nueva variable computada, usted debe utilizar la propiedad `.value`, al igual que con `ref`. -Let’s move our search functionality into `setup`: +Movamos ahora nuestra funcionalidad de búsqueda dentro de `setup`: ```js // src/components/UserRepositories.vue `setup` function import { fetchUserRepositories } from '@/api/repositories' import { ref, onMounted, watch, toRefs, computed } from 'vue' -// in our component +// en nuestro componente setup (props) { - // using `toRefs` to create a Reactive Reference to the `user` property of props + // utilizar `toRefs` para crear Referencias Reactivas para la prop `user` const { user } = toRefs(props) const repositories = ref([]) const getUserRepositories = async () => { - // update `props.user` to `user.value` to access the Reference value + // actualizar `props.user` a `user.value` para acceder al valor Referencia repositories.value = await fetchUserRepositories(user.value) } onMounted(getUserRepositories) - // set a watcher on the Reactive Reference to user prop + // configurar un watcher en la Referencia Reactica para la prop user watch(user, getUserRepositories) const searchQuery = ref('') @@ -392,7 +392,7 @@ setup (props) { } ``` -We could do the same for other **logical concerns** but you might be already asking the question – _Isn’t this just moving the code to the `setup` option and making it extremely big?_ Well, that’s true. That’s why before moving on with the other responsibilities, we will first extract the above code into a standalone **composition function**. Let's start with creating `useUserRepositories`: +Podríamos realizar lo mismo para la atra **responsabilidad lógica**, pero usted seguramente se este realizando la siguiente pregunta - _¿Esto no es simplemente mover el código a la opción `setup` y hacer la misma extremadamente grande?_ Bueno, eso es cierto. Es por esto que antes de mover las otras responsabilidades, primero extraeremos el código de arribo en una **función de composición** independiente. Comencemos por crear `useUserRepositories`: ```js // src/composables/useUserRepositories.js @@ -416,7 +416,7 @@ export default function useUserRepositories(user) { } ``` -And then the searching functionality: +Y luego nuestra funcionalidad de búsqueda: ```js // src/composables/useRepositoryNameSearch.js @@ -438,7 +438,7 @@ export default function useRepositoryNameSearch(repositories) { } ``` -**Now having those two functionalities in separate files, we can start using them in our component. Here’s how this can be done:** +**Ahora, al tener ambas funcionalidad en archivos separados, podemos utilizarlas dentro de nuestro componente. Así es como esto se haría:** ```js // src/components/UserRepositories.vue @@ -462,8 +462,8 @@ export default { } = useRepositoryNameSearch(repositories) return { - // Since we don’t really care about the unfiltered repositories - // we can expose the filtered results under the `repositories` name + // Dado que realmente no nos importan los repositorios no filtrados + // podemos exponer el resultado filtrado bajo la variable `repositories` repositories: repositoriesMatchingSearchQuery, getUserRepositories, searchQuery, @@ -483,7 +483,7 @@ export default { } ``` -At this point you probably already know the drill, so let’s skip to the end and migrate the leftover filtering functionality. We don’t really need to get into the implementation details as it’s not the point of this guide. +En este punto usted ya sabe como va la cosa, así que vayamos al final y migremos la funcionalidad de filtrado restante. No tenemos que entrar en los detalles de implementación, puesto que no va al caso de esta guía. ```js // src/components/UserRepositories.vue @@ -514,8 +514,8 @@ export default { } = useRepositoryFilters(repositoriesMatchingSearchQuery) return { - // Since we don’t really care about the unfiltered repositories - // we can expose the end results under the `repositories` name + // Dado que realmente no nos importan los repositorios no filtrados + // podemos exponer el resultado filtrado bajo la variable `repositories` repositories: filteredRepositories, getUserRepositories, searchQuery, @@ -526,6 +526,6 @@ export default { } ``` -And we are done! +Y terminamos! -Keep in mind that we've only scratched the surface of Composition API and what it allows us to do. To learn more about it, refer to the in-depth guide. +Recuerde que solamente razgamos la superficie de la API de Composición y lo que esta nos permite hacer. Para aprender más acerca de la misma, vea la guía en profundidad.