Hướng Dẫn Xây Dựng TodoApp Full-Stack với Node.js, Express, MongoDB và EJS
Todo Application là một trong những ứng dụng web đơn giản nhất mà hầu hết các lập trình viên web bắt đầu hành trình của họ với. Tuy nhiên, nhiều ứng viên lại gặp khó khăn khi thực hiện nó. Ứng dụng đơn giản này chứa nhiều chủ đề và khái niệm quan trọng mà bạn cần hiểu trước khi tham gia vào sự phức tạp của việc phát triển ứng dụng web cho người dùng đại chúng.
Nội Dung Chính
Trong hướng dẫn này, chúng ta sẽ tập trung vào các khái niệm như:
- Mongoose (MongoDB) để lưu trữ dữ liệu.
- Handlers cho việc render phía server.
- Khái niệm module.exports.
- Các chức năng CRUD cơ bản để làm cho ứng dụng hoạt động.
Tính Năng Của Ứng Dụng
Trước khi bắt đầu với phần mã, điều quan trọng là phải hiểu cách hoạt động và các tính năng của ứng dụng:
- Thêm một todo vào ứng dụng todo.
- Lấy tất cả các todo trên trình duyệt.
- Xóa một todo khỏi danh sách todo.
- Lấy một todo duy nhất trên trình duyệt.
Ứng dụng cần có một cơ sở dữ liệu để lưu trữ các todo mà chúng ta sẽ thêm vào, vì vậy chúng ta sẽ sử dụng MongoDB - Mongoose.
MongoDB
MongoDB là một sản phẩm cơ sở dữ liệu NoSQL cho việc lưu trữ dữ liệu dưới dạng BSON, một định dạng tương tự JSON. Để lưu trữ dữ liệu, bạn cần tải MongoDB từ trang chính thức theo sự tương thích của hệ thống của bạn.
Cài Đặt MongoDB
Trước khi có thể lưu trữ dữ liệu, bạn cần thiết lập server MongoDB. Bạn cần tạo một thư mục trong thư mục dự án của bạn, đặt tên là data, sau đó trong terminal viết:
mongod --dbpath=data
Sau khi chạy lệnh này, hãy kiểm tra xem MongoDB có đang chạy hay không bằng cách vào trình duyệt và nhập URL: http://localhost:27017. Nếu nó hoạt động, bạn sẽ thấy một thông báo xác nhận.
Mongoose
Mongoose là một thư viện lập trình hướng đối tượng JavaScript giúp tạo kết nối giữa MongoDB và môi trường runtime JavaScript Node.js. Về cơ bản, nó là một ODM (Object Data Modelling), trong đó tất cả mọi thứ được lưu trữ dưới dạng đối tượng.
Khởi Động Server
Để bắt đầu server, trong terminal, bạn cần chạy:
npm init -y
npm install express
npm install mongoose
Tạo một file JavaScript trong thư mục dự án. Bây giờ, chúng ta cần tạo một kết nối giữa MongoDB và file JavaScript của chúng ta.
Tạo Schema với Mongoose
Để sử dụng Mongoose, chúng ta cần các models (bộ sưu tập), được tạo ra với sự trợ giúp của schema. Mọi thứ trong Mongoose bắt đầu bằng một Schema. Mỗi schema ánh xạ đến một bộ sưu tập MongoDB và định nghĩa hình dạng của các tài liệu trong bộ sưu tập đó.
Trong ứng dụng của chúng ta, chúng ta sẽ tạo một schema cho một Todo với các thuộc tính:
- taskName
- Description
- Id (được tự động tạo bởi MongoDB, không cần chỉ định)
Nên tách biệt các chức năng khác nhau của dự án, vì vậy chúng ta sẽ tạo schema trong một file JavaScript mới được lưu trữ trong thư mục model.
Tại đây, trong đối tượng schema, chúng ta khai báo một đối tượng dữ liệu dưới dạng cặp key:value, trong đó mỗi key có một đối tượng với kiểu dữ liệu và thuộc tính required: true, nghĩa là bắt buộc phải cung cấp dữ liệu, nếu không sẽ xảy ra lỗi.
Khái Niệm module.exports
Trong Node.js, module.exports là một đối tượng đặc biệt có sẵn trong mọi file JavaScript. Nó cho phép bạn xuất ra các chức năng cụ thể (như hàm, đối tượng, lớp hoặc giá trị nguyên thủy) từ một module, làm cho chúng có thể truy cập từ các module khác trong ứng dụng của bạn.
Chúng ta có thể sử dụng file Todos.js và mongoose.model trong bất kỳ file JavaScript nào khác mà chúng ta cần.
Sử Dụng Handlebars (hbs)
Để hiển thị dữ liệu trên trình duyệt, chúng ta sẽ sử dụng handlebars - hbs. Khi sử dụng để phục vụ file tĩnh, dữ liệu được gửi đến trình duyệt theo cách lẻ tẻ (tức là một ít dữ liệu được gửi theo yêu cầu) với sự trợ giúp của middleware app.use(express.static()), nhưng cách này không hiệu quả trong việc viết mã backend.
Do đó, chúng ta sử dụng SERVER SIDE RENDERING - gửi toàn bộ file một lần với sự trợ giúp của handlebars. Điều này giúp chúng ta gửi file index một lần và nó được sử dụng dưới dạng file .hbs. Với điều này, file HTML không chỉ được tạo ra trên backend mà chúng ta cũng có thể sử dụng các biến JavaScript trong file.
Cài Đặt Handlebars
Để cài đặt Handlebars, bạn cần chạy:
npm install hbs
Chúng ta có thể truy cập file .hbs trong file JS với sự trợ giúp của res.render, đây là một phản hồi mà khách hàng nhận được file index.hbs:
res.render('index')
Để sử dụng handlebars trong file JavaScript của chúng ta, chúng ta cần thiết lập nó bằng cách:
app.set('view engine','hbs')
Bây giờ, trong file package.json, các dependencies sẽ trông giống như sau:
Tiếp theo, tạo một thư mục trong thư mục dự án với tên views, nơi sẽ chứa tất cả các file .hbs của chúng ta. Tạo file index.hbs sẽ được gửi đến khách hàng và một file error.hbs nếu có sự cố xảy ra ở backend.
Cùng lúc, tạo một thư mục static để chứa file style.css và phải yêu cầu tất cả các file này.
Giao Diện Ứng Dụng
Người dùng có thể tạo ứng dụng của họ với nhiều sự sáng tạo, nhưng ở đây, chúng ta sẽ giữ nó đơn giản để tập trung vào chức năng.
Trong file index.hbs, chúng ta sẽ tạo một mẫu đơn giản cho ứng dụng, sử dụng thẻ <form> để giúp chúng ta thêm các todo mới và thẻ <ul> để hiển thị các todo đã tạo trên trình duyệt.
Thẻ <form> sẽ có <input> để thêm tên nhiệm vụ và mô tả. Nút gửi sẽ thêm todo vào cơ sở dữ liệu của chúng ta thông qua thuộc tính action trong form, định tuyến đến đường dẫn URL đã cho.
Tuy nhiên, ứng dụng vẫn là một ứng dụng tĩnh mà không có khả năng thực hiện bất kỳ chức năng nào. Vậy nên, chúng ta sẽ triển khai chức năng CRUD để làm cho ứng dụng trở nên hữu ích.
Phần Backend Của Ứng Dụng
Thêm một todo vào ứng dụng
Khi chúng ta nhấn “THÊM TODO” trên trang web sau khi thêm tên nhiệm vụ và mô tả, những gì xảy ra là:
- Để thêm bất kỳ loại dữ liệu nào, chúng ta sử dụng yêu cầu
POST. - Chúng ta sẽ thêm dữ liệu với sự trợ giúp của form mà chúng ta đã tạo trong file
index.hbs, vớiactiongiúp chúng ta có một đường dẫn của yêu cầu POST. - Đường dẫn này sẽ có yêu cầu POST được viết trong file
app.js. - Đối với yêu cầu POST trong
app.js, chúng ta gọi đếntodoFun.jsmột cách bất đồng bộ cho hàmaddTodo. addTodosẽ thực hiện chức năng thêm một todo vào cơ sở dữ liệuTodosvà trả về thông báo nếu thực hiện thành công.- Cuối cùng, yêu cầu sẽ được chuyển hướng về đường dẫn cơ sở.
- Todo mới sẽ được thêm vào cơ sở dữ liệu mà chúng ta có thể xem qua “MongoDB Compass”.
Lấy tất cả các todo trên trình duyệt
Để lấy tất cả các todo, chúng ta chỉ cần lấy tất cả các todo trong cơ sở dữ liệu và gửi nó đến trang index.hbs để hiển thị trên trang với sự trợ giúp của danh sách.
- Khi một yêu cầu
GETđược thực hiện trên đường dẫn cơ sở (/), hàmgetTodo()được gọi trong filetodoFun.jsmột cách bất đồng bộ. - Hàm
getTodo()sẽfind()tất cả các todo từ cơ sở dữ liệu bằng cách sử dụng hàmfindcủa mongoose và sau đó trả về cho yêu cầu GET nơi nó được gọi từ. - Sau đó, các todo mà chúng ta nhận được sẽ được gửi đến file
index.hbsdưới dạng một đối tượng bằng yêu cầures.render.
Trong file index.hbs, không chỉ hiển thị một danh sách mà còn cho phép chúng ta sử dụng các biến JavaScript và hoạt động như “for each loops” và “if conditions” với cú pháp “moustache”.
Xóa một todo khỏi danh sách
Khi chúng ta nhấn nút xóa, yêu cầu GET sẽ được chuyển đến “đường dẫn xóa”.
- Với sự trợ giúp của
req.params, chúng ta de-structureidmà là duy nhất cho mỗi todo. - Sau đó, chúng ta gọi hàm
delTodo(id)từ filetodoFun.js. - Hàm này sẽ xóa todo bằng cách sử dụng hàm
Todos.deleteOne()của mongoose bằng cách so khớp với id. - Cuối cùng, yêu cầu sẽ được chuyển hướng đến đường dẫn cơ sở.
Lấy một todo trên trình duyệt
Để lấy một todo duy nhất từ tất cả các todo:
- Khi chúng ta nhấp vào todo mà mình chọn, nó sẽ chuyển hướng đến một trang mới chỉ chứa todo đó.
- Điều này khả thi vì mỗi todo có một id duy nhất được cung cấp bởi MongoDB, giúp server xác định todo mà khách hàng cần.
- Khi nhấp vào todo (vì tất cả các todo được lưu trữ trong thẻ anchor, chúng có đường dẫn
href), nó sẽ chuyển hướng yêu cầuGETđến đường dẫn/todo/:id. - Tại đây, chúng ta sẽ lấy id của một todo đó bằng cách sử dụng
req.paramsvà sau đó gọi hàmgetTodotừ filetodoFun. - Hàm này sẽ tìm một todo bằng cách sử dụng hàm
Todos.findOne()trong cơ sở dữ liệu với id tương ứng và trả về nó.
Kết Luận
Như vậy, ứng dụng Todo của chúng ta đã sẵn sàng với một cơ sở dữ liệu vĩnh viễn giúp chúng ta thực hiện các thao tác CRUD cơ bản để có thể theo dõi danh sách todo của mình.
Hy vọng hướng dẫn này hữu ích cho bạn. Nếu bạn muốn xem toàn bộ mã nguồn, hãy truy cập đường dẫn GitHub.
Câu Hỏi Thường Gặp (FAQ)
1. Tôi cần gì để bắt đầu với ứng dụng Todo này?
Bạn cần cài đặt Node.js, MongoDB và các package cần thiết.
2. Làm thế nào để thêm một todo mới?
Bạn chỉ cần điền thông tin vào form và nhấn nút “THÊM TODO”.
3. Làm thế nào để xem tất cả todos?
Tất cả todos sẽ được hiển thị trên trang chính sau khi bạn thêm chúng.
4. Tôi có thể xóa một todo không?
Có, bạn có thể xóa todo bằng cách nhấn nút xóa tương ứng.
5. Ứng dụng này có thể mở rộng không?
Có, bạn có thể thêm nhiều tính năng khác như chỉnh sửa todo, tìm kiếm, phân loại, v.v.