- vừa được xem lúc

Xây dựng eCommerce shopping cart bằng Svelte JavaScript framework.

0 0 23

Người đăng: Nguyen Xuan Tam

Theo Viblo Asia

Introduction

Svelte JavaScript framework là miễn phí và là open-source. Đuợc tạo bởi Rich Harris và được duy trì bởi các thành viên cốt lõi của Svelte. Các ứng dụng Svelte không bao gồm các tham chiếu framework khác. Thay vào đó, việc xây dựng một ứng dụng Svelte sẽ tạo ra mã để thao tác DOM, điều này có thể làm giảm kích thước của các tệp được chuyển cũng như mang lại hiệu suất khởi động và thời gian chạy của ứng dụng tốt hơn. Svelte có trình biên dịch riêng để chuyển đổi code ứng dụng thành JavaScript phía máy client tại thời điểm xây dựng. Nó được viết bằng TypeScript. Mã nguồn Svelte được cấp phép theo Giấy phép MIT và được lưu trữ trên GitHub.

Build Svelte ecommerce cart.

Chúng ta sẽ bắt đầu tạo ứng dụng svelte. Chúng ta sẽ tạo 1 thư mục sveltecart trong thư mục home sử dụng command sau.

npx degit sveltejs/template sveltecart

Cấu trúc thư mục

Các file quang trọng nhất trong ứng dụng này là:

  • src/main.js
  • src/App.svelte
  • public/index.html

File public/index.html có nội dung sau:

<!DOCTYPE html>
<html lang="en">
<head> <meta charset='utf-8'> <meta name='viewport' content='width=device-width,initial-scale=1'> <title>Svelte app</title> <link rel='icon' type='image/png' href='/favicon.png'> <link rel='stylesheet' href='/global.css'> <link rel='stylesheet' href='/build/bundle.css'> <script defer src='/build/bundle.js'></script>
</head>
<body>
</body>
</html>

Lưu ý: Ở đoạn html trên có gọi 2 file css và 1 file js trong cùng một thư mục. File global.css nắm giữ css có thể ảnh hưởng đến bất kỳ component nào. File build/bundle.css được tạo từ css trong mỗi component. File build/bundle.js được tạo từ JavaScript and HTML trong mỗi component và bất kỳ javascript nào khác trong ứng dụng.

File src/main.js có nội dung như sau:

import App from './App.svelte';
const app = new App({ target: document.body, props: { name: 'world' }
});
export default app;

Điều này tạo ra App component, thuộc tính target có thể chỉ nơi component được tạo ra. Đối với hầu hết các ứng dụng, đây là phần nội dung của tài liệu. name prop được pass đến App component.

File src/App.svelte chưa nội dung sau:

<script> export let name;
</script>
<main> <h1>Hello {name}!</h1> <p>Visit the <a href="https://svelte.dev/tutorial">Svelte tutorial</a> to learn how to build Svelte apps.</p>
</main>
<style> main { text-align: center; padding: 1em; max-width: 240px; margin: 0 auto; } h1 { color: #ff3e00; text-transform: uppercase; font-size: 4em; font-weight: 100; } @media (min-width: 640px) { main { max-width: none; } }
</style>

Các biến được xuất trông thẻ script là giá trị nhận được từ file src/main.js. Dấu ngoặc {} dùng để xuất giá trị của một biểu thức javascript. Thẻ style để lưu trữ tất cả styles css được áp dụng cho ứng dụng này.

Building the Svelte eCommerce shopping cart

Đầu tiên là sẽ tạo thư mục và file và bắt đầu ứng dụng. Để tạo các thành phần bắt buộc, hãy thực hiện các lện sau trong terminal

cd src
mkdir CartComponents
mkdir Stores
cd CartComponents
touch card.svelte
touch cardwrapper.svelte
touch checkout.svelte
touch checkoutitem.svelte
touch navbar.svelte
cd ..
cd Stores
touch stores.js
cd..
touch items.js

Trong src thư mục, chúng ta có thể tạo CartComponents thư mục và bên trong CartComponents thư mục sẽ tạo file:

card.svelte
cardwrapper.svelte
checkout.svelte
checkoutitem.svelte
navbar.svelte

Giống như, Trong thư mục src chúng ta có thể tạo Stores thư mục và bên trong Stores thư mục, chúng ta có thể tạo stores.js. Tiếp theo trong src thư mục. Chúng ta sẽ tạo 1 file Item.js.

Chúng ta sẽ sử dụng Bootstrap CSS cho ứng dụng, đầu tiên chúng ta sẽ thêm Bootstrap cdn vào file index.html. Đến file public/index.htmlvà thêm bootstrap cdn.

<!DOCTYPE html>
<html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width,initial-scale=1" /> <title>Svelte app</title> <link rel="icon" type="image/png" href="/favicon.png" /> <link rel="stylesheet" href="/global.css" /> <link rel="stylesheet" href="/build/bundle.css" /> <!-- boostarp cdn starts here --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous" /> <!-- bootstrap cdn ends here --> <script defer src="/build/bundle.js"></script> <style> body { background: #f2f4f8; } </style> </head> <body></body>
</html>

Cập nhật file stores/stores.js

import { writable } from 'svelte/store' export const cart = writable({})

Ở đoạn code trên, chúng ta import writable() function từ svelte/store và sử dụng nó để tạo một store gọi cart. Mở file src/items.js và cập nhật như sau:

export default [ { name: 'laptop', price: '500', img: 'laptop1.png' }, { name: 'Latest PC', price: '1,000', img: 'mobile1.png' }, { name: 'Latest laptop', price: '1000', img: 'laptop2.png' }, { name: 'latest smart watch', price: '5,000,000', img: 'smartwatch.png' }, { name: 'Monitor', price: '2000', img: 'display.png' }, { name: 'playstation', price: '2,670', img: 'playstation.png' }
]

Building the Cards Components

Mở file src\CartComponents\card.svelte và update nộ dung.

<script> import { get } from "svelte/store"; import { cart } from "../Stores/stores.js"; export let item; let { img, name, price } = item; img = `img/${img}`; const cartItems = get(cart); let inCart = cartItems[name] ? cartItems[name].count : 0; function addToCart() { inCart++; cart.update(n => { return { ...n, [name]: { ...item, count: inCart } }; }); }
</script> <div class="card"> <img class="card-img-top" width="200" src={img} alt={name} /> <div class="card-body"> <h5 class="card-title">{name}</h5> <b class=alert alert-info > $ {price}</b> <p class=alert alert-info >{#if inCart > 0} <span> <em>({inCart} in cart)</em> </span> {/if}</p> </div> <div class="btn-group" role="group"> <button type="button" class="btn btn-primary" on:click={addToCart}> <object aria-label="shopping cart" type="image/svg+xml" data="img/svg/shopping-cart.svg" /> Add to cart </button> </div> </div>

Ở đoạn mã trên chúng ta đã import get() từ svelte/store. Nó sử dụng getset một cách thủ công. Cập nhật file src\CartComponents\CardWrapper.svelte

<script> import Card from "./Card.svelte"; import items from "../items.js";
</script> <div class="container"> <div class="row"> {#each items as item} <div class="col-md-4"> <Card {item} /> </div> {/each} </div> </div> 

Trong đoạn mã trên chúng ta đã import Card.svelte & item.js đã tạo trước đó để sử dụng và hiển thị cho các thẻ sử dụng Bootsrap class.

Working with the Checkout Components

Cập nhật file src\CartComponents\CheckoutItem.svelte

<script> import { cart } from "../Stores/stores.js"; export let item; let { name, price, img, count } = item; const countButtonHandler = (e) => { if (e.target.classList.contains("add")) { count++; } else if (count >= 1) { count--; } cart.update((n) => ({ ...n, [name]: { ...n[name], count } })); }; const removeItem = () => { cart.update((n) => { delete n[name]; return n; }); };
</script> <div class="row"> <img class="img-fluid img-thumbnail" width="300" src={`img/${img}`} alt={name} /> <div class="item-meta-data"> <h3 class="title">{name}</h3> <p class="price">Price: $ {price}</p> <div class="col"> <button type="button" class="btn btn-success add" on:click={countButtonHandler}>+</button > {" "} <span>{count}</span> {" "} <button type="button" class="btn btn-warning" on:click={countButtonHandler}>-</button > {" "} <button type="button" class="btn btn-danger" on:click={removeItem}> <object aria-label="remove" type="image/svg+xml" data="img/svg/cancel.svg" /> Remove </button> </div> </div>
</div> 

Trong đoạn code trên chúng ta đã viết 1 logic đơn giản trả lại các Items cho cart. Kiểm tra checked-out cho mỗi cart và hiển thị message theo điều kiện thảo mãn.

Tiếp theo chúng ta cập nhật file src\CartComponents\Navbar.svelte

<script> import { cart } from "../Stores/stores.js"; import { createEventDispatcher } from "svelte"; const dispatch = createEventDispatcher(); let cart_sum = 0; const unsubscribe = cart.subscribe(items => { const itemValues = Object.values(items); cart_sum = 0; itemValues.forEach(item => { cart_sum += item.count; }); }); function goToHome() { dispatch("nav", { option: "home" }); } function goToCheckout() { dispatch("nav", { option: "checkout" }); } </script> <nav class="navbar navbar-dark bg-primary navbar-expand-lg navbar-dark "> <div class="container"> <a class="navbar-brand logo-font" id="brand" on:click={goToHome}> SvelteCart </a> <!-- links toggle --> <button class="navbar-toggler order-first" type="button" data-toggle="collapse" data-target="#links" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation"> <i class="fa fa-bars"></i> </button> <!-- account toggle --> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#account" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation"> <i class="fa fa-shopping-cart fa-1x" aria-hidden="true"></i> <span class="badge badge-light">88</span> </button> <div class="collapse navbar-collapse" id="links"> <ul class="navbar-nav mr-auto"> <li class="nav-item"> <a class="nav-link" href="#"> Electronics</a> </li> <li class="nav-item"> <a class="nav-link" href="#">customer care</a> </li> </ul> </div> <div class="collapse navbar-collapse" id="account"> <ul class="navbar-nav ml-auto"> <li class="nav-item active"><a class="nav-link" on:click={goToCheckout}>Items in Cart <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-cart-dash-fill" viewBox="0 0 16 16"> <path d="M.5 1a.5.5 0 0 0 0 1h1.11l.401 1.607 1.498 7.985A.5.5 0 0 0 4 12h1a2 2 0 1 0 0 4 2 2 0 0 0 0-4h7a2 2 0 1 0 0 4 2 2 0 0 0 0-4h1a.5.5 0 0 0 .491-.408l1.5-8A.5.5 0 0 0 14.5 3H2.89l-.405-1.621A.5.5 0 0 0 2 1H.5zM6 14a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm7 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zM6.5 7h4a.5.5 0 0 1 0 1h-4a.5.5 0 0 1 0-1z"/> </svg> </a></li> <li class="nav-link active"> {#if cart_sum > 0} {cart_sum} {/if} </li> </ul> </div> </div>
</nav> <br> 

Trong đoạn mã trên chúng ta đã import createEventDispatcher funtion từ svelte package và gọi một event dispatcher. Cuối cùng update file App.svelte

<script> import CardWrapper from "./CartComponents/CardWrapper.svelte"; import Navbar from "./cartComponents/Navbar.svelte"; import Checkout from "./CartComponents/Checkout.svelte"; let nav = "home"; function navHandler(event) { nav = event.detail.option; } </script> <Navbar on:nav={navHandler} /> {#if nav === 'home'} <CardWrapper /> {:else} <Checkout /> {/if}

Ở trên đoạn mã trên chúng ta đã nhập tất cả các thành phần cần thiết để tạo ra App.svelte file.

Conclusion

Svelte là một sự thay thế xứng đáng cho các tùy chọn phổ biến hiện nay của React, Vue và Angular. Nó có nhiều lợi ích, bao gồm kích thước gói nhỏ, định nghĩa thành phần đơn giản, quản lý trạng thái dễ dàng và khả năng phản ứng mà không cần DOM ảo. Qua bài hướng dẫn này bạn đã học được cách để xây dụng một ứng dụng giỏ hàng đơn giản bằng Svelte. Bạn có thểm tham khảo source code tại đây: GitHub.

References

https://en.wikipedia.org/wiki/Svelte

https://svelte.dev/docs

https://codesource.io/building-an-ecommerce-shopping-cart-with-svelte/

Bình luận

Bài viết tương tự

- vừa được xem lúc

Giới thiệu Typescript - Sự khác nhau giữa Typescript và Javascript

Typescript là gì. TypeScript là một ngôn ngữ giúp cung cấp quy mô lớn hơn so với JavaScript.

0 0 500

- vừa được xem lúc

Bạn đã biết các tips này khi làm việc với chuỗi trong JavaScript chưa ?

Hi xin chào các bạn, tiếp tục chuỗi chủ đề về cái thằng JavaScript này, hôm nay mình sẽ giới thiệu cho các bạn một số thủ thuật hay ho khi làm việc với chuỗi trong JavaScript có thể bạn đã hoặc chưa từng dùng. Cụ thể như nào thì hãy cùng mình tìm hiểu trong bài viết này nhé (go).

0 0 414

- vừa được xem lúc

Một số phương thức với object trong Javascript

Trong Javascript có hỗ trợ các loại dữ liệu cơ bản là giống với hầu hết những ngôn ngữ lập trình khác. Bài viết này mình sẽ giới thiệu về Object và một số phương thức thường dùng với nó.

0 0 136

- vừa được xem lúc

Tìm hiểu về thư viện axios

Giới thiệu. Axios là gì? Axios là một thư viện HTTP Client dựa trên Promise.

0 0 117

- vừa được xem lúc

Imports và Exports trong JavaScript ES6

. Giới thiệu. ES6 cung cấp cho chúng ta import (nhập), export (xuất) các functions, biến từ module này sang module khác và sử dụng nó trong các file khác.

0 0 93

- vừa được xem lúc

Bài toán đọc số thành chữ (phần 2) - Hoàn chỉnh chương trình dưới 100 dòng code

Tiếp tục bài viết còn dang dở ở phần trước Phân tích bài toán đọc số thành chữ (phần 1) - Phân tích đề và những mảnh ghép đầu tiên. Bạn nào chưa đọc thì có thể xem ở link trên trước nhé.

0 0 229