Vue - Js 3 y TypeScript

Télécharger au format pdf ou txt
Télécharger au format pdf ou txt
Vous êtes sur la page 1sur 5

Vue.

js
Página de Atajos
Iniciar un proyecto: (Recomendado)
Registrar App-Scoped assets. (Ej: Componente)

npm init vue@latest app.component(



'TodoDeleteButton', TodoDeleteButton
);

Proyecto con Vite: (opcional)

npm create vite Directivas


yarn create vite Las directivas en Vue.js, tiene el pre jo v-, estas
directivas esperan una expresión de JavaScript con la
pnpm create vite

excepción de v-for, v-on, v-slot.

Usar desde un CDN:


Raw HTML

<p>Using text interpolation: {{ rawHtml }}</p>


<script src="https://unpkg.com/vue@3/ <p>Using v-html directive:
dist/vue.global.js"></script> <span v-html=“rawHtml"></span>

</p>

Ejemplo:

<script src=“https://unpkg.com/
vue@3/dist/vue.global.js"></script> v-bind

<div v-bind:id=“dynamicId"></div>
<div id="app">{{ message }}</div>
// Format corta
<script> <div :id=“dynamicId"></div>
const { createApp } = Vue; // Válido también
<div :id="`list-${id}`"></div>
createApp({

data() {
return {
Enlazar multiples propiedades a la vez

message: 'Hello Vue!'


} const objectOfAttrs = {
} id: 'container',
}).mount(‘#app'); class: 'wrapper'
</script>
}

<div v-bind="objectOfAttrs"></div>
Con guraciones comunes en el main.ts

import { createApp } from 'vue';


import { createPinia } from 'pinia';
Atributos dinámicos:

import App from './App.vue'; <a v-on:


import router from ‘./router'; [eventName]="doSomething"> ... </a>
import './assets/main.css'; <!-- shorthand -->
const app = createApp(App);
<a @[eventName]="doSomething">

app.config.errorHandler = (err) => {


/* handle error */ v-on

} <a v-on:click="doSomething"> ... </a>


app.use(createPinia());
app.use(router); <!-- shorthand -->
<a @click="doSomething"> ... </a>
app.mount(‘#app');

devtalles.com fernando-herrera.com vuejs.org/

fi

fi

Vue.js
Página de Atajos
TypeScript con CompositionAPI

#2
Inferir props: (TypeScript realizará el tipado)
interface Props {
<script setup lang=“ts"> name: string
count?: number
const props = defineProps({ }
foo: { type: String, required: true },
bar: Number // reactive destructure for defineProps()
}); const {
name,
props.foo; // string count = 100
props.bar; // number | undefined } = defineProps<Props>();
</script>

Fuera del Script Setup, es necesario usar el


de neProps es un genérico y se puede de neComponent( ) para habilitar props y su
especi car en línea, con interfaces o clases.
tipado.

(No es necesario importar de neProps - es global)

import { defineComponent } from 'vue';


const props = defineProps<{
foo: string export default defineComponent({
bar?: number props: {
}>(); message: String
},
// Con interfaces/clases setup(props) {
interface Props { props.message //type: string
foo: string; }
bar?: number; });
}

const props = defineProps<Props>(); de neEmits dentro del Script Setup puede ser

inferida o con declaración de tipo.

(No es necesario importar de neEmits - es global)

IMPORTANTE: Esto no es válido

// runtime
import { Props } from './other-file'; const emit = defineEmits(['change', 'update']);

// No es soportado // type-based
defineProps<Props>(); const emit = defineEmits<{

(e: 'change', id: number): void
(e: 'update', value: string): void
}>();
de neProps con withDefaults. (Docs)

Cuando se usa TS para los props, perdemos la


posibilidad de valores por defecto. Para esto Fuera del Script Setup, hay que utilizar
podemos usar 2 formas:
de neComponent( ) para obtener y llamar el
#1 emit.

import { defineComponent } from 'vue';


export interface Props {
msg?: string
export default defineComponent({
labels?: string[]
emits: ['change'],
}
setup(props, { emit }) {
// type check / auto-completion
const props =
emit(‘change');
withDefaults(defineProps<Props>(), {
}
msg: 'hello',
});
labels: () => ['one', 'two']

});

devtalles.com fernando-herrera.com vuejs.org/

fi
fi
fi
fi
fi

fi

fi
fi

Vue.js
Página de Atajos
Reactividad de Vue.js
Asignando el tipo a computed( )
Asignando el tipo a ref( ) TS puede inferir el tipo basado en el retorno, pero
La función ref, crea un objeto reactivo, el cual se aconseja especi carlo.

puede inferir el tipo o usarlo como un genérico.


import { ref, computed } from ‘vue';
import { ref } from 'vue';
const count = ref(0);
// inferred type: Ref<number> // inferred type: ComputedRef<number>
const year = ref(2020); const double = computed(() => count.value * 2);

// => TS Error: Type 'string' is not


assignable to type 'number'.
// Mediante genéricos
const double = computed<number>(() => {
year.value = ‘2020';
// type error

// if this doesn't return a number

 })
También:

import { ref } from 'vue';


import type { Ref } from ‘vue'; Asignando el tipo a eventos:

const year: Ref<string | number> = ref(‘2020');


<script setup lang="ts">
year.value = 2020; // ok! function handleChange(event) {

// `event` implicitly has `any` type
console.log(event.target.value)
}
Personalmente mi favorita:
</script>
import { ref } from 'vue';
<template>
// Type: Ref<string | number> <input
const year = ref<string | number>(‘2020');
type=“text"
year.value = 2020; // ok! @change="handleChange" />

</template>

Asignando el tipo a reactive( )


Lo anterior puede dar errores por el tipo any, por
La función reactive, convierte un objeto normal a
lo cual asignar Event y luego hacer un cast.

un objeto reactivo. (Primitivos no son soportados)

function handleChange(event: Event) {


import { reactive } from 'vue'; console.log(
(event.target as HTMLInputElement).value
// inferred type: { title: string } );
const book = reactive({ }
title: 'Vue Guide'

});

Asignando el tipo a referencias HTML

Es interesa que se pueden usar interfaces <script setup lang="ts">


import { ref, onMounted } from 'vue';
simples con la función reactive. (No usarlo como genérico)

import { reactive } from 'vue'; const el = ref<HTMLInputElement | null>(null);

interface Book { onMounted(() => {


title: string el.value?.focus();
year?: number });
</script>
}
<template>
const book: Book = reactive({
<input ref="el" />
title: 'Vue Guide'
}); </template>

devtalles.com fernando-herrera.com vuejs.org/

fi

Vue.js
Página de Atajos
Asignar el tipo a referencias en el Template:
También puedes construir tu Store con una
Útil cuando quieres exponer información entre combinación de funciones reactivas de Vue.

componentes padre e hijo usando Script Setup.


import { ref } from ‘vue';

// Global state,
<!-- MyModal.vue --> // Creado en el scope del módulo
<script setup lang="ts"> const globalCount = ref(1);
import { ref } from ‘vue';
export function useCount() {
const isContentShown = ref(false); // local state, creado por componente
const open = () => const localCount = ref(1);
(isContentShown.value = true);
return {
globalCount,
defineExpose({ localCount
open }
}); };
</script>

Y para poder obtener la instancia de “MyModal”, Pinia Store


necesitamos obtener el tipo vía typeof y el Pinia es el gestor de estado actualmente
InstanceType:
recomendado por Evan You, autor y creador de Vite y
<!-- App.vue --> Vue.

<script setup lang="ts">


import MyModal from ‘./MyModal.vue'; Instalar Pinia
const modal = ref<InstanceType<typeof MyModal> | null>(null);
yarn add pinia
const openModal = () => { npm install pinia
modal.value?.open()
} import { createApp } from 'vue';
</script> import { createPinia } from 'pinia';
import App from './App.vue';

State Management: const pinia = createPinia();


const app = createApp(App);
Reactive Objects:
Vue cuenta con una forma nativa te trabajar con un app.use(pinia);
store global usando la función reactive( ).
app.mount('#app');

// store.js Ejemplo de Pinia Store - Option Store

import { reactive } from ‘vue'; export const useCounterStore =


defineStore('counter', {
export const store = reactive({ state: () => ({
count: 0, count: 0,
increment() { name: 'Eduardo'
this.count++ }),
} getters: {
}); doubleCount: (state) => state.count * 2,

},
actions: {
<template>
increment() {
<button @click="store.increment()">
From B: {{ store.count }} this.count++
</button> },
</template> },

});

devtalles.com fernando-herrera.com vuejs.org/

Vue.js
Página de Atajos
Ejemplo de Pinia Setup Store. Usando la Se puede re-establecer el store llamando $reset( )

composición reactiva de Vue.


const store = useStore();
export const useCounterStore = defineStore('counter', () =>
{
const count = ref(0);
store.$reset();
const name = ref(‘Eduardo');

const doubleCount = computed(() => count.value * 2); Se puede mutar diferentes piezas del store con $patch
function increment() {
count.value++ store.$patch({
} count: store.count + 1,
return { count, name, doubleCount, increment }; age: 120,
}); name: 'DIO',

});
Dentro del Setup Store:

• ref( )’s se vuelven propiedades de estado

• computed( )’s, se vuelven getters


Alternativamente se puede llamar con un callback para
• functions( )’s, se vuelven acciones
obtener el state del store.

cartStore.$patch((state) => {
¿Cuál de las dos formas usar? state.items.push({
Usa la que se haga más familiar para ti o resulte más name: 'shoes',
simple, si no estás seguro, empieza con Option Stores.
quantity: 1
});
Consumir el store: state.hasChanged = true;
import { useCounterStore } from '@/stores/counter' });

export default {
setup() {
const store = useCounterStore(); Se puede suscribir para escuchar cambios del store,
pero la ventaja sobre el $watch de Vue, es que la
return {
//Puedes regresar toda la instancia del store suscripción se dispara una vez después del patch.

// y así usarlo en el template cartStore.$subscribe((mutation, state) => {


store, // import { MutationType } from 'pinia'
} mutation.type; // 'direct' | 'patch object' | 'patch
}, function'
} // mismo que el cartStore.$id
mutation.storeId; // 'cart'

// Sólo disponible con mutation.type === 'patch object'
mutation.payload; // objeto pasado al cartStore.$patch()

IMPORTANTE: Esto no funciona


// Mantener todo el state en el localstorage
localStorage.setItem('cart', JSON.stringify(state));
const store = useCounterStore(); });
// ❌ esto no funciona, rompe la reactividad

// Es lo mismo que desestructurar Props


const { name, doubleCount } = store; Usar otros stores dentro de un store.


import { useOtherStore } from './other-store';

export const useStore = defineStore('main', {


En caso de necesidad, usar storeToRefs( )
state: () => ({
import { storeToRefs } from ‘pinia'; // ...
}),
export default defineComponent({ getters: {
setup() {
const store = useCounterStore();
otherGetter(state) {
const otherStore = useOtherStore();
// State a variables reactivas return state.localData + otherStore.data;
const { name, doubleCount } = storeToRefs(store); },
},
// Acciones pueden ser extraídas directamente });
const { increment } = store;

return {
name,
doubleCount, Sitios web útiles para continuar:

increment, github.com/vuejs/awesome-vue

}
}, next.attojs.org/

}); pinia.vuejs.org/


github.com/vuejs/apollo

devtalles.com fernando-herrera.com vuejs.org/

Vous aimerez peut-être aussi