Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
NotificationsYou must be signed in to change notification settings

Curso-VUE/3-vue-shop

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

  1. Crear proyecto con Vue UI
  2. Instalación y configuración de los plugins
  3. Iniciar un módulo con Vuex para manejar los productos de la aplicación
  4. Acciones del móduloproducts haciendo petición HTTP conasync yawait
  5. Definir la lógica del listado de productos
  6. Primera versión del sitado de productos paginados
  7. Componente que representa un producto
  8. Componente con slots para definir un layout
  9. Módulo del carrito de compras
  10. Añadir productos al carrito desde el listado de productos
  11. Componente carrito
  12. Persistir Vuex en LocalStorage
  13. Persistir Vuex en IndexedDB, ideal para PWAs

1. Crear proyecto con Vue UI

Creamos el nuevo proyecto a través devue ui

Vamos a utilizar los siguientes plugins:


2. Instalación y configuración de los plugins

Instalamos ambos plugins mediante el comandonpm i bootstrap-vue vue-paginate

Para cargar los plugins en la aplicación es buena práctica crear un directorioplugins ensrc donde incluiremos un archivo .js por cada plugin que vayamos a utilizar.

  • bootstrap-vue.js
importVuefrom'vue'import{BootstrapVue}from'bootstrap-vue'import'bootstrap/dist/css/bootstrap.css'import'bootstrap-vue/dist/bootstrap-vue.css'Vue.use(BootstrapVue)
  • vue-paginate
importVuefrom'vue'importVuePaginatefrom'vue-paginate'Vue.use(VuePaginate)

Crearemos también en la carpetaplugins unindex.js donde requeriremos los dos ficheros que acabamos de crear.

require('./bootstrap-vue');require('./vue-paginate');

Finalmente enmain.js requerimos elindex.js deplugins después de las importaciones.

importVuefrom'vue'importAppfrom'./App.vue'importstorefrom'./store'require('./plugins');...

3. Iniciar un módulo con Vuex para manejar los productos de la aplicación

Para generar el dataset utilizamoshttps://www.mockaroo.com/ que es un generador de datos aleatorios.

Vamos a generar un dataset con elementos que tengan los parámetros siguientes:

  • id
  • name
  • picture
  • price
  • stock

Guardamos su contenido en un nuevo archivopublic/fixtures/products.json.

En este proyecto vamos a trabajar con elstore mediante módulos, así que dentro desrc creamos una carpetamodules y tantas carpetas como módulos necesitemos. En este caso, por ahora únicamente necesitaremos una carpetaproducts.

Dentro de la carpetaproducts creamos un archivo para las actions, otro para los mutations, otro para el state y finalmente un index que importe los anteriores.

  • state.js
exportdefault{products:[]}
  • mutations.js
exportfunctionsetProducts(state,products){state.products=products;}
  • actions.js (por ahora vacío)

  • index.js

importstatefrom'./state';import*asmutationsfrom'./mutations';import*asactionsfrom'./actions';constnamespaced=true;exportdefault{  namespaced,  state,  mutations,  actions}

Finalmente importamos el módulo en elstore.

importVuefrom'vue'importVuexfrom'vuex'Vue.use(Vuex)importproductsfrom'../modules/products';exportdefaultnewVuex.Store({modules:{    products}})

4. Acciones del móduloproducts haciendo petición HTTP conasync yawait

Vamos a utilizar las acciones para realizar peticiones asíncronas y actualizar elstore.

Configuramos la acción en/src/modules/products/actions.js:

exportasyncfunctionfetchProducts({ commit}){constdata=awaitfetch('/fixtures/products.json');constproducts=awaitdata.json();commit('products/setProducts',products,{root:true});}

En el commit hay que especificar la ruta del mutation que vamos a utilizar, el nuevo valor y { root: true} para indicar que el estado se encuentra en la raiz.


5. Definir la lógica del listado de productos

Eliminamos el componenteHelloWorld.vue así como su importación, declaración y renderizado deapp.vue. Eliminamos también los estilos, de forma que nos quede el componente limpio.

En generamos un nuevo componenteProductList. En él configuramos el mapState y el mapActions para acceder al estado y a las acciones del móduloproducts.

Configuramos el hookmounted para obtener los productos una vez el componente se haya cargado.

En el template, visualizamos la cantidad de productos que se han cargado para comprobar que funciona correctamente.

<template><div>{{products.length}}</div></template><script>import{mapActions,mapMutations,mapState}from'vuex';exportdefault{mounted(){this.fetchProducts()},computed:{    ...mapState('products',['products'])},methods:{    ...mapActions('products',['fetchProducts'])}}</script>

Configuramos la paginación en los datos deProductList:

data(){return{paginate:['products'],perPage:3}},

6. Primera versión del sitado de productos paginados

Creamos una primera aproximación del template de componenteProductList.

Primero establecemos que se visualice un alert cuando no haya datos de productos:

<template><divv-if="products.length"></div><b-alertv-elseshowvariant="info">No hay productos para mostar</b-alert></template>

Para la lista de productos paginados utilizamos la etiquetapaginate en eldiv:

<paginatename="products":list="products":per="perPage"><pv-for="product in paginated('products')":key="product.id">{{product.name}}</p></paginate>

Al mismo nivel que paginate renderizamos los links de las siguientes páginas mediante la etiquetapaginate-links:

<paginate-linksfor="products":limit="10":classes="{    'ul': 'pagination',    'li': 'page-item',    'li > a': 'page-link'  }"></paginate-links>

El límite indica la cantidad máxima de paginate-links que se muestran. Con la configuración de clases podemos añadir una clase a los elementos que decidamos.


7. Componente que representa un producto

Creamos el template del nuevo componenteProductItem:

<template><b-card:title="product.name":img-src="product.picture":img-alt="product.name"img-topstyle="max-width: 30rem;"class="mb-2"><b-buttonblockvariant="warning"@click="$emit('addToCart', product)">      Añadir al carrito</b-button></b-card></template>

Definimos en el script las props que nos llegarán del componente padre (en este caso product):

<script>exportdefault{props:{product:{type:Object,required:true,}}}</script>

EnProductList renderizamos el nuevo componente sustityyendo lo que teníamos dentro de las etiquetaspaginate:

<b-card-groupcolumns><product-itemv-for="product in paginated('products')":key="product.id":product="product"@addTOCart="addProductToCart"></product-item></b-card-group>

Creamos un método para manejar el evento que se genera la hacer click en el botón del componente hijo:

methods:{  ...mapActions('products',['fetchProducts']),addProductToCart(product){console.log(product)}}

8. Componente con slots para definir un layout

Vamos a utilizar slots para definir un layout en donde mostrar los productos y el carrito.

Generamos un nuevo componente ShopLayout en el que renderizaremos a 9 columnas la lista de productos y a 3 columnas el carrito:

<template><b-container><b-row><b-colcols="9"><slotname="product-list"></slot></b-col><b-colcols="3"><slotname="cart"></slot></b-col><b-row></b-container></template>

Utilizamos el nuevo componente enapp.vue:

  • En el template:
<template><divid="app"><shop-layout><templateslot="product-list"><product-list></product-list></template><templateslot="cart">        Carrito</template></shop-layout></div></template>
  • En el script:
<script>importProductListfrom"./components/ProductList.vue";importShopLayoutfrom"./components/ShopLayout.vue";exportdefault{name:"App",components:{    ShopLayout,    ProductList},};</script>

9. Módulo del carrito

Creamos una nuevo módulocart que tendrástate,mutations ygetters.

  • index.js: Al igual que en el móduloproducts exportamos los elementos del módulo:
importstatefrom'./state';import*asmutationsfrom'./mutations';import*asgettersfrom'./getters';constnamespaced=true;exportdefault{  namespaced,  state,  mutations,  getters}
  • state.js: El estado del módulo contentrá el carrito de la compra
exportdefault{cart:[]}
  • mutations.js: Exsportamos una funciones para añadir un producto a la lista y otra para eliminar un producto.
import{find,filter}from'lodash';exportfunctionaddProduct(state,product){constproductInCart=find(state.cart,{id:product.id});if(!productInCart){constcopy=Object.assign({},product);copy.qty=1;state.cart.push(copy);}else{productInCart.qty+=1;}}exportfunctionremoveProductFromCart(state,product){state.cart=filter(state.cart,({id})=>id!==product.id);}
  • getters.js: Losgetters permiten obtener los datos del state filtrados o calculados.
exportfunctiontotalCost(state){returnstate.cart.reduce((acc,product)=>{returnacc+parseFloat(product.price)*product.qty},0);}

10. Añadir productos al carrito desde el listado de productos

Vamos a definir el métodoaddProductToCart del componenteProductList mapeando la mutación del módulocart:

  methods:{    ...mapActions('products',['fetchProducts']),    ...mapMutations('cart',['addProduct']),addProductToCart(product){this.addProduct(product);}}

11. Componente carrito

Generamos el componentecart y en el script definimos los siguientes elementos:

  • data: array con los nombres de los campos de cada producto que utilizaremos en una tabla de bootstrap.
  • computed:state ygetters decart
  • methods:mutations decart.
<script>import{mapGetters,mapMutations,mapState}from'vuex';exportdefault{data(){return{fields:['name','qty','price','actions']}},computed:{    ...mapState('cart',['cart']),    ...mapGetters('cart',['totalCost'])},methods:{    ...mapMutations('cart',['removeProductFromCart'])}}</script>

El template quedaría de la siguiente forma:

<template><divv-if="cart.length"><b-tablestripedhover:items="cart":fields="fields"><templatev-slot:cell(actions)="cell"><b-buttonsize="sm"variant="danger"@click.stop="removeProductFromCart(cell.item)">          Eliminar</b-button></template></b-table><b-alertshowvariant="success"class="text-center">      Coste total: {{ totalCost }}€</b-alert></div><b-alertv-elseshowvariant="info">    No hay productos en el carrito</b-alert></template>

Importamos el componentecart al componente principal,app:

...<templateslot="cart"><cart></cart></template>...
...importCartfrom"./components/Cart.vue";  components:{ShopLayout,ProductList,Cart},};...

12. Persistir Vuex en LocalStorage

Vamos a instalar la dependenciavuex-persist en el proyecto.

Realizamos la modificaciones necesarias en elstore:

importVuefrom'vue'importVuexfrom'vuex'importVuexPersistencefrom'vuex-persist'importproductsfrom'../modules/products';importcartfrom'../modules/cart';Vue.use(Vuex)constvuexLocal=newVuexPersistence({storage:window.localStorage})exportdefaultnewVuex.Store({modules:{    products,    cart},plugins:[vuexLocal.plugin]})

De esta forma se guardarán en LocalStorage el estado de todos los módulos de nuestra aplicación. Si decidimosalmacenar el estado de sólo algunos módulos, debemos indicarlo en la configuración del plugin:

constvuexLocal=newVuexPersistence({storage:window.localStorage,modules:['cart']})

13. Persistir Vuex en IndexedDB, ideal para PWAs

Vamos a utilizar el pluginlocalForage

Únicamente debemos modificar la configuración del storage en VuexPersistance...

importlocalForagefrom'localforage'constvuexLocal=newVuexPersistence({storage:localForage,asyncStorage:true,modules:['cart']})

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

[8]ページ先頭

©2009-2025 Movatter.jp