0% found this document useful (0 votes)
7 views

Full Stack

web note

Uploaded by

paypal23573609
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views

Full Stack

web note

Uploaded by

paypal23573609
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 100

Node JS:

1. Node JS Dùng Để Làm Gì?


 Chạy File JS không cần sử dụng trình duyệt Web
2. Show Mô Tả Của Lệnh Node?
node -h
3. Show Phiên Bản Của Node?
node -v
4. Chạy 1 File JS Như Chạy 1 File Python?
node <Đường Dẫn Tới File JS Không Cần Phần Mở Rộng>
 Khi chạy lệnh trên, thực chất là bạn đang chạy node.exe, để ý trong Task Manager sẽ có
Process tên lầ node.exe, và File JS của bạn được đọc và chạy từng dòng trong môi
trường node.exe này, khi chạy, nó có thể chiếm giữ các Port, và do đó node.exe chỉ đóng
khi nó không chiếm Port nào nữa và chạy xong File JS và tất cả Promise đều được
Fulfilled hoặc Rejected, nếu cố tình đóng node.exe thì nó cũng sẽ trả tự do cho các Port
 File JS sẽ được chạy với tư cách là 1 Module, cụ thể là Common hay ECMA sẽ tùy thuộc
vào File "package.json" ở thư mục làm việc hiện tại, nếu File này có thuộc tính "type" là
"module" thì chạy với tư cách ECMA Module, còn không thì là Common Module
 File với phần mở rộng ".mjs" y chang JS, nhưng khi nó được chạy thì luôn chạy với tư
cách 1 ECMA Module, nếu dùng Node chạy File MJS thì cần phần mở rộng
 Tương tự File với phần mở rộng ".cjs" y chang JS, nhưng luôn chạy với tư cách Common
Module
 Khi 1 File JS chạy với tư cách 1 Module, thì nó mặc định ở trong Strict Mode, ngược lại
thì không ở trong Strict Mode, để chủ động chỉ định 1 đoạn Code sẽ chạy trong Strict
Mode, phải đặt "use strict" lên đầu Scope tương ứng, nếu đặt ở giữa sẽ vô dùng, ví dụ
{
"use strict"
var b = 6
a = 5 // đoạn này bình thường không lỗi, nhưng giờ sẽ lỗi
}
5. Cài Đặt Thư Viện?
npm install
 Khi chạy lệnh trên, nó sẽ dò trong thư mục làm việc hiện tại xem có File "package.json"
không, nếu không có hoặc có nhưng cấu trúc File không hợp lệ sẽ báo lỗi, ngược lại, thì
nó sẽ tiếp tục dò xem trong thư mục làm việc hiện tại có File "package-lock.json" không,
nếu có và cấu trúc hợp lệ, thì nó sẽ đối chiếu giữa 2 File "package.json" và "package-
lock.json", nếu 2 File này tương thích thì sau đó nó sẽ dựa vào "package-lock.json" để tải
về các thư viện cần thiết, bạn sẽ thấy có 1 thư mục "node_modules" sẽ được tạo ra
trong thư mục làm việc hiện tại, mỗi thư mục con bên trong nó là 1 thư viện được tải về,
tên thư mục con = tên thư viện, ví dụ bản tải về thư viện A, thư viện A lại phụ thuộc vào
B, C, D, thì trong "node_modules" sẽ có "A", "B", "C", "D", nếu đã tải rồi thì không tải
nữa, nhưng nếu phiên bản cũ rồi thì vẫn bị ghi đè, trường hợp không có File "package-
lock.json" hoặc nó không có cấu trúc hợp lệ hoặc không tương thích với "package.json",
thì sẽ tạo ra File "package-lock.json" mới dựa theo "package.json", và vẫn dựa vào File
mới này để tải thư viện
 Cấu trúc hợp lệ của "package.json" như sau
{
"dependencies": {
<Tên Thư Viện 1>: <Phiên Bản 1>,
<Tên Thư Viện 2>: <Phiên Bản 2>,

},
"devDependencies": {
<Tên Thư Viện Dev 1>: <Phiên Bản Dev 1>,
<Tên Thư Viện Dev 2>: <Phiên Bản Dev 2>,

}
<Các Thuộc Tính Khác>
}
 <Phiên Bản> phải được ghi theo cơ chế Semantic Versioning, có thể có các tiền tố, ví dụ
{
"dependencies": {
"express": "^4.19.2",
"nodemon": "~3.1.3",
"foo": "1.2.3"
}
}
 Như vậy File "package.json" sẽ liệt kê các thư viện chính mà chúng ta cần, kèm theo điều
kiện về phiên bản của nó, ví dụ ^4.19.2, là sẽ tải về phiên bản mới nhất sao cho bé hơn
5.0.0
 Cấu trúc hợp lệ của File "package-lock.json"
{
"name": <Tên Dự Án>,
<Các Thuộc Tính Khác>,
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"dependencies": {
<Giống "dependencies" Trong "package.json">
},
"devDependencies": {
<Giống "devDependencies" Trong "package.json">
}
},
"node_modules/<Tên Thư Viện 1>": {
"version": <Phiên Bản Chính Xác 1>,
"resolved": <Đường Link Tải File Nén Thư Viện Này 1>,
"integrity": <Mã Hash Của Thư Viện 1>,
<Các Thuộc Tính Khác 1>
},
"node_modules/<Tên Thư Viện 2>": {
"version": <Phiên Bản Chính Xác 2>,
"resolved": <Đường Link Tải File Nén Thư Viện Này 2>,
"integrity": <Mã Hash Của Thư Viện 2>,
<Các Thuộc Tính Khác 2>
},

}
}
 <Tên Dự Án> = thuộc tính "name" của File "package.json", nếu không có thuộc tính này,
thì = tên thư mục làm việc hiện tại
 <Các Thuộc Tính Khác> sẽ có thuộc tính "version" và = thuộc tính "version" trong File
"package.json", nếu trong File "package.json" không có thuộc tính "version" thì thôi
 Dễ thấy, File "package-lock.json" liệt kê toàn bộ các thư viện sẽ được tải về, bao gồm cả
thư viện chính và các thư viện mà các thư viện chính này phụ thuộc, nghĩa là tất cả các
thư viện được liệt kê ở đây sẽ có trong thư mục "node_modules"
 <Các Thuộc Tính Khác> có thể bao gồm cả "dependencies", tức thư viện này lại phụ
thuộc thư viện khác
 Lí do sử dụng File "package-lock.json" là vì, giả sử không có nó, mà chỉ có "package.json",
thì khi chạy npm install, ở những thời điểm khác nhau, thì rất có thể sẽ tải về những thư
viện ở phiên bản khác nhau, ví dụ bản chỉ định sẽ tải thư viện Express với phiên bản
^4.0.0 ở File "package.json", thì buổi sáng khi bạn chạy npm install, thì có thể nó sẽ tải
phiên bản mới nhất là 4.9.2, thỏa mãn < 5.0.0, nhưng buổi chiều, đồng nghiệp của bạn
Clone dự án về rồi npm install, lại tải trúng phiên bản 4.9.3, là phiên bản mới nhất lúc
đó, như vậy 2 người sẽ phải Code ở 2 phiên bản khác nhau, không thống nhất, kể cả việc
bạn bỏ tiền tố trước chuỗi phiên bản ở File "package.json", thì các thư viện chính này
cũng sẽ phụ thuộc vào các thư viện khác, và chúng có tiền tố, ví dụ thư viện Express phụ
thuộc vào thư viện A, yêu cầu phiên bản ~1.2.3, bạn đã chỉ định tải chính xác Express
4.9.2, nhưng ai ngờ nó tải A phiên bản 1.2.4 vào buổi sáng, vào buổi chiều thì lại tải
phiên bản 1.2.5, như vậy là các thư viện ở trung gian không thống nhất, điều này đã
được giải quyết bằng File "package-lock.json", khi lần đầu chưa tạo File này, thì nó sẽ
dựa vào "package.json" để xác định chính xác các phiên bản mới nhất sao cho thỏa mãn
các yêu cầu, <Phiên Bản Chính Xác> không có tiền tố, sự tương thích giữa "package-
lock.json" và "package.json" chính là các <Phiên Bản Chính Xác> thỏa mãn điều kiện về
phiên bản trong các "dependencies", ví dụ <Phiên Bản Chính Xác> = 1.2.5, thỏa mãn
~1.2.3, cho dù 1 thời gian lâu sau đó nữa, nó đã ra phiên bản 1.2.9, thì vẫn dùng 1.2.5,
do nó vẫn thỏa mãn với ~1.2.3
 Như vậy File "package-lock.json" sẽ không thay đổi khi File "package.json" không thay
đổi, dẫn đến phiên bản các thư viện được tải về là cố định tại mọi thời điểm
 Cách sử dụng tiền tố trước số phiên bản
Cú pháp
Chấp nhận phiên bản từ <Phiên Bản> trở
lên, nhưng chỉ thay đổi số bản vá, ví dụ
~<Phiên Bản>
~1.2.3 thì 1.2.5 hợp lệ nhưng 1.3.0 không
hợp lệ
Chấp nhận phiên bản từ <Phiên Bản> trở
lên, nhưng chỉ thay đổi số bản vá và bản
^<Phiên Bản>
nhỏ, ví dụ ^1.2.3 thì 1.2.5, 1.4.8 hợp lệ,
nhưng 2.0.0 thì không hợp lệ
Chấp nhận phiên bản = chính xác <Phiên
<Phiên Bản>
Bản>
Ví dụ >=1.2.3, tức chấp nhận phiên bản
<Dấu So Sánh><Phiên Bản>
lớn hơn hoặc bằng 1.2.3, như 1.2.8
Chấp nhận x từ 0 tới giá trị lớn nhất có
<Bản Lớn>.<Bản Nhỏ>.x thể, ví dụ 1.2.x thì 1.2.0 đến 1.2.13 hợp lệ,
giả sử sau 1.2.13 là 1.3.0
* Chấp nhận mọi phiên bản
Tải lần đầu thì tải phiên bản mới nhất,
latest
nhưng chấp nhận mọi phiên bản sau đó
 Bạn có thể chỉ định tải thêm 1 thư viện và đặt nó vào "dependencies"
npm install <Tên Thư Viện>
 Khi này nếu trong "package.json" chưa có <Tên Thư Viện> trong "dependencies" thì sẽ
thêm vào, phiên bản mới nhất, tiền tố ^ ở đầu, cập nhật "package-lock.json" và tải thư
viện này, còn nếu đã có <Tên Thư Viện> và phiên bản của nó có ^ ở đầu, thì đổi lên
phiên bản mới nhất thỏa mãn không thay đổi bản lớn, nếu phiên bản không có tiền tố
thì chỉ thêm ^, các trường hợp khác giữ nguyên phiên bản, và nếu "package-lock.json"
đã thỏa mãn điều kiện thì không tải, ngược lại thì làm mới "package-lock.json" và tải
 Bạn có thể tải 1 lúc thêm nhiều thư viện, ví dụ
npm install express nodemon
 Để tải và đặt vào "devDependencies" nếu chưa tải
npm install <Tên Thư Viện> --save-dev
 Lệnh sau tương tự npm install, chỉ có điều nó sẽ báo lỗi thay vì tạo mới File "package-
lock.json" nếu File này không tồn tại hoặc không tương thích với File "package.json",
đồng thời nó sẽ xóa thư mục "node_modules" rồi tải lại từ đầu
npm ci
 Lệnh sau tương tự npm install, nhưng sẽ không tải các thư viện trong
"devDependencies" vào thư mục "node_modules"
npm install --omit=dev
 Có thể sử dụng cờ i thay cho install, ví dụ
npm i express
 Để gỡ cài đặt 1 thư viện, xóa nó khỏi "devDependencies" và cả "dependencies"
npm uninstall <Tên Thư Viện>
 Để cài đặt toàn cục thì thêm cờ -g, tức trong thư mục "C:\Users\<Tên Người Dùng>\
AppData\Roaming\npm\node_modules" sẽ có thư mục với tên là <Tên Thư Viện>, phần
thư viện phụ thuộc sẽ ở trong thư mục con "node_modules" của thư mục <Tên Thư
Viện>, ví dụ
npm install express -g
 Nếu thư viện mà có File lệnh với phần mở rộng ".cmd", thì trong thư mục "C:\Users\
<Tên Người Dùng>\AppData\Roaming\npm" sẽ có File này, ví dụ như Nodemon
 Để gỡ cài đặt toàn cục thì cũng thêm cờ -g
 Giả sử có 1 thư viện, thư viện này có File ".cmd", ví dụ thư viện Create React App, bạn
đéo muốn tải thư viện này, mà chỉ muốn dùng File ".cmd" của nó chạy 1 lần duy nhất, thì
sử dụng lệnh sau, nó sẽ tải thư viện nếu chưa có trong bộ đệm và chạy File ".cmd" của
thư viện, sau đó sẽ lưu trong bộ đệm nếu chưa lưu, bộ đệm đầy thì sẽ xóa
npx <Tên Thư Viện> <Các Đối Số Cho File CMD>
 Ví dụ
npx nodemon haha.js
6. Liệt Kê Các Thư Viện Lỗi Thời?
 Để liệt kê các thư viện có phiên bản quá cũ, dẫn đến các đối tượng xấu có thể lợi dụng
npm audit
 Để cập nhật tất cả thư viện để chúng khỏi lỗi thời
npm audit fix --force
7. Khởi Tạo Package?
 Để khởi tạo File "package.json" nhanh chóng, dùng lệnh
npm init
 Sau đó lần lượt nhập thuộc tính "name", "version", "description", "main", "scripts" /
"test", "repository" / "url", "keywords", "author", "license"
 Thuộc tính "keywords" bạn sẽ nhập các chuỗi ngăn cách bởi dấu phẩy, nó sẽ là 1 mảng
 Thuộc tính "license" không cần nhập gì hết nó tự động = "ISC"
 Ví dụ nội dung File "package.json" sau khi nhập
{
"name": "thonglon",
"version": "2.1.2",
"description": "motacailon",
"main": "chamhoi",
"scripts": {
"test": "gaga"
},
"repository": {
"type": "git",
"url": "sss"
},
"keywords": [
"sfasf",
"fsfs"
],
"author": "ghaha",
"license": "ISC"
}
8. Import Thư Viện?
 Cách viết dưới đây chỉ áp dụng cho trường hợp File JS được chạy với tư cách Common
Module
 Ở File chứa thứ cần mượn thì thêm dòng Code này vào chỗ nào sao cho hợp lí
module.exports = <Bất Kể Thứ Gì>
- <Bất Kể Thứ Gì> là 1 giá trị thuộc kiểu dữ liệu bất kì
 Ở File mượn thì nếu muốn sử dụng <Bất Kể Thứ Gì> do File chứa thứ cần mượn Export
ra, thì sử dụng hàm
require(<Đường Dẫn Đến File Chứa Thứ Cần Mượn>)
- <Đường Dẫn Đến File Chứa Thứ Cần Mượn> phải có phần mở rộng, có thể tương đối
hoặc tuyệt đối, không phân biệt dấu / và \, nếu là đường dẫn tương đối đến File ở cùng
thư mục hoặc cấp thấp hơn, phải có ./ hoặc .\ ở đầu, nếu đường dẫn dẫn tới 1 thư mục,
thì tương đương dẫn tới File "index.js" có trong thư mục đó
- Lệnh trên sẽ chạy File được chỉ định với tư cách 1 Module, Common hay ECMA thì tùy
thuộc vào nó là JS, MJS hay CJS, nếu nó là ECMA thì lỗi, ngược lại chạy từ đầu đến cuối,
mỗi lần gặp lệnh module.exports = <Giá Trị> là nó lại gán lại <Giá Trị> vào kết quả cuối
cùng, nghĩa là module.exports có thể chạy nhiều lần, lấy lần cuối, nếu bạn tiếp tục
require cùng 1 File 2 lần, thì lần thứ 2 trở đi File được require không chạy, mà lấy cái kết
quả cuối cùng của lần chạy đầu tiên để trả về
 Ví dụ
- Ở File chứa thứ cần mượn
module.exports = [1, 2, 3]
- Ở File mượn
const foo = require("./ggnore.js")
- Khi này foo = [1, 2, 3]
 Chú ý nếu sử dụng cú pháp sau
require(<Tên Thư Viện>)
- Ví dụ
require("express")
- Thì máy sẽ vào thư mục "node_modules" trong thư mục làm việc hiện tại, tìm thư mục
có tên <Tên Thư Viện> và trả về thứ được Export ra trong File "index.js" ở thư mục này
 Cách viết dưới đây chỉ áp dụng cho File JS được chạy với tư cách ECMA Module
 Mỗi File sẽ có thể Export ra nhiều giá trị, trong đó chỉ có nhiều nhất là 1 giá trị mặc định,
còn lại là giá trị thường
 Cơ chế Import Export y chang module.exports, tức là khi Import 1 File nhiều lần, thì chỉ
chạy từ đầu tới cuối 1 lần kể cả khi bạn Import những giá trị khác nhau trong những lần
khác nhau, giá trị Export được lưu cho những lần sau và không đổi, đường dẫn cú pháp
tương tự, nếu đường dẫn đến thư mục thì tương đương đến File "index.js" bên trong
 Để Export giá trị mặc định
export default <Giá Trị>
- Ví dụ
export default () => {}
 Để Export giá trị thường
export <Lệnh Khai Báo Và Khởi Tạo Giá Trị>
- <Lệnh Khai Báo Và Khởi Tạo Giá Trị> phải có tên, như tên biến, tên hàm, cái tên này sẽ
được thêm vào danh sách các giá trị Export thường của File
- Ví dụ
export function foo(){}
export const a = 5
 Để Import giá trị mặc định từ 1 File
import <Tên Bất Kì> from <Đường Dẫn>
- <Tên Bất Kì> là do bạn đặt để lưu giá trị mặc định được Export ra
- Ví dụ
import hahanore from "./bar/alice.js"
 Để Import 1 hoặc nhiều giá trị thường từ 1 File
import {<Một Số Giá Trị Thường>} from <Đường Dẫn>
- <Một Số Giá Trị Thường> phải là liệt kê các tên của giá trị Export thường bạn muốn
Import, đây cũng là tên biến bạn sẽ dùng trong File mượn, bạn có thể đổi tên bằng cách
thêm as <Tên Mới>
- Ví dụ
import {foo, bar, alice as john, gaara as luffy} from "./bar/alice.js"
 Bạn có thể vừa Import giá trị mặc định và giá trị thường, giá trị mặc định phải đặt trước,
ví dụ
import hahanore, {foo, bar} from "./bar/alice.js"
 Để Export giá trị mặc định, giá trị mặc định này bằng giá trị mặc định được Export ra từ
File khác
export {default} from <Đường Dẫn>
 Để Export giá trị thường, giá trị thường này bằng giá trị mặc định được Export ra từ File
khác
export {default as <Tên Thường Mới>} from <Đường Dẫn>
 Để Export giá trị thường, giá trị thường này bằng 1 giá trị thường được Export ra từ File
khác
export {<Tên Các Giá Trị Thường Từ File Khác>} from <Đường Dẫn>
- Nếu để nguyên thì tên giá trị thường Export ra từ File này cũng giống File khác đó, để đổi
tên thì thêm as <Tên Mới>, ví dụ
export {foo as bar, alice as john, gaara, luffy} from "./bar/alice.js"
 Có thể kết hợp các cách trên vào 1 dòng, ví dụ
export {foo, bar as john, default, bob} from "./bar/alice.js"
 Để Import tất cả các giá trị bao gồm cả mặc định lẫn thường
import * as <Tên Mới> from <Đường Dẫn>
- <Tên Mới> là 1 Object, chứa các Key là tên các giá trị thường, Key là "default" ứng với giá
trị mặc định
 Chú ý trường hợp bạn chạy File JS bằng Node, thì có thể thay <Đường Dẫn> = tên thư
viện, nghĩa là các thư mục con trong thư mục "node_modules" có thể truy cập trực tiếp,
ví dụ
import foo from "express"
 Tương đương
const foo = require("express")
9. Rút Gọn Lệnh?
npm run <Lệnh>
 Khi bạn chạy lệnh này, thì nó sẽ dò trong thuộc tính "scripts" của File "package.json",
xem có Key nào = <Lệnh> không, nếu có, thì nó sẽ chạy chuỗi Value tương ứng, ví dụ
trong File "package.json"
"scripts": {
"foo" : "node_modules\\.bin\\nodemon.cmd haha"
}
 Thì khi bạn nhập
npm run foo
 Thì tương đương
node_modules\.bin\nodemon.cmd haha
 Riêng Key "start" thì không cần run
npm start
 Đặc biệt, khi chạy bằng cách này, thì ta có thể sử dụng các File ".cmd" ở thư mục ".bin"
trong thư mục "node_modules" mà không cần chỉ định đường dẫn cụ thể, và cũng không
cần phần mở rộng, ví dụ
"scripts": {
"foo" : "nodemon haha"
}
10. Origin?
 Là tổ hợp Scheme và Authority trong URL
11. SOP (Same Origin Policy)?
 Là quy định của trình duyệt chỉ cho phép Origin A được phép gửi yêu cầu tới Origin A,
không được gửi yêu cầu tới Origin khác, ví dụ Origin A là https://foo.com:3000, thì ở
máy chủ Host tên miền foo.com, Port 3000, sẽ không được phép gửi yêu cầu tới máy chủ
Host tên miền khác foo.com, hoặc khác Port 3000, hoặc máy chủ không cho phép yêu
cầu với giao thức HTTPS
12. CORS (Cross Origin Resource Sharing)?
 Là mở rộng của SOP, nghĩa là ngoài 2 Origin giống nhau có thể gửi yêu cầu cho nhau, bạn
có thể chỉ định 1 số Origin khác có thể gửi yêu cầu tới Origin của bạn

Express:

1. Cách Import?
 Để cài đặt
npm install express
 Để Import
 Common Module
const <Express> = require("express")
 ECMA Module
import <Express> from "express"
2. Tạo 1 App?
const <App> = <Express>()
 Mỗi khi chạy lệnh trên, thì 1 App mới được tạo, các App không liên quan tới nhau, mỗi
App sẽ chiếm giữ nhiều Port, và không thể có Port bị 2 App chiếm giữ
3. Lắng Nghe Tại 1 Port?
 Để 1 App chiếm giữ 1 Port, hay bắt đầu lắng nghe tại Port này
<App>.listen(<Port>, <Call Back>)
 Đây là hàm bất đồng bộ, nên các lệnh tiếp theo chạy luôn không chờ, sau khi đã chiếm
giữ thành công thì <Call Back> sẽ được gọi, không chỉ định <Call Back> cũng được
 Nếu gọi lệnh trên lần 2 với cùng <Port> sẽ lỗi
 Ví dụ
foo.listen(3000)
4. Middleware?
 Với mỗi Path khác nhau trên URL, ta có thể gửi yêu cầu tới nó bằng các phương thức
khác nhau như Get, Post, …, và mỗi Path như vậy, sẽ có 1 Middleware Stack cho riêng
nó, Middleware Stack sẽ bao gồm Middleware 1, Middleware 2, Middleware 3, …, khi
gửi yêu cầu với phương thức bất kì, thì ngay lập tức Middleware 1 sẽ được gọi đầu tiên,
và được truyền các tham số lần lượt là <Request>, <Response>, và <Next>, khi
Middleware 1 chạy, nếu gặp lệnh <Next>() lần đầu tiên, thì lập tức nhảy sang chạy
Middleware 2, tương tự Middleware 2 chạy thì nếu gặp lệnh <Next>() thì sẽ nhảy sang
chạy Middleware 3, …, dễ thấy cơ chế giống như đệ quy, cho tới khi chạy xong
Middleware cuối cùng, thì nó sẽ quay lại Middleware kế cuối để chạy nốt phần sau
<Next>(), lưu ý <Next>() chạy lần thứ 2 trở đi sẽ vô dụng và nếu không còn Middleware
nào để chạy thì <Next>() cũng vô dụng, rồi lại quay lui Middleware kế kế cuối, …, trong
khi chuỗi Middleware chạy, bạn sẽ thấy biểu tượng vòng tròn xoay xoay nghĩa là đang tải
ở trên tiêu đề Tab, cho tới khi có lệnh <Response>.send hoặc <Response>.render trong
Middleware thì nó mới hết, đồng thời gửi Response về trình duyệt, trường hợp 1
Middleware không có lệnh <Next>() bên trong sẽ quay vòng vòng mãi mãi, lưu ý 2 lệnh
send và render chạy thì mấy lệnh sau nó vẫn chạy tiếp và bạn không thể gửi Response 2
lần
 Để thêm 1 Middleware, cái nào thêm sau thì đánh số lớn hơn, ví dụ Middleware 1, 2, 3,

<App>.use(<Path Đầu>, <Middleware>)
 <Middleware> sẽ là 1 Call Back nhận 3 tham số như đã nói
 <Path Đầu> tức là lệnh trên sẽ thêm <Middleware> vào tất cả các Path có khởi đầu là
<Path Đầu>, ví dụ <Path Đầu> = "/foo/bar", thì các Path như "/foo/bar/alice",
"/foo/bar/alice/john", "/foo/bar/boo", … đều được thêm <Middleware>
 Lệnh trên áp dụng với mọi Port mà <App> đang chiếm giữ
 Nếu <Path Đầu> không chỉ định thì áp dụng cho mọi Path
 <Path Đầu> có thể sử dụng cơ chế động, bằng cách thêm dấu 2 chấm ở đầu các khúc, ví
dụ Path tĩnh thông thường sẽ là /foo/bar, /alice, …, còn Path động sẽ là
/foo/:slug, /:bar, /:gg/concac/:concu, …, xét ví dụ /:gg/concac/:concu, thì tất cả các Path
từ 3 khúc trở lên, sao cho khúc thứ 2 là concac, sẽ bị dính, ví dụ /x/concac/y/z,
/lon/concac/longchim, …, nghĩa là tương đương với hàng tỉ câu lệnh use, ứng với tất cả
Path này, chuỗi sau dấu : của các khúc được gọi là Slug, trong <Middleware>, bạn có thể
dùng <Request> để truy xuất giá trị của các Slug, thông qua Object trả về bởi lệnh
<Request>.params, Object này có cặp Key Value, với Key là tên Slug, và Value là giá trị
hiện tại của nó bạn nhập trên URL, tiếp tục ví dụ trên, giả sử bạn nhập Path của URL là
/concho/concac/buom/thui, thì sẽ dính /:gg/concac/:concu, khi này <Request>.params

{
"gg": "concho",
"concu": "buom"
}
 Tương tự như trên, nhưng Middleware được thêm sẽ có thêm điều kiện là nếu Path trên
URL không giống y chang <Path> hoặc yêu cầu với phương thức không phải Get, thì sẽ
Next ngay lập tức mà không chạy Call Back, <Path> vẫn có thể động, <Path> phải được
chỉ định
<App>.get(<Path>, <Middleware>)
 Về lệnh send
<Response>.send(<Response Body>)
 Nếu <Response Body> là String, thì thuộc tính "Content-Type" của Response Header sẽ
là "text/html;charset=urf-8"
 Nếu <Response Body> là 1 Object viết theo Dictionary, thì "Content-Type" là
"application/json;charset=utf-8"
 Về lệnh render, cũng như trên, nhưng trước khi gửi Response thì nó sẽ thông qua Engine
chính, 1 App sẽ có nhiều Engine, và giá trị của thuộc tính View Engine của App chính là
tên đại diện của Engine chính, các Engine còn lại là phụ
<Response>.render(<Đường Dẫn Tới File Render>)
 Khi lệnh trên được chạy, trước tiên, nó sẽ tìm đến thư mục A được chỉ định bởi thuộc
tính Views của App, tức thuộc tính Views của App phải là String đường dẫn tuyệt đối tới
thư mục A hoặc tương đối tới A, kể từ bên trong thư mục làm việc hiện tại, <Đường Dẫn
Tới File Render> sẽ là đường dẫn tương đối, kể từ bên trong A, dẫn tới File cần Render,
không ghi phần mở rộng, File cần Render này phải có phần mở rộng = tên đại diện của
Engine chính, tùy vào loại Engine mà nó sẽ xử lí File này khác nhau để trả về 1 String cuối
cùng, String này sẽ làm phần Response Body
 Ví dụ
app.use("/foo", (req, res, next) => {
console.log(1)
next()
console.log(2)
})
app.use("/foo", (req, res, next) => {
console.log(3)
next()
console.log(4)
})
app.get("/foo/bar", (req, res, next) => {
console.log(5)
next()
console.log(6)
})
app.get("/foo/bar", (req, res, next) => {
console.log(7)
res.send("ggnore")
console.log(8)
})
 Ở đây, khi bạn nhập URL với Path là /foo/bar, thì màn hình Console lập tức hiện ra là
1
3
5
7
8
6
4
2
 Về <Request>
 Để trả về Object ứng với chuỗi Query trên URL, tức là gồm các Key Value của các tham số
Query
<Request>.query
5. Cài Đặt Server?
 Mỗi 1 App sẽ có các thuộc tính riêng, trong đó có 1 số thuộc tính liên quan đến cài đặt,
còn lại là thuộc tính thường, để gán lại giá trị cho 1 thuộc tính hoặc tạo mới 1 thuộc tính
<App>.set(<Tên Thuộc Tính>, <Giá Trị>)
 Ví dụ
foo.set("hahanore", 123)
 Để trả về giá trị của 1 thuộc tính
<App>.get(<Tên Thuộc Tính>)
 Các thuộc tính cài đặt
 Thuộc tính View Engine, "view engine"
 Thuộc tính Views, "views", mặc định là String đường dẫn tuyệt đối tới thư mục làm việc
hiện tại, thêm thư mục "views" đằng sau, ví dụ "C:\Users\pc\Desktop\Web Test\views"
 Để thêm 1 Engine vào App
<App>.engine(<Tên Đại Diện Engine>, <Engine>)
 Nếu lặp lại lệnh trên với cùng <Tên Đại Diện Engine>, thì bỏ thằng trước lấy thằng sau
 Ví dụ
foo.engine("hahanore", ultimate_engine())
6. Các File Tĩnh?
 Lệnh sau sẽ trả về 1 Middleware
<Express>.static(<Đường Dẫn Tới Nguồn Tĩnh>)
 <Đường Dẫn Tới Nguồn Tĩnh> có thể là tuyệt đối hoặc tương đối từ trong thư mục làm
việc hiện, nó sẽ dẫn đến thư mục A
 Bạn có thể Pass Middleware này vào phương thức use của 1 App, nó có tác dụng phân
tích URL, nếu thấy URL là đường dẫn tới 1 File, tức là có phần mở rộng, nó sẽ xem xét
thư mục A có File đó không, nếu có thì trả về trình duyệt, ví dụ Path của URL là
/foo/bar/alice.png, thì trong A nếu có thư mục "foo" và trong "foo" có "bar" và trong
"bar" có "alice.png" thì sẽ trả về File "alice.png", nếu không tồn tại thì trả về lỗi 404, ví
dụ
app.use(express.static("thu/mucA"))
7. Xử Lí Request Body?
 Như đã biết, Request Body chính là các cặp Key Value trong Form bạn Submit bằng
phương thức Post, tuy nhiên Request Body không có ngay được để sử dụng trong các
Middleware, mà bạn cần phải xử lí các thông tin Submit trước mới ra được Request
Body, để làm điều này thì dùng lệnh sau, lệnh này trả về 1 Middleware có tác dụng xử lí
thông tin Submit để tạo Request Body
<Express>.urlencoded({extended: true})
 Ví dụ
app.use(express.urlencoded({extended: true}))
 Sau khi Middleware trên được chạy, thì các Middleware tiếp theo có thể sử dụng lệnh
sau để trả về Object, gồm các cặp Key Value trong Request Body
<Request>.body
8. Mô Hình MVC (Model View Controller)?

9. Chia Nhỏ Các Tuyến Đường?


const <Route> = <Express>.Router()
 <Route> chính là 1 hàm, và như bạn đã biết, bạn có thể tạo thuộc tính hoặc phương
thức cho 1 hàm rồi sau
 Lệnh sau y chang phương thức use của App
<Route>.use(<Path Đầu>, <Middleware>)
 Tương tự với các lệnh get, post, … bạn đều có thể gọi trên <Route>, nghĩa là <Route>
giống như 1 App thu nhỏ, có Middleware Stack riêng, để sử dụng <Route>
<App>.use(<Path Đầu>, <Route>)
 Khi này, vẫn như cơ chế Middleware thông thường, nếu Path trên URL có phần đầu là
<Path Đầu>, thì hàm <Route> sẽ được gọi, và được truyền 3 tham số <Request>,
<Response> và <Next>, và nó dựa vào Middleware Stack của chính nó để xử lí, chỉ có
điều, nó sẽ tính Path kể từ sau <Path Đầu>, đây gọi là Mount Point, tuy nhiên điều này
chỉ xảy ra khi <App> dùng hàm use, nếu <App> dùng get, post, … thì Mount Point trở về
vạch xuất phát gần nhất
 Ví dụ 1
const route = express.Router()
route.use("/:slam", (req, res) => res.send(req.params.slam)) // Dòng 2
app.use("/:slug/bar", route) // Dòng 3
 Khi này giả sử bạn nhập Path trên URL là /concac/bar/daubuoi/daucu, thì dòng 3 sẽ dính,
do đó hàm route được gọi, khi này Mount Point là /concac/bar, do đó dòng 2 dính với
slam = "daubuoi", và thế là Response Body là "daubuoi"
 Ở dòng 2, để ý thấy bạn sẽ không thể truy cập được slug, mà chỉ truy cập được slam,
nghĩa là chỉ truy cập được Slug trong route, không phải trong app
 Ví dụ 2
const route = express.Router()
route.use("/:slam", (req, res) => res.send(req.params.slam)) // Dòng 2
app.get("/foo/bar", route) // Dòng 3
 Khi này giả sử bạn nhập Path trên URL là /foo/bar với phương thức Get, thì dòng 3 dính,
hàm route được gọi, tuy nhiên Mount Point khi này là / do không phải phương thức use,
do đó slam ở dòng 2 sẽ là "foo", nên in ra màn hình "foo"
 Ví dụ 3
const route = express.Router()
route.use("/bob", (req, res, next) => {
console.log(1)
next()
console.log(2)
}) // Dòng 1
route.get("/bob/alice", (req, res) => {
console.log(3)
res.send("ggnore")
console.log(4)
}) // Dòng 2
app.use("/foo/bar", route) // Dòng 3
 Khi này giả sử bạn nhập Path trên URL là /foo/bar/bob/alice với phương thức Get, thì
dòng 3 dính, hàm route được gọi, Mount Point khi này là /foo/bar, dễ thấy dòng 1 là
Middleware 1 nên sẽ dính trước, in ra Console giá trị 1, rồi nhảy sang Middleware 2 là
dòng 2, do phương thức là Get nên dòng này dính, in ra Console 3, trả về Response Body
là "ggnore", in ra Console 4, rồi trở về dòng 1, in ra 2, và kết thúc
 Bạn có thể lòng <Route> trong <Route>, chia càng nhỏ ra các tuyến đường, ví dụ
const route1 = express.Router()
const route2 = express.Router()
route2.use("/bar", (req, res) => res.send("Hello")) // Dòng 1
route1.get("/bar/bob", route2) // Dòng 2
app.use("/foo", route1) // Dòng 3
 Khi này giả sử bạn nhập Path trên URL là /foo/bar/bob, thì dòng 3 dính, gọi route1,
Mount Point là /foo, do đó dòng 2 dính, gọi route2, Mount Point vẫn là /foo do dùng
phương thức get, do đó dòng 1 lại dính, và in ra "Hello"

Nodemon:

1. Cách Tải?
npm install nodemon --save-dev
 Khi này, trong thư mục con ".bin" của "node_modules", sẽ có File "nodemon.cmd"
2. Cách Khởi Động Lại Server Mỗi Khi Thay Đổi File?
 Dùng File "nodemon.cmd"
node_modules/.bin/nodemon.cmd <Đường Dẫn Tới File JS Không Cần Phần Mở Rộng>
 Lệnh trên y chang như dùng Node để chạy 1 File JS, tuy nhiên, thay vì chỉ có 1 Process
node.exe thì có 2 Process node.exe cùng xuất hiện, 1 cái dùng để hóng các thay đổi
trong các File để làm mới cái còn lại, và cái này tồn tại vĩnh viễn cho tới khi bạn cố tính
tắt nó đi, nghĩa là, khác với Node, Nodemon sẽ không dừng cho dù File JS đã chạy xong,
và bất cứ khi nào các File liên quan đến File JS đó bị thay đổi, thì Nodemon sẽ chạy lại từ
đầu, mặc định thì các File liên quan phải có phần mở rộng là ".js", ".mjs" hoặc ".json" thì
mới tính, các File còn lại thay đổi hay không cũng chẳng làm mới, để thay đổi sự mặc
định này, thì tạo File "nodemon.json" trong thư mục làm việc hiện tại, và đặt thuộc tính
"ext" trong nó thành chuỗi các phần mở rộng sẽ lắng nghe sự thay đổi, ví dụ
{
"ext": "js json scss css"
}

JSON Server:

1. Cách Tải?
npm install json-server
2. Tạo JSON Server?
npx json-server <Đường Dẫn Tới File JSON Có Phần Mở Rộng>
 Lệnh trên sẽ tạo 1 Server tại http://localhost:3000, để tạo Server tại Port khác thì thêm
cờ -p, theo sau là số Port, Server chỉ đóng khi Terminal chạy lệnh trên hủy chạy
 Nội dung File JSON sẽ bao gồm các Key cấp 1, Value của mỗi Key này là thứ sẽ được trả
về khi bạn gửi yêu cầu vào Link tới Server / <Tên Key> bằng phương thức Get, ví dụ
http://localhost:3500/ggnore
 Thứ được trả về khi gửi yêu cầu Get bằng hàm fetch, là 1 Object, gọi là Response, để trả
về 1 Promise, Promise này bất đồng bộ có tác dụng giải mã nội dung từ JSON thành biến,
nghĩa là nó trả về đúng kiểu dữ liệu, khi Fulfilled thì Promise Result = giá trị biến
<Response>.json()
 Ví dụ
fetch("http://localhost:3500/ggnore").then(x => x.json()).then(x => console.log(x))

Cookie Parser?

1. Cách Import?
 Để tải
npm install cookie-parser
 Để Import
 Common Module
const <Cookie Parser> = require("cookie-parser")
 ECMA Module
import <Cookie Parser> from "cookie-parser"
2. Middleware Giải Mã Cookie?
 <Request> trong Middleware của App của Express chưa thể sử dụng Cookie ngay được,
nhắc lại Cookie này tự động được gửi kèm theo yêu cầu từ phía trình duyệt người dùng,
để trả về Middleware có chức năng giải mã Cookie
<Cookie Parser>()
 Ví dụ
app.use(cookie_parser())
 Bây giờ ở các Middleware tiếp theo, có thể dùng lệnh sau để trả về Cookie, là Object viết
theo Dictionary, chứa các cặp Key Value đều là String
<Request>.cookies

Express Handlebars:

1. Cách Import?
 Để tải
npm install express-handlebars
 Để Import
 Common Module
const <Express Handlebars> = require("express-handlebars")
 ECMA Module
import <Express Handlebars> from "express-handlebars"
2. Thêm Engine Vào App Của Express?
<App>.engine(<Tên Đại Diện Engine>, <Express Handlebars>.engine(<Config>))
 <Config> là 1 Object viết theo Dictionary
 Engine này hoạt động như sau, trong thư mục được chỉ định bởi thuộc tính Views của
<App>, phải có 1 thư mục tên là "layouts", trong đây lại phải có 1 File tên là "main" với
phần mở rộng = giá trị của thuộc tính "extname" của <Config>, ví dụ extname =
".ggnore", nếu không chỉ định thì mặc định extname = ".handlebars", File "main" này y
chang 1 File HTML hoàn chỉnh, tuy nhiên trong nó có thể dùng 1 số cú pháp đặc biệt
 Khi bạn viết như sau, thì vị trí bạn viết, sẽ được đặt thẳng vào toàn bộ nội dung của File
cần Render
{{{body}}}
 Khi bạn viết như sau, thì vị trí bạn viết, sẽ được đặt thẳng vào toàn bộ nội dung của 1
File A, File A này được xác định như sau, xét thư mục được chỉ định bởi thuộc tính Views
của <App>, phải có 1 thư mục tên là "partials" bên trong nó, và <Đường Dẫn Đến File
Partial> sẽ bắt đầu từ bên trong thư mục "partials" này, dẫn tới File A, không ghi phần
mở rộng, File A phải có phần mở rộng = phần mở rộng của File "main" ở trên
{{> <Đường Dẫn Đến File Partial>}
- Ví dụ
{{> foo/bar}
 Nội dung của File "main" sau khi được thế, sẽ là thứ được trả về làm Response Body

Path:

1. Cách Import?
 Thư viện này tự động dùng được chỉ cần File JS chạy bằng Node, không cần tải
 Để Import
 Common Module
const <Path> = require("path")
 ECMA Module
Import <Path> from "path"
2. Nối Đường Dẫn?
<Path>.join(<Các Đường Dẫn>)
 Lệnh trên sẽ trả về String có được nhờ việc nối tất cả String trong <Các Đường Dẫn> lại
với nhau bằng dấu \ giữa các String, sau đó bất kì dấu / nào tồn tại đều bị biến thành \,
đồng thời mọi chùm dấu \ liền nhau sẽ bị hợp thành 1 dấu \ duy nhất, ví dụ
path.join("C::Emmet: Increment by 1/:a/concu", "concac", "conbuom//")
 Lệnh trên trả về "C::Emmet: Increment by 1\:a\concu\concac\conbuom\"

HTTP:

1. Cách Import?
 Thư viện này tự động dùng được chỉ cần File JS chạy bằng Node, không cần tải
 Để Import
 Common Module
const <HTTP> = require("http")
 ECMA Module
Import <HTTP> from "http"
2.

Mongoose:

1. Cách Import?
 Để tải
npm install mongoose
 Để Import
 Common Module
const <Mongoose> = require("mongoose ")
 ECMA Module
import <Mongoose> from "mongoose"
2. Kết Nối Với Cluster?
 Một lúc bạn có thể kết nối với nhiều cơ sở dữ liệu của nhiều Cluster khác nhau, nhưng
trong đó, chỉ có 1 kết nối tiêu chuẩn, bạn chỉ được phép tạo nhiều nhất 1 kết nối tiêu
chuẩn, các kết nối còn lại là kết nối thường
 Lệnh dưới đây sẽ tạo 1 Promise bất đồng bộ, nó có nhiệm vụ kết nối với 1 cơ sở dữ liệu
của 1 Cluster, có thể là ở trên đám mây hoặc cục bộ, sau khi kết nối xong thì thu được
Promise Result là 1 Object, tạm gọi là <Connection>, đây là kết nối tiêu chuẩn
<Mongoose>.connect(<URI>)
 <URI> là URI tới Cluster thêm phần tên cơ sở dữ liệu muốn kết nối ở đằng sau, lưu ý nếu
kết nối cục bộ, thì localhost phải đổi thành 127.0.0.1, ví dụ các URI sau là hợp lệ
mongodb+srv://thanglon:[email protected]/coso1
mongodb://127.0.0.1:27017/coso2
 Tương tự, nhưng lệnh dưới đây tạo ra kết nối thường, Promise Result cũng là
<Connection>
<Mongoose>.createConnection(<URI>)
 Nếu để đó thì các kết nối vẫn giữ nguyên, để ngắt kết nối, đúng hơn là trả về 1 Promise
bất đồng bộ, có nhiệm vụ ngắt kết nối
<Connection>.disconnect()
 Nếu <Connection> là kết nối tiêu chuẩn thì có thể thay bằng <Mongoose>
 Lệnh sau trả về 1 Schema, tạm gọi là <Schema>, khi <Schema> này được gắn với 1
Collection của 1 cơ sở dữ liệu nào đó, thì những lần tạo Document tiếp theo trên
Collection đó phải tuân theo <Schema> này mới được lưu vào Collection
new <Mongoose>.Schema(<Scheme>, {
collection: <Tên Collection>,
versionKey: <Tên Version Key>
})
 <Scheme> là Object viết theo kiểu Dictionary, Value ở đây sẽ là kiểu dữ liệu
 <Tên Collection> tạm gọi là thuộc tính Collection Name của <Schema>, không chỉ định
cũng được
 <Tên Version Key> tạm gọi là thuộc tính Version Key của <Schema>, không chỉ định thì
mặc định nó = "__v"
 Lệnh sau trả về 1 Object, tạm gọi là <Model> ứng với 1 Collection của cơ sở dữ liệu
<Connection>.model(<Tên Model>, <Schema>)
 <Tên Model> là String, bạn đặt cái mẹ gì cũng được
 Nếu <Schema> có chỉ định thuộc tính Collection Name, thì giá trị của thuộc tính này sẽ
chính là tên của Collection mà ta sẽ liên kết tới, nếu không tồn tại Collection nào có tên
này trong cơ sở dữ liệu thì sẽ tạo mới, nếu không chỉ định Collection Name, thì
Collection liên kết tới sẽ có tên suy ra bởi <Tên Model>, bằng cách viết thường hết các
chữ cái, rồi các dấu cách thay bằng dấu _, rồi sẽ đổi sang dạng số nhiều, ví dụ thêm s
hoặc es cuối từ tiếng Anh
 Nếu <Connection> là kết nối tiêu chuẩn, thì có thể thế <Connection> ở lệnh trên thành
<Mongoose>
 Lệnh sau sẽ trả về 1 Promise bất đồng bộ, có nhiệm vụ Query 1 số Document trong
Collection ứng với <Model>, Promise Result sẽ là 1 Array chứa các Object, tạm gọi là
<Document>, chính là các Document được Query ra
<Model>.find(<Query>)
 <Query> viết y chang như chuỗi Query trong Mongo DB Compass, tức là 1 Object viết
theo Dictionary
 Để trả về 1 bản nháp Document, tạm gọi là <Temp Document>, nó chưa lưu vào
Collection vội
new <Model>(<Nội Dung Document>)
 <Nội Dung Document> là Object viết theo Dictionary, viết kiểu gì cũng được
 Các kiểu dữ liệu tương ứng giữa JS và Mongo DB

JS Mongo DB
String String
Nếu là số nguyên vừa tầm thì khi lưu
Number sẽ thành Int32, ngược lại nếu số thập
phân, hoặc vượt tầm thì Double
Boolean Boolean
Array Array
Date Date
<Mongoose>.Schema.Types.Decimal128 Decimal128
<Mongoose>.Schema.Types.BigInt Int64
Object Object
<Mongoose>.Schema.Types.ObjectId ObjectID
 Chỉnh sửa 1 <Document> y chang như khi bạn chỉnh sửa 1 Object viết theo Dictionary,
để trả về 1 Promise bất đồng bộ, có nhiệm vụ lưu <Document> hoặc <Temp Document>
vào Collection
<Document>.save()
 Lệnh trên sẽ lỗi nếu <Document> không tuân theo <Schema>, tức là có 1 cặp Key Value
trong <Document>, mà kiểu dữ liệu của Value không thể ép về kiểu được chỉ định trong
<Schema>
 Nếu trong <Document> chứa các Key không có trong <Schema>, thì các Key này bị bỏ
không lưu
 Nếu trong <Document> thiếu Key được chỉ định trong <Schema>, thì không sao, các Key
này cũng sẽ không lưu trừ khi có giá trị mặc định
 Sẽ có 2 Key nữa được lưu vào là Key "_id" và Version Key
- Với Key "_id", thì đây là Key được tạo bởi hệ thống, không thể chỉnh sửa hay xóa, kiểu là
ObjectID, tất cả Document trong Collection sẽ được đảm bảo Value của Key "_id" là độc
nhất
- Với Version Key, nếu bạn chỉ định nó trong <Schema> là false, thì sẽ không lưu Version
Key nào hết, nhưng nếu nó là 1 String nào đó, thì bạn sẽ thấy có 1 Key với tên là String
đó, được lưu với kiểu dữ liệu là Int32 với giá trị ban đầu = 0
 Để trả về 1 ObjectID
new <Mongoose>.Types.ObjectId(<String 24 Kí Tự Thập Lục Phân>)
 Để xóa tất cả Document thỏa mãn Query nào đó, nói đúng hơn là trả về 1 Promise bất
đồng bộ, có nhiệm vụ xóa các Document, cách viết Query đã biết
<Model>.deleteMany(<Query>)

Developer Tools:

1. Cách Hoạt Động?


 Để mở cửa sổ Developer Tools, gọi tắt là cửa sổ phát triển, phải chuột vào chỗ bất kì
trong trang Web đang hiện ở 1 Tab + chọn "Inspect", khi này 1 cửa sổ phát triển liên kết
với Tab vừa chọn sẽ hiện lên
 Khi đóng Tab, thì cửa sổ phát triển cũng đóng theo
 Tab cập nhật gì, thì cửa sổ phát triển cũng cập nhật theo, và ngược lại, cửa sổ phát triển
cập nhật gì, thì Tab cũng cập nhật theo
 Để chủ động đóng cửa sổ phát triển, Click dấu X góc phải trên của nó
 Mặc định cửa sổ phát triển sẽ nằm bên phải và tích hợp vào Tab liên kết, để thay đổi vị
trí của nó, Click dấu 3 chấm dọc góc phải trên + tại mục "Dock side" chọn biểu tượng
"Dock to right" để đặt bên phải, "Dock to left" để đặt bên trái, "Dock to bottom" để đặt
bên dưới và "Undock to separate window" để tách nó thành 1 cửa sổ riêng không tích
hợp nữa, vẫn liên kết với Tab
 Cửa sổ phát triển bao gồm 3 phần chính, thanh trên cùng chứa các Tab, phần ngay bên
dưới sẽ khác nhau với mỗi Tab, và phần dưới cùng có thể có hoặc không, là Tab
"Console" mở sẵn, nó sẽ ẩn đi khi bạn vào Tab "Console" chính, và hiện ra ở những Tab
khác, để ẩn hoặc hiện nó, nhấn "Esc"
2. Tab "Elements"?
 Cửa sổ phát triển sẽ có 2 chế độ, 1 là chế độ chọn phần tử, 2 là chế độ không chọn phần
tử, mặc định ở chế độ không chọn phần tử
 Để thay đổi chế độ, Click vào biểu tượng mũi tên góc trái trên = nhấn "Ctrl" + "Shift" +
"C"
 Tab "Elements" bao gồm 2 phần, phần trên chứa cấu trúc DOM thời điểm hiện tại của
Tab liên kết với cửa số phát triển, trình bày theo mã HTML, gọi tắt là cửa sổ DOM, phần
bên dưới chứa đầy đủ thông tin của Node được chọn, gọi tắt là cửa sổ Node được chọn
 Khi bạn đang trong chế độ chọn phần tử, và tiến hành Click chuột tại chỗ nào đó trong
trang Web, thì cửa sổ phát triển sẽ nhảy ngay sang Tab "Elements" và phần tử bạn Click
vào tương ứng trong cửa sổ DOM sẽ được chọn, hoặc bạn chọn trực tiếp trong cửa sổ
DOM cũng được
 Cửa sổ Node được chọn bao gồm 3 phần, thanh trên cùng chứa đường đi từ Node gốc,
là Node HTML, tới Node được chọn, nghĩa là danh sách các Node từ Node HTML tới
Node được chọn, bạn có thể Click vào để chọn 1 trong số chúng, thanh bên dưới chứa
các Tab, gọi là thanh thuộc tính Node được chọn, toàn bộ phần bên dưới sẽ khác nhau
với các Tab khác nhau
 Các Tab tại thanh thuộc tính Node được chọn bao gồm
 Tab "Styles", gồm 5 phần, thanh trên cùng gọi là thanh công cụ kiểu cách, phần ngay bên
dưới là toàn bộ kiểu cách mà bạn đã chỉ định trực tiếp cho Node được chọn thông qua
chỉ định thuộc tính style, bạn có thể chỉnh sửa phần này, trước mỗi dòng ở đây có thêm
ô để bạn Tick hoặc Untick, nếu Untick thì dòng tương ứng trở nên vô dụng, phần ở giữa
tương tự, nhưng là kiểu cách bạn đặt trong Tag Style hoặc trong File CSS bên ngoài, bạn
có thể chỉnh sửa phần này, phần dưới in nghiêng có đề "user agent stylesheet" chứa
toàn bộ kiểu cách mặc định của Node được chọn, bạn không thể chỉnh sửa phần này, ví
dụ kiểu cách mặc định của Tag đoạn văn sẽ khác Tag đề mục, và giả sử xóa hết kiểu cách
mặc định này đi, thì nó chả khác gì Node văn bản mặc định, phần cuối cùng là bản vẽ
Node này khi kết xuất, bao gồm Padding, Border, Margin
3. Tab "Console"?
 Gồm 2 phần, thanh trên cùng gọi là thanh công cụ Console, phần bên dưới là nơi bạn có
thể chạy lệnh JS trực tiếp, nó giống như Terminal, những gì được in ra sẽ nằm ở đây, gọi
là Console
 Bạn chỉ có thể nhập lệnh lên Console và nhấn Enter để chạy chỉ khi luồng JS của trang
Web đang không chạy
 Tất cả những gì trong Tab "Console" sẽ bị xóa khi Tab liên kết với cửa sổ phát triển
chuyển hướng sang trang Web khác
 Để chủ động xóa tất cả nội dung trong Tab "Console", Click biểu tượng "Clear console"
bên trái thanh công cụ Console = nhấn "Ctrl" + "L"
 Ngoài ra, để ẩn hiện cửa sổ cài đặt Console, Click biểu tượng bánh răng bên phải cùng
thanh công cụ Console
 Để ngăn chặn việc xóa nội dung trong Tab "Console" khi chuyển hướng trang, Tick vào ô
"Preserve log" tại cửa sổ cài đặt Console, và Untick để trở lại mặc định
 Nếu khi in ra Console dòng tiếp theo, mà nội dung giống dòng ngay trước, thì không in ra
dòng mới, đồng thời cũng sẽ hiển thị số lần lặp lại
4. Tab "Sources"?
 Bao gồm 3 phần, phần góc trái trên là cửa sổ Navigator, phần góc phải trên là cửa sổ Edit
File, phần bên dưới là cửa sổ Debug
 Cửa sổ Navigator bao gồm 2 phần, thanh trên cùng chứa các Tab là thanh Navigator,
phần bên dưới sẽ khác nhau với mỗi Tab
 Cửa sổ Edit File chứa các Tab giống VS Code là các File bạn mở, bạn có thể chỉnh sửa và
lưu nó, không thể chỉnh sửa nếu là File HTML
 Tab "Page" tại thanh Navigator sẽ chứa cấu trúc thư mục của trang Web, giống trong VS
Code, thư mục to nhất đại diện cho trang Web tên là "top", các thư mục con ngay bên
dưới là các tên miền, bạn có thể Click vào các File bên trong để mở nó trong cửa sổ Edit
File, ở đây bao gồm tất cả các File mà trang Web đang sử dụng, bao gồm cả các File lưu
ở các trang Web khác
5. Response?
 Khi gửi 1 yêu cầu tới máy chủ, thì nó sẽ phải hồi về 1 Response duy nhất, Response này
chỉ đơn giản là 1 văn bản thông thường, có bố cục như sau
<Phiên Bản Giao Thức Và Trạng Thái>
<Response Header>

<Response Body>
 Dễ thấy giữa phần <Response Header> và <Response Body> sẽ có 1 dòng trống
 <Phiên Bản Giao Thức Và Trạng Thái> thông thường sẽ có dạng sau, ví dụ giao thức là
HTTP phiên bản 1.1, mã trạng thái phản hồi là 200
HTTP/1.1 200 OK
 <Response Header> sẽ bao gồm các dòng, mỗi dòng là 1 thuộc tính
- "Date", thời điểm phản hồi xảy ra, theo múi giờ chuẩn, có cú pháp
<Thứ>, <Ngày> <Tháng> <Năm> <Giờ>:<Phút>:<Giây> GMT
a) <Thứ>, <Tháng> là từ tiếng anh, lấy 3 chữ cái đầu, kí tự đầu viết hoa
- "Content-Encoding", cơ chế mã hóa của <Response Body>

Nội dung Ý nghĩa


UTF-8 Mã hóa bằng UTF 8
br Nén dữ liệu bằng thuận toán Brotli
- "Content-Length", số Byte để lưu <Response Body> sau khi mã hóa
- "Content-Type", loại văn bản, nó có thể kèm theo loại bộ kí tự nó dùng trong <Response
Body>, tức là cho ta biết trước trong <Response Body> sẽ có những kí tự nào, bỏ đi cái
này cũng không sao, ngăn cách với loại văn bản bởi dấu chấm phẩy
a) Loại văn bản

application/json Văn bản JSON


text/html Văn bản HTML
text/css Văn bản CSS
text/javascript Văn bản JS
b) Loại bộ kí tự, có cú pháp charset=<Tên Loại Bộ Kí Tự>

utf-8 Tất cả kí tự trong bộ mã Unicode


us-ascii Tất cả kí tự trong bộ mã ASCII
 <Response Body> là chuỗi văn bản nội dung chính
6. Yêu Cầu (Request)?
 Cũng giống Response, mỗi yêu cầu sẽ bao gồm Request Header, và Request Body hoặc
Request Query tùy vào yêu cầu theo phương thức nào
 Về Query trên URL, như đã biết, nó sẽ bắt đầu = dấu ?, và sau đó bạn sẽ chỉ định các
tham số Query, mỗi tham số có cú pháp sau, và các tham số ngăn cách nhau bằng dấu &
<Tên Tham Số>=<Giá Trị>
 <Tên Tham Số> và <Giá Trị> đều là String bất kì phải không chứa các kí tự đơn lẻ là &, %,
#, =, mỗi dấu cách bạn gõ vào tự động biến thành %20, sau đó chuỗi này sẽ được xử lí
bằng cách mỗi khi gặp kí tự % thì sẽ kết hợp với 2 chữ số thập lục phân đằng sau để thế
bằng kí tự tương ứng, nếu gặp dấu + thì thế thành dấu cách
 Nếu không có phần <Giá Trị> hoặc cả phần =<Giá Trị> thì <Giá Trị> là chuỗi rỗng
 Bảng kí tự %

Kí tự tương ứng
%2B +
%20 Dấu cách
%26 &
%3D =
%23 #
 Ví dụ, đầu tiên bạn nhập Query như sau vào URL
?f+++o o= abc&a%2B=1
- Thì trước tiên, nó sẽ quy đổi về Query hợp pháp sau
?f+++o%20%20o=%20%20abc&a%2B=1&concac&concu=
- Sau đó, dùng các quy tắc như đã nói, ta được 2 cặp Key Value
{
"f o o": " abc",
"a+": "1",
"concac": "",
"concu": ""
}
7. Tab Network?
 Có 4 phần, thanh trên cùng, gọi tắt là thanh công cụ mạng, phần ngay bên dưới, gọi là
cửa sổ đồ thị mạng, phần rộng hơn bên dưới, là cửa sổ File tải lên, và thanh dưới cùng,
gọi là thanh thống kê mạng
 Tab "Network" ban đầu khi bạn mở cửa sổ phát triển sẽ trống, và kể từ lúc này nó bắt
đầu hóng dữ liệu mà máy chủ gửi về trang Web ở máy bạn, cũng như những dữ liệu bạn
gửi cho máy chủ, …, để tạm ngưng việc hóng, Click biểu tượng màu đỏ bên trái cùng ở
thanh công cụ mạng = nhấn "Ctrl" + "E", khi này nó sẽ thành biểu tượng vòng tròn xám,
nhấn lại nó nữa để bắt đầu hóng lại, nhưng đồng thời cũng xóa tất cả những gì đã hóng
 Tất cả những gì trong Tab "Network" cũng sẽ bị xóa khi Tab liên kết với cửa sổ phát triển
chuyển hướng sang trang Web khác, để ngăn chặn việc xóa nội dung trong Tab
"Network" khi chuyển hướng trang hoặc khi hóng lại, Tick vào ô "Preserve log" tại thanh
công cụ mạng, và Untick để trở lại mặc định
 Để chủ động xóa tất cả nội dung trong Tab "Network", Click biểu tượng "Clear network
log" bên trái thanh công cụ mạng = nhấn "Ctrl" + "L"
 Để ý ngay dưới thanh công cụ mạng, sẽ có 1 thanh khác, gọi là thanh lọc, thanh này mặc
định sẽ hiện ra, để ẩn hiện nó, Click biểu tượng "Filter" ở bên trái thanh công cụ mạng
 Về cửa sổ File tải lên
 Cột "Name", tên phần cuối cùng trong URL bạn gửi yêu cầu tới, ví dụ URL là
https://www.youtube.com/watch?v=UnDDZrz1BoQ thì phần cuối sẽ là watch?
v=UnDDZrz1BoQ, Click vào tên ở cột này sẽ mở cửa sổ chi tiết yêu cầu ở bên phải
 Cột "Status", mã trạng thái phản hồi

Mã Ý nghĩa Văn bản liên kết


200 Máy chủ nhận yêu cầu và phản hồi thành công OK
Máy chủ nhận yêu cầu, nhưng không phản hồi nữa
304 do nội dung phản hồi sẽ giống như lần phản hồi gần Not Modified
nhất
Máy chủ nhận yêu cầu, nhưng không thể phàn hồi
404 Not Found
do Path trên URL không tồn tại
 Cột "Type", kiểu dữ liệu phản hồi về
 Cột "Initiator", chỉ ra nơi đã gửi yêu cầu này, nêu ra tên File cụ thể và dòng Code đã gửi
yêu cầu
 Cột "Size", kích thước dữ liệu trả về, theo Byte
 Cột "Time", thời gian kể từ lúc yêu cầu được gửi đi tới khi xử lí xong, theo Mili giây
 Về cửa sổ chi tiết yêu cầu
 Về Tab "Headers"
- Mục "General"
a) "Request URL", URL bạn gửi yêu cầu đến
b) "Request Method", phương thức yêu cầu, viết hoa, ví dụ Get là GET
c) "Status Code", mã trạng thái phản hồi và văn bản liên kết với nó
d) "Remote Address", địa chỉ IP của trang Web, hay chính là địa chỉ IP của máy chủ lưu
trang Web, và Port bạn gửi yêu cầu đến
- Mục "Request Headers"
a) "Cookie", mục này chỉ hiện khi có Cookie được truyền đi cùng với yêu cầu, là 1 dãy các
tham số ngăn cách nhau bởi dấu phẩy có pháp <Key>=<Value>
 Về Tab "Response", chính là phần Response Body sau khi đã được giải mã, bạn chỉ có thể
đọc, không chỉnh sửa
 Về Tab "Payload", Tab này sẽ xuất hiện khi yêu cầu phương thức Post, hoặc khi có Query
trên URL
- Mục "Query String Parameters", mục này xuất hiện khi có Query trên URL
a) Nút "view source", Click để xem chuỗi Query gốc trên URL, sau đó Click "view parsed" để
trở lại xem chuỗi Query dưới dạng các cặp Key Value
b) Nút "view URL-encoded", Click để xem Key Value dưới dạng chưa được thế, ví dụ %20
vẫn giữ là %20 chứ không phải dấu cách, sau đó Click "view decoded" để trở lại dạng sau
khi thế
- Mục "Form Data", mục này xuất hiện khi gửi yêu cầu với phương thức Post thông qua
Tag Form, cơ chế hiển thị và giải mã y chang mục "Query String Parameters", đây chính
là Request Body
8. Tab Application?
 Có 2 phần
 Panel bên trái là Panel điều hướng
 Phần bên phải khác nhau với mỗi Tab trong Panel điều hướng
- Về Tab "Local storage", Tab này sẽ chứa các Tab con là các Origin, bao gồm Origin của
trang Web hiện tại và các Origin bên thứ 3, Click vào 1 trong các Origin để xem Local
Storage của nó, bản chất của Local Storage là nó được lưu trong máy bạn, mỗi Origin sẽ
có Local Storage riêng, các cặp Key Value trong Local Storage sẽ không bị xóa bởi thời
gian, tức nó tồn tại vĩnh viễn, cho tới khi chủ trình duyệt Web xóa nó hoặc Code JS chạy
ở trình duyệt tại trang Web đó xóa nó
a) Thanh trên cùng là thanh lọc
b) Thanh dưới là thanh hiện Origin của trang Web hiện tại
c) Thanh dưới nữa nêu rõ đây có phải Origin bên thứ 3 không
d) Phần bảng ở dưới liệt kê các cặp Key Value của Local Storage của Origin tương ứng, tất
cả Key Value đều là String, chọn 1 Key rồi phải chuột, chọn "Edit Key" để chỉnh lại tên
Key, "Delete" để xóa cặp Key Value, chọn 1 Value rồi phải chuột chọn "Edit Value" để
chỉnh lại Value, dòng cuối bảng, Double Click vào để và nhập cặp Key Value mới
e) Phần phía dưới hiện giá trị chi tiết của Key Value được chọn
- Về Tab "Session storage", đéo khác gì Local Storage, nhưng cho dù cùng 1 trang Web,
nếu mở ở 2 Tab khác nhau, thì Session Storage sẽ khác nhau, nghĩa là nó riêng cho mỗi
Tab, và khi đóng Tab thì nó cũng bị xóa, nếu bạn chỉ chuyển hướng trong 1 Tab, thì khi
trở lại trang Web cũ, Session Storage vẫn giữ nguyên
- Về Tab "Cookies", giống Local Storage, nhưng thay vì tồn tại mãi mãi thì Cookie sẽ chỉ
tồn tại 1 khoảng thời gian trước khi nó biến mất, đồng thời có thể chỉ định phạm vi sử
dụng của nó
a) Thanh trên cùng là thanh lọc
b) Phần bảng ở dưới liệt kê các cặp Key Value của Cookie, cột "Name" là Key, "Value" là
Value cùng với 1 số thông tin khác của chúng là cột "Domain" = .<Tên Miền Hiện Tại>,
cột "Path" là phạm vi sử dụng của cặp Key Value này, ví dụ / thì tất cả Path trên URL đều
dùng đuộc, nếu /foo thì chỉ có các Path bắt đầu từ /foo mới dùng được, cột "Expire /
Max-Age" là thời điểm cặp Key Value này sẽ biến mất tính theo múi giờ chuẩn, "Session"
nghĩa là đóng Tab thì mất, cột "Size" = tổng số kí tự của Key + số kí tự của Value
c) Phần dưới cùng là phần hiển thị chi tiết Value của Key
9. Mô Phỏng Điện Thoại?
 Tại cửa sổ phát triển, Click vào biểu tượng "Toggle device toolbar" = nhấn "Ctrl" + "Shift"
+ "M" để thay đổi giữa 2 chế độ là chế độ PC và chế độ điện thoại, mặc định ở chế độ PC
 Ở chế độ điện thoại, trang Web của bạn mô phỏng như ở điện thoại, gồm 3 phần chính,
thanh trên cùng là thanh công cụ điện thoại, thanh bên dưới là thanh kích thước điện
thoại, phần dưới cùng là trang Web của bạn trên điện thoại, gọi là cửa sổ điện thoại
 Khi đóng cửa sổ phát triển thì trang Web nếu đang ở chế độ điện thoại, sẽ trở lại chế độ
PC
 Có 2 loại điện thoại, 1 là loại thích ứng, 2 là loại điện thoại thông thường, để chọn loại
điện thoại, Click vào "Dimensions:" bên trái thanh công cụ điện thoại + chọn
"Responsive" để chọn loại thích ứng hoặc chọn các tên điện thoại bên dưới để chọn loại
thông thường
 Ở giữa thanh công cụ điện thoại sẽ hiện kích thước điện thoại theo cú pháp chiều rộng x
chiều cao, không thể thay đổi các kích thước này nếu là loại điện thoại thông thường, và
có thể thay đổi với loại thích ứng
 Bạn cũng có thể Click vào thanh kích thước điện thoại để chuyển ngay sang loại thích
ứng với chiều rộng là kích thước bạn chọn, ngoài ra, loại thích ứng còn cho phép bạn
thay đổi kích thước điện thoại trực tiếp bằng cách kéo thả biên điện thoại
10. Mã Nguồn Trang Web?
 Phải chuột vào chỗ bất kì trong trang + chọn "View page source" = nhấn "Ctrl" + "U" =
nhập lên thanh tìm kiếm cú pháp view-source:<URL>, khi này 1 Tab mới sẽ mở ngay bên
cạnh Tab của trang Web, Tab này sẽ hiển thị phần Response Header đã được giải mã khi
gửi yêu cầu đến <URL> bằng phương thức Get
 Bạn chỉ có thể xem, không chỉnh sửa, Tick "Line wrap" góc trái trên, để phần nội dung bị
tràn biên sẽ được xuống dòng mới

HTML:

1. DOM (Document Object Model)?


 Mỗi File được viết bởi ngôn ngữ đánh dấu được coi như 1 Rooted Tree, mỗi Node sẽ có
giá trị và thuộc tính riêng
 Để xem cấu trúc DOM của 1 File HTML, vào Link
https://software.hixie.ch/utilities/js/live-dom-viewer/
 Dán đoạn HTML vào mục "Markup to test", khi này tại mục "DOM view" sẽ hiện cấu trúc
DOM
 Node gốc sẽ là Node HTML, nó có 2 Node con là Node Head và Node Body, trong Node
Body là các Node chứa nội dung trang Web
 Các Leaf Node có thể là Node văn bản, Node hình ảnh, …
2. Phần Mở Rộng File HTML?
 ".html"
3. Cách Hoạt Động Của Ngôn Ngữ Đánh Dấu Trong Trình Duyệt?
 Khi ta gửi yêu cầu tới máy chủ đòi nội dung File đánh dấu, máy chủ trước tiên sẽ gửi về
nội dung của File này đã được mã hóa thành Byte Code, nghĩa là bây giờ máy ta sẽ nhận
được 1 chuỗi nhị phân, sau đó nó sẽ gửi Response Header ứng với File này, dựa vào
Response Header, ta biết chuỗi này được mã hóa bởi cơ chế mã hóa nào đó, ví dụ UTF 8,
khi này trình duyệt của ta sẽ sử dụng cơ chế giải mã hóa tương ứng, trong trường hợp
này là UTF 8, để biến chuỗi nhị phân nhận được thành các kí tự văn bản như trong File
đánh dấu ban đầu, đồng thời trong Response Header cũng có nói là nó thuộc kiểu ngôn
ngữ đánh dấu nào, ví dụ HTML, hay SVG, …, thuộc phiên bản bao nhiêu, … và dựa vào đó
để hiểu nội dung File này nó muốn làm gì, từ đó kết xuất nội dung trang Web ra trình
duyệt, lưu ý là ta có thể gửi yêu cầu tới chính máy của ta, chỉ cần dán đường dẫn tới File
đánh dấu trong máy ta lên trình duyệt
4. Khai Báo Phiên Bản Ngôn Ngữ Đánh Dấu Của File Đánh Dấu?
 Phần mở rộng File đã cho biết ngôn ngữ đánh dấu là gì
 Đặt dòng sau vào đầu File, nếu không đặt thì tự động hiểu là phiên bản cũ
<!DOCTYPE <Phiên Bản>>
 Ví dụ
<!DOCTYPE html>
 Dòng trên chỉ định ta dùng phiên bản HTML 5, là cái mới nhất
5. Cấu Trúc 1 File HTML?
 Dòng đầu là dòng khai báo ngôn ngữ đánh dấu
 Tiếp theo phải tạo Node HTML, Node Head và Node Body, nếu không tạo thì khi chạy
trên trình duyệt sẽ tự động thêm
<html>
<head>
</head>
<body>
</body>
</html>
 Các dấu cách hoặc dấu xuống dòng liên tiếp, đều quy về = 1 dấu cách, nếu chúng nằm
giữa 2 kí tự khác cách và xuống dòng
 Ví dụ
<body> a b </body>
 Phần Header do máy chủ gửi sẽ 1 phần dựa vào nội dung trong Node Head
 Trong Node Head, ta có thể tạo các Node sau
 Để đặt tiêu đề cho Tab, thêm Node tiêu đề
<title><Tiêu Đề></title>
- Khi này, Node Head sẽ có thêm Node con là Node tiêu đề, Node tiêu đề có Node con là
Node văn bản với nội dung là <Tiêu Đề>
 Trong Node Head, ta có thể tạo ra các Node con là các Node Meta chỉ định thông tin
Header
- Để chỉ định kiểu mã hóa ra Byte Code
<meta charset = <Kiểu Mã Hóa>>
- Ví dụ
<meta charset = "UTF-8">
- Để chỉ định tên người tạo ra Web
<meta name = "author" content = <Tên>>
- Ví dụ
<meta name = "author" content = "Huan">
- Để chỉ định từ khóa để Google tìm kiếm
<meta
name = "keywords"
content = "khabanh, daubuoi, cac"
>
- Để chỉ định mô tả ngắn cho trang Web
<meta name = "description" content = <Mô Tả>>
 Trình duyệt sẽ đọc từng Tag trong File HTML, và biến nó thành 1 Node trong DOM, khi
gặp phải Tag Script, nó sẽ chuyển sang chạy hết Code JS được đặt trong Tag này tại chỗ,
nghĩa là không gửi yêu cầu tới File JS bên ngoài, còn nếu Tag Script có chỉ định Link File JS
bên ngoài, thì nó sẽ gửi yêu cầu để nhận nội dung của File này và tiến hành chạy nó,
trong trường hợp này không được đặt Code JS trong Tag Script, trong trường hợp dùng
File bên ngoài, bạn được phép chỉ định thêm việc chạy nó sau khi DOM được tạo xong
xuôi hoặc chạy ngay lập tức, nếu chỉ định chạy sau khi DOM được tạo xong xuôi, thì File
JS này sẽ được đưa vào hàng đợi để chạy sau, song song với việc tạo DOM, trình duyệt
cũng tạo luôn CSSOM (CSS Object Model) có cấu trúc Rooted Tree như DOM, nhưng
chứa thông tin về kiểu cách của các loại Node trong DOM, khi gặp Tag Link có thuộc tính
rel = "stylesheet" chỉ định Link tới File CSS bên ngoài hoặc Tag Style với mã CSS bên
trong, thì trình duyệt sẽ dựa vào đó mà thêm thắt vào CSSOM, chỉ khi cả DOM và CSSOM
được tạo xong xuôi, chúng sẽ liên kết với nhau để tạo Render Tree, trình duyệt sẽ dựa
vào đây mà kết xuất nội dung ra màn hình, tuy nhiên, nếu bạn chỉ định thuộc tính style
cho Tag trực tiếp, thì nó sẽ ghi đè các thuộc tính trong CSSOM cho Tag này, khi mã JS của
bạn làm thay đổi cấu trúc DOM và CSSOM, thì Render Tree thay đổi, do đó khi đó trình
duyệt cũng sẽ cập nhật lại những thứ thay đổi trên trang Web
 Để tạo 1 Tag Script với Code JS bên trong
<script>
<Code JS Ở Đây>
</script>
 Để tạo 1 Tag Script sử dụng File JS bên ngoài
<script src = <Đường Dẫn Tới File JS Có Phần Mở Rộng>></script>
 <Đường Dẫn Tới File JS Có Phần Mở Rộng> có thể là đường dẫn tương đối, kể từ trong
thư mục chứa File HTML, hoặc URL tới File JS Online
 Trường hợp bạn lấy File JS từ URL Online, thì có thể thêm thuộc tính integrity với giá trị
là mã SHA của File JS này, mã SHA có được bằng cách đưa File JS vào 1 hàm để nó mã
hóa, nghĩa là nếu nội dung File JS Online bị thay đổi, thì mã SHA cũng sẽ thay đổi, và nếu
thêm thuộc tính integrity, File JS chỉ được tải về và chạy khi giá trị của integrity trùng với
mã SHA của File JS, khi thêm integrity thì cũng phải thêm thuộc tính crossorigin =
"anonymous"
 Để vẫn tải File JS trong khi DOM tải, nhưng khi tải xong thì đưa vào hàng đợi, khi nào
DOM và CSSOM tạo xong thì mới chạy, thêm thuộc tính defer
<script src = <Đường Dẫn Tới File JS Có Phần Mở Rộng> defer></script>
 Mặc định File JS được chạy không với tư cách là Module, do đó không dùng được
require, import, module.exports, để chỉ định File JS hoặc đoạn Code JS trong Tag Script là
1 ECMA Module, ta thêm thuộc tính type = "module", các ECMA Module sẽ luôn chỉ
được chạy sau khi DOM và CSSOM đã tạo xong xuôi, đồng thời, nếu có nhiều Tag Script
với ECMA Module có tên giống nhau, nó chỉ gửi yêu cầu 1 lần, lưu ý ECMA Module chỉ
chạy được trên Server, nghĩa là bạn Click chạy thẳng File HTML sẽ lỗi, cần dùng tạo 1
Server cục bộ tại thư mục chứa File HTML, như dùng tiện ích Go Live
 Ví dụ
<script type = "module" src = "foo.js"></script>
<script type = "module" src = "foo.js"></script>
- Khi này, trình duyệt chỉ gửi yêu cầu 1 lần duy nhất tới File "foo.js"
 Để tạo 1 Tag Style với mã CSS bên trong
<style>
<Mã CSS Ở Đây>
</style>
 Để chỉ định File CSS ở bên ngoài để trình duyệt gửi yêu cầu tới
<link rel = "stylesheet" href = <Đường Dẫn Tới File CSS Có Phần Mở Rộng>>
 Bạn có thể thêm thuộc tính integrity như khi tải File JS Online
 Ví dụ chỉ định thuộc tính style trực tiếp cho 1 Tag bằng mã CSS đặt trong 1 String
<h1 style = "color: red;"> ggnore </h1>
6. Comment HTML?
<!--<Đoạn Mã HTML Bị Comment>-->
7. Thuộc Tính Của Tag?
 Bạn có thể tạo thuộc tính bất kì với tên và giá trị bất kì cho nó trong Tag mà không có lỗi
gì xảy ra
8. Tag Không Làm Gì Cả?
 Khi bạn chỉ muốn bao văn bản vào 1 Tag, nhưng không muốn tạo kiểu cách mặc định cho
nó, dùng Tag Span
 Ví dụ
<span>abc</span>
9. Inline, Block, Inline Block?
 1 Node trong DOM chỉ có thể thuộc 1 trong 3 kiểu là Inline, Block hoặc Inline Block, mỗi
Node sẽ tương ứng 1 Box trên trang Web, 1 Box có 4 vùng từ thấp lên cao là Content
Box, Padding Box, Border Box và Margin Box
 Mặc định Node HTML thuộc kiểu Block, chiều rộng của nó = chiều rộng màn hình, nếu
nội dung trang mà vượt qua chiều rộng màn hình, thì sẽ có thanh cuộn ngang, chiều
rộng Node HTML vẫn = chiều rộng màn hình
 Node Body thuộc kiểu Block với Margin 8 px 4 phía, do đó nó nằm gọn trong Node
HTML, và do đó nằm gọn trong màn hình
 Xét 1 Node A bất kì thuộc kiểu Block, ta chỉ chú tâm đến Content Box của nó, tạm gọi
chiều rộng và chiều cao Content Box này là W và H, ta định nghĩa cách bố trí nội dung
theo đệ quy sau
 Coi nguyên trang Web chỉ là 1 chuỗi các kí tự và ảnh, mỗi kí tự và ảnh sẽ có kiểu cách
riêng áp lên nó
 Mỗi kí tự văn bản tách thành 1 Node đơn lẻ, gọi là Node kí tự, Node kí tự thuộc kiểu
Inline, Base Line của Node kí tự được xác định theo cơ chế sau, ví dụ xét chuỗi
"AyooÁe", thì Base Line của mỗi kí tự trong đây là đường thẳng chạm đít "A", "o", "e",
Bottom Line của mỗi kí tự trong đây là đường thẳng đi qua đầu cuống kí tự "y" và song
song Base Line, Top Line của mỗi kí tự trong đây là đường thẳng đi qua điểm cao nhất
của dấu sắc trong "Á" và song song Base Line
 Node kí tự chỉ có thể có Margin trái hoặc phải, Margin trên và dưới đều vô tác dụng,
Bottom Edge của mỗi Node kí tự là đường thẳng cách Middle Line, là gạch ngang kí tự
"e", một khoảng = thuộc tính CSS line-height của kí tự này / 2, và nằm bên dưới, Top
Edge tương tự nhưng nằm bên trên, lưu ý ở đây có thể có sai số
 Các Node ảnh đều là Node Inline Block, Content Box = cái ảnh, Base Line của nó = cạnh
dưới, Bottom Edge = cạnh dưới Margin Box, Top Edge = cạnh trên Margin Box
 A chỉ có thể có loại Node con là Inline, Block và Inline Block, trong Block sẽ chỉ chứa
Inline, trong Inline Block sẽ chứa cả Block và Inline, và trong Block con của Inline Block sẽ
chỉ chứa Inline, bây giờ ta sẽ xét từng trường hợp
 Trường hợp 1, ta đang đặt các Node Inline cũng như Inline Block vào A, các Node con
Inline và Inline Block sẽ đặt lần lượt từ trái qua phải, Margin trái thằng đầu tiên sẽ chạm
cạnh trái của Content Box của A, đặt sao cho Margin phải thằng bên trái chạm Margin
trái thằng bên phải, cho đến khi nào gặp phải Node con Block thì đưa Node con Block
này xuống dòng dưới, bắt đầu dòng mới và căn chỉnh lại dòng cũ, hoặc gặp phải Node kí
tự là dấu cách và đang tràn biên cạnh phải Content Box của A thì cũng xuống dòng, khi
gặp Node Break thì cũng xuống dòng ngay lập tức, căn chỉnh dòng như sau, Base Line
của các Node phải thẳng 1 hàng ngang, Top Edge cao nhất phải chạm Bottom Edge thấp
nhất của dòng bên trên, nếu là dòng đầu tiên thì phải chạm cạnh trên Content Box của A
 Trường hợp 2, Node con Block có tổng chiều rộng Content Box của nó + Margin +
Padding + Border mặc định sẽ bằng chiều rộng Content Box của A, tuy nhiên ta có thể
thay đổi chiều rộng này, Top Edge của Node con Block = cạnh trên Margin Box của nó,
Bottom Edge = cạnh dưới Margin Box, tất cả phần tử Inline nằm trong nó được sắp xếp
như khi sắp các Node Inline vào A, nếu không chỉ định chiều cao cho Content Box của
Node con Block này thì tự động = khoảng cách từ Bottom Edge thấp nhất của dòng thấp
nhất đến Top Edge cao nhất của dòng cao nhất trong Node con Block này, sau khi kết
xuất Node con Block này thì sẽ xuống dòng, Base Line của Node Block = Base Line của
dòng dưới cùng trong nó
 Nếu 2 dòng Node Block liên tiếp, thì Margin ở chỗ tiếp xúc của 2 thằng sẽ dung hợp, tức
là lấy Margin của thằng có Margin lớn hơn để ngăn cách Border
 Node con Inline Block , có thể chỉnh mọi thứ như chiều rộng, chiều cao Content Box của
nó, cũng Margin, Padding, Border sẽ có tác dụng cả 4 hướng, các Node con trong nó
được sắp xếp như khi sắp xếp các Node con Inline và Node con Block vào A, Base Line
của Node con Inline Block = Base Line của dòng cuối cùng trong nó, nếu ko chỉ định chiều
rộng cho Content Box của Node con Inline Block thì = tổng chiều dài của dòng dài nhất
bao gồm cả Margin, Padding, Border, cách bố trí thì đã nêu trong phần Inline, chỉ có điều
Bottom Edge của nó = cạnh dưới Margin Box và Top Edge = cạnh trên Margin Box như đã
nói ở phần ảnh
10. Tag Div?
<div>
<Nội Dung>
</div>
 = Span, nhưng thêm thuộc tính display = block, nghĩa là tạo Node Block
11. Tag Đề Mục?
<h<Số>>
<Đề Mục>
</h<Số>>
 <Số> phải là số nguyên từ 1 tới 6
 Các thuộc tính mặc định bao gồm display = block, margin-inline-start và end = 0, font-
weight = bold và các thuộc tính sau

<Số> font-size margin-block-start và end


1 2 em 0.67 em
2 1.5 em 0.83 em
3 1.17 em 1 em
4 1 em 1.33 em
5 0.83 em 1.67 em
6 0.67 em 2.33 em
12. Tag Đoạn Văn?
<p>
<Nội Dung>
</p>
 Các thuộc tính mặc định

Thuộc tính Giá trị


display block
margin-block-start 1em
margin-block-end 1em
13. Tag Ảnh?
<img src = <Link Ảnh> alt = <Văn Bản Thay Thế>>
 Lệnh trên sẽ gửi yêu cầu tới <Link Ảnh>, khi không nhận được ảnh sẽ hiện
1 kí tự ảnh + dấu cách vô hình + <Văn Bản Thay Thế>, và hoạt động y chang Node Inline,
khi này nó có các thuộc tính mặc định sau

Thuộc tính Giá trị


overflow clip
overflow-clip-margin content-box
 Nếu nhận được ảnh, thì hoạt động như Node Inline Block, với vùng Content Box luôn
chứa khít ảnh của bạn, mặc định kích thước Content Box = kích thước ảnh, bạn có thể
chỉ định nó thành Node Block cũng được, nhưng nếu chỉnh nó thành Inline thì sẽ bị đổi
thành Inline Block
14. Tag Video?
<video controls>
<source src = <Link Video 1>>
<source src = <Link Video 2>>

</video>
 Lệnh trên sẽ chọn Video đầu tiên mà trình duyệt hỗ trợ, ví dụ có trình duyệt chỉ hỗ trợ
".mp4" nhưng không hỗ trợ ".ogg", sau đó gửi yêu cầu tới <Link Video>, nếu không tồn
tại Video thì lỗi
 Cách hoạt động giống Tag ảnh, nhưng có vài nút bạn có thể bấm để chạy Video, phát
tiếng, tua, …, ban đầu Video chưa phát, bỏ thuộc tính controls sẽ mất mấy nút này
15. Tag Liên Kết?
 Để tạo 1 Link tới trang Web khác
<a href = <Link>><Nội Dung></a>
 Nội Dung> sẽ được hiển thị với kiểu cách, Click vào nó sẽ chuyển tới <Link>
 Nếu <Link> không phải Link tới trang Web khác, mà là 1 chuỗi nào đó, thì chuỗi đó sẽ
được thêm vào sau địa chỉ trên thanh Search
 Các thuộc tính CSS mặc định

Thuộc tính Giá trị


color #0000EE
text-decoration-line underline
cursor pointer
 Nếu không chỉ định thuộc tính href cho Tag a, thì nó chả khác mẹ gì Tag span
 Khi nhấn Link, không có Tab mới tạo ra mà Tab hiện tại sẽ bị chuyển hướng
16. Tag List Item?
<li>
<Nội Dung Item>
</li>
 Tag này chỉ có thuộc tính CSS display = list-item, do đó nó sẽ có lớp giả marker, và kí tự
đánh dấu mặc định là chấm đen
17. Tag Danh Sách Không Thứ Tự?
<ul>
<Danh Sách>
</ul>
 Các thuộc tính CSS mặc định

Thuộc tính Giá trị


display block
list-style-type disc
margin-block-start 1 em
margin-block-end 1 em
padding-inline-start 40 px
18. Tag Danh Sách Có Thứ Tự?
<ol>
<Danh Sách>
</ol>
 Giống y chang Tag ul nhưng thuộc tính CSS list-style-type = decimal
19. Tag Bảng?
<table>
<Nội Dung>
</table>
 Tag này sẽ có thuộc tính CSS mặc định display = table, tuy nhiên nếu ta không dùng Tag
table mà chẳng hạn dùng span, hay bất cứ Tag nào khác với display = table, nó đều vô
dụng, coi nó hoạt động như Block
 Các thuộc tính CSS mặc định

Thuộc tính Giá trị


border-collapse separate
text-indent 0 px
box-sizing border-box
border-spacing 2 px
border-color gray
 Trong <Nội Dung>, sẽ có 3 phần, Header, Body và Footer, nếu ta không tạo thì nó cũng
tự động tạo
 Header
<thead>
<Nội Dung Header>
</thead>
 Body
<tbody>
<Nội Dung Body>
</tbody>
 Footer
<tfoot>
<Nội Dung Footer>
</tfoot>
 Để tạo 1 hàng chứa các ô đặt vào 1 trong 3 phần này
<tr>
<Các Ô>
</tr>
 Mỗi ô sẽ đặt trong 1 Tag th hoặc td, th in đậm căn giữa, td không in đậm căn trái
 Ví dụ
<tr>
<th>foo</th>
<td>bar</td>
<th>bob</th>
</tr>
 Vì số ô ở các dòng có thể khác nhau, quy ước độ rộng cột thứ k = chiều rộng của ô có
chiều rộng lớn nhất trong cột thứ k
 Minh họa

20. Tag Input?


<input name = <Tên> type = <Loại> value = <Nội Dung Hiển Thị>>
 Tag trên hoạt động như Node Inline Block, tuy nhiên các thuộc tính CSS mặc định khá
phức tạp nên ta cũng không nên tạo kiểu lại cho nó làm gì
 Ta có

<Loại>
"checkbox" Ô vuông bo góc dùng để Tick hoặc Untick
Vòng tròn dùng để Tick, một khi đã Tick
không thể Untick, trong 1 File HTML, nếu
có nhiều Tag input với type = radio, và
"radio"
cùng giá trị name, thì chỉ có tối đa 1 vòng
tròn được Tick, Tick vòng khác, thì vòng
trước Untick
Khung chữ nhật bo góc, Click chuột vào để
"text" nhập văn bản, Click chuột ra để không
nhập nữa, văn bản nhập không bị xóa
Nút bấm, Click chuột vào để bấm, chữ trên
"submit" nút bấm = <Nội Dung Hiển Thị>, mặc định
là "Submit"
21. Tag Select?
 Tag này chỉ chứa Tag Option làm Tag con
<select name = <Tên>>
<option value = <Giá Trị 1>><Tên Option 1></option>
<option value = <Giá Trị 2>><Tên Option 2></option>

</select>
 Tag trên hoạt động như Node Inline Block, tuy nhiên các thuộc tính CSS mặc định khá
phức tạp nên ta cũng không nên tạo kiểu lại cho nó làm gì
 Nó giống như 1 Menu chọn tùy chọn, bạn sẽ chỉ chọn 1 trong các tùy chọn được liệt kê,
mỗi tùy chọn là 1 Tag Option, cái hiện ra là <Tên Option>, còn <Giá Trị> là thứ sẽ được
Submit khi bạn đặt Tag Select vào 1 Tag Form và Submit
22. Tag Button?
<button>
<Nội Dung>
</button>
 Tag trên hoạt động như Node Inline Block, <Nội Dung> sẽ được bao trong 1 nút bấm,
Click chuột lên nó để bấm
23. Tag Label?
<label for = <Bound ID>>
<Nội Dung>
</label>
 Chả khác mẹ gì Tag span, ngoại trừ việc có thêm thuộc tính CSS cursor = default
 Nếu chỉ định <Bound ID> là giá trị của thuộc tính id của 1 Tag nào đó, thì Tag Label này sẽ
bị gắn với Tag đó, và khi này nó sẽ có 1 số hiệu ứng đặc biệt
 Nếu Click vào Tag Label bị gắn với Tag Input loại ô Input văn bản, thì như việc bạn Click
vào ô Input đó để nhập, tương tự với các loại Input khác và Tag Select
24. Tag Form?
<form method = <Phương Thức> action = <Path Submit>>
<Nội Dung>
</form>
 Các thuộc tính CSS mặc định

Thuộc tính Giá trị


display block
margin-top 0 px
 Bất cứ khi nào 1 Tag Input với thuộc tính type = "submit" nằm trong <Nội Dung> bị bấm
vào, thì Tab hiện tại, từ URL hiện tại sẽ lập tức gửi yêu cầu tới URL có cùng Origin với
URL hiện tại, nhưng với Path là <Path Submit>, và chuyển hướng luôn tới URL này, nếu
không chỉ định <Path Submit>, thì gửi yêu cầu luôn tới URL hiện tại
 <Phương Thức> nếu không chỉ định thì mặc định là "get", tức phương thức Get, thì khi
chuyển hướng và gửi yêu cầu còn đính thêm Query lên URL, Query này dựa vào các phần
tử trong Tag Form, bao gồm các Tag Input, Select, …, Key = giá trị thuộc tính name của
chúng, và Value = giá trị thuộc tính value của chúng
 Nếu <Phương Thức> là "post", thì sẽ gửi yêu cầu với phương thức Post, khi này vẫn sẽ
chuyển hướng, nhưng không đính Query vào URL,
25. Thuộc Tính Lang?
 Thêm thuộc tính lang = <Ngôn Ngữ> vào 1 Tag để 1 số trình duyệt khi truy cập trang
Web của bạn, thì nếu <Ngôn Ngữ> khác xa tiếng Anh, như tiếng Việt, nó sẽ hỏi có muốn
dịch nội dung trong Tag này từ tiếng Việt sang tiếng Anh không, mặc định <Ngôn Ngữ> =
tiếng Anh
 Ta có

<Ngôn Ngữ>
"vi" Tiếng Việt
"en" Tiếng Anh
 Ví dụ
<h1 lang = "vi">
foo
</h1>
26. Favicon?
 Là biểu tượng nhỏ nằm bên trái tiêu đề Tab, để thêm Favicon
<link rel = "shortcut icon" href = "<Đường Dẫn Tới Favicon>">
 Ví dụ
<link rel = "shortcut icon" href = "foo.png">
27. Kí Tự Thoát?
 Ví dụ bạn muốn hiển thị chuỗi "<h1>gg</h1>" lên màn hình, nhưng đang tiếc là chỉ hiện
thị được "gg" do cái kia bị tưởng là Tag, để làm được điều này, ta sẽ dùng kí tự thoát
biểu diễn < và >, tương ứng là &lt; và &gt;
 Ví dụ, "&lt;h1&gt;gg&lt;/h1&gt;

CSS:

1. Thuộc Tính Kế Thừa?


 Có 1 số thuộc tính CSS nếu bạn không chỉ định ở Node con thì nó sẽ có giá trị = thuộc
tính CSS đó ở Node cha
 Các thuộc tính CSS còn lại không có tính kế thừa nếu bạn không chỉ định giá trị cho thuộc
tính CSS đó, thì nó sẽ được gán giá trị mặc định đã định sẵn
 Để trả về giá trị đã định sẵn, dùng initial
 Ví dụ
color: initial;
 Với thuộc tính không kế thừa, dùng từ khóa inherit để kế thừa
 Ví dụ
border: inherit;
2. Selector?
 Để áp kiểu cách lên Node trong DOM, cần phải xác định đó là những Node nào, việc làm
này thông qua Selector, cú pháp CSS như sau
<Selector> {
<Các Thuộc Tính Và Giá Trị>
}
 <Các Thuộc Tính Và Giá Trị> có cú pháp như sau
<Tên Thuộc Tính> : <Giá Trị>;
 <Selector> sẽ là thứ chỉ định Node được áp kiểu, ta có bảng giá trị ưu tiên sau

<Selector> Giá trị ưu tiên


* 0-0-0-0
<Tên Tag> 0-0-0-1
.<Tên Class> 0-0-1-0
#<ID> 0-1-0-0
- .<Tên Class> sẽ chọn tất cả các Node có thuộc tính class = <Tên Class>, lưu ý 1 Node có
thể thuộc nhiều Class, ngăn cách nhau bởi dấu cách, ví dụ class = "foo bar" thì vừa thuộc
Class foo vừa thuộc Class bar
- #<ID> sẽ chọn tất cả các Node có thuộc tính id = <ID>
- * sẽ chọn tất cả các Node trong DOM
- Giá trị ưu tiên được hiểu như sau, mỗi số trong chùm 4 không có giới hạn, ví dụ 11-100-
99-4 vẫn hợp lệ, và khi so sánh, thì so từ trái sang từng số một, ví dụ 99-4-9-5 sẽ lớn hơn
98-4-9-5 và cũng lớn hơn 99-4-8-5, giá trị ưu tiên của 1 Selector = tổng giá trị ưu tiên của
các Selector đơn lẻ hợp thành nó
 Ví dụ 1
h1 {
width: 100px;
}
 Thì thuộc tính CSS width của tất cả Tag h1 đều trở thành 100px, nhưng chỉ trong trường
hợp việc chỉ định thuộc tính CSS width trong đoạn CSS này có độ ưu tiên cao nhất, độ ưu
tiên hiện tại của nó = 0-0-0-1
 Ví dụ 2
.foo {
height: 100px;
}
 Tất cả các Node có thuộc tính class = "foo" đều được áp thuộc tính CSS height = 100px,
chỉ trong trường hợp đoạn CSS này có độ ưu tiên cao nhất, độ ưu tiên hiện tại của nó =
0-0-1-0
 Ví dụ 3
#bar {
background-color: red;
}
 Tất cả các Node có thuộc tính id = "bar" đều được áp thuộc tính CSS background-color =
red, chỉ trong trường hợp đoạn CSS này có độ ưu tiên cao nhất, độ ưu tiên hiện tại của
nó = 0-1-0-0
 Ví dụ 4, kết hợp nhiều Selector, phải viết sát nhau, tên Tag nếu có phải đặt ở đầu, có thể
lặp Selector để tăng độ ưu tiên
h1.foo#bar.foo.foo#bar {
color: blue;
}
 Tất cả các Tag h1 với id = "bar" và class = "foo" đều được áp thuộc tính CSS color = blue,
chỉ trong trường hợp đoạn CSS này có độ ưu tiên cao nhất, độ ưu tiên hiện tại của nó =
0-0-0-1 +(0-0-1-0) * 3 + (0-1-0-0) * 2 = 0-2-3-1
 Nếu chỉ định cùng 1 thuộc tính CSS trong 2 Selector khác nhau cùng độ ưu tiên, thì cái
viết sau sẽ được áp
 Khi bạn chỉ định trực tiếp, ví dụ width = 100px trong thuộc tính style của Tag nào đấy, thì
khi này độ ưu tiên của nó = 1-0-0-0
 Các thuộc tính CSS mặc định đã tích hợp sẵn vào Tag có độ ưu tiên = 0-0-0-0, do đó bạn
có thể ghi đè chúng bất cứ lúc nào
 Nếu bạn muốn việc chỉ định giá trị cho thuộc tính CSS nào đó có độ ưu tiên tối cao, tức là
độ ưu tiên = vô tận, thì thêm !impotant
 Ví dụ
h1 {
color: blue !important;
}
 Tất cả các Tag h1 đều được áp thuộc tính CSS color = blue, nó không thể bị ghi đè
 Tuy nhiên, nếu bạn thêm !important ở cả 2 nơi, thì nó sẽ chọn nơi có độ ưu tiên lơn hơn
khi bỏ !important, nếu bằng nhau thì chọn cái viết sau
 Các thuộc tính kế thừa có độ ưu tiên = 0-0-0-0
 Trong VS Code, bạn có thể xem độ ưu tiên của 1 Selector bằng cách di chuột lên nó
3. Combinator?
 Là phép kết hợp các Selector
 Để chỉ chọn những Node là Node con cháu của Node tổ tiên nào đó
<Node Tổ Tiên> <Node Con Cháu>
 Ví dụ
div p {
color: green;
}
 Khi này chỉ có những Tag p là con cháu của Tag div mới được áp thuộc tính CSS color =
green, độ ưu tiên = 0-0-0-1 + 0-0-0-1 = 0-0-0-2
 Để chỉ chọn những Node là Node con của Node cha nào đó
<Node Cha>><Node Con>
 Ví dụ
div>p {
color: green;
}
 Khi này chỉ những Tag p là con trực tiếp của Tag div mới được áp thuộc tính CSS color =
green, độ ưu tiên = 0-0-0-1 + 0-0-0-1 = 0-0-0-2
 Để chỉ chọn những Node là Node anh em và đứng ngay sau Node nào đó
<Node Trước>+<Node Sau>
 Ví dụ
div+p {
color: green;
}
 Khi này chỉ những Tag p là Tag anh em của Tag div và phải đứng ngay sau Tag div mới
được áp thuộc tính CSS color = green, độ ưu tiên = 0-0-0-1 + 0-0-0-1 = 0-0-0-2
 Để chỉ chọn những Node là Node anh em và đứng sau Node nào đó, không cần đứng
ngay sau
<Node Trước>~<Node Sau>
 Ví dụ
div~p {
color: green;
}
 Khi này chỉ những Tag p là Tag anh em của Tag div và đứng sau Tag div mới được áp
thuộc tính CSS color = green, độ ưu tiên = 0-0-0-1 + 0-0-0-1 = 0-0-0-2
 Tương tự như tên Tag, thông thường, bạn có thể kết hợp với Class và ID
 Ví dụ
h1~span#foo.bar {
color: green;
}
 Khi này chỉ những Tag span có id = "foo" và class = "bar" là Tag anh em của Tag h1 và
đứng sau Tag h1 mới được áp thuộc tính CSS color = green, độ ưu tiên = 0-0-0-1 + 0-0-0-
1 + 0-1-0-0 + 0-0-1-0 = 0-1-1-2
4. Nhóm Selector?
 Bạn có thể nhóm các Selector lại bằng dấu phẩy nếu thấy chúng có cùng giá trị các thuộc
tính, ví dụ
h1, h2 {
color: red;
}
 Tương đương
h1 {
color: red;
}
h2 {
color: red;
}
5. Font Size?
 Mặc định Node HTML có thuộc tính CSS "font-size: 16px;", tất cả các thuộc tính CSS liên
quan tới Font đều có tính kế thừa
 Đơn vị "em" nếu dùng trên thuộc tính CSS font-size của Node A thì 1 em = font-size của
Node cha của A, nếu dùng trên các thuộc tính CSS khác font-size như width, height, …
của A thì 1 em = font-size của A
6. Màu Thập Lục Phân?
 Thêm dấu # đằng trước
 Ví dụ
#0000EE
7. Màu Chữ?
color: <Màu>;
8. Gạch Chữ?
text-decoration-line: <Gạch Ở Đâu>;
 Ta có

<Gạch Ở Đâu>
none Mặc định, không gạch gì hết
overline Hiện Top Line lệch 1 tí của kí tự
Hiện Base Line xuống dưới 1 tí của kí tự,
underline nếu kí tự ví dụ như g, nó có cuống ở phía
dưới thì có thể che con mẹ nó underline
line-through Hiện Middle Line lệch 1 tí của kí tự
 Có thể hiện cùng lúc nhiều gạch, ví dụ
text-decoration-line: overline line-through;
 Để chỉ định kiểu gạch
text-decoration-style: <Kiểu Gạch>;
 Ta có

<Kiểu Gạch>
solid Mặc định, gạch thẳng
dashed Gạch đứt quãng
 Để chỉ định màu gạch
text-decoration-color: <Màu>;
 Để chỉ định độ dày gạch
text-decoration-thickness: <Độ Dày>;
 Có thể viết gộp 4 thuộc tính trên lại
text-decoration: <Các Thuộc Tính>;
 Ví dụ
text-decoration: overline underline dashed 10px red;
9. Viết In Đậm?
 Thêm thuộc tính CSS "font-weight: bold;"
10. Viết Số Kiểu Cách?
font-variant-numeric: <Kiểu Cách>;
 Thuộc tính CSS này có tính kế thừa
 Áp dụng cho toàn bộ kí tự số trong Node
 Ta có

<Kiểu Cách>
normal Mặc định, như bạn hay thấy
oldstyle-nums Viết các số với độ cao chênh lệch nhau
tabular-nums Chiều rộng mỗi số = nhau
11. Chuyển Sang In Hoa Hoặc In Thường?
text-transform: <Kiểu In>;
 Thuộc tính CSS này có tính kế thừa
 Ta có

<Kiểu In>
none Mặc định, không làm gì hết
uppercase Tất cả kí tự đều in hoa
lowercase Tất cả kí tự đều in thường
capitalize Biến kí tự đầu tiên mỗi từ viết hoa
12. Viết Chữ Từ Trên Xuống?
 Thêm thuộc tính CSS "writing-mode: vertical-lr"
 Xét Node có thuộc tính CSS này, quay Box của nó ngược chiều kim đồng hồ góc 90 độ,
được điểm nhìn A, gọi điểm nhìn cũ là B, viết chữ từ trái sang phải, hết dòng thì lên dòng
bên trên, bây giờ giới hạn không còn là chiều rộng mà là chiều cao màn hình, đồng thời
kí tự và ảnh trong mỗi dòng sẽ được căn giữa dòng, lưu ý ảnh không bị quay ở điểm nhìn
B
 Base Line so với viết theo kiểu ngang là kí tự bên phải cùng ở điểm nhìn A
 Tương tự "writing-mode: vertical-rl", quay Box 90 độ ngược chiều kim đồng hồ, viết từ
trái sang, hết dòng thì xuống dưới
 Ta có chỉ định thuộc tính CSS direction để xác định chiều viết, điểm nhìn trái phải sẽ bị
đảo ngược
direction: <Chiều>;
 Thuộc tính CSS này có tính kế thừa
 Ta có

<Chiều>
ltr Mặc định, đéo có gì để nói
Chưa đặt dòng vào Content Box vội, xét
mỗi dòng, lặp qua từng Node con, nếu bắt
rtl gặp Node Inline Block thì đẩy nó sang bên
phải Content Box, nếu gặp Node Inline, thì
đẩy 1 lúc hết phần còn lại
 Theo điểm nhìn A, margin-block-start = margin-top, margin-block-end =
margin-bottom, margin-inline-start = margin-left, margin-inline-end = margin-right,
tương tự cho cả padding
13. Hàm Trả Về Giá Trị Thuộc Tính Tag?
attr(<Tên Thuộc Tính>)
 Lệnh trên sẽ trả về String, do đó nó chỉ có thể áp dụng cho thuộc tính CSS content của
lớp giả before và after
 Ví dụ
h1::after {
content: attr(daucac);
}
 Khi này content = giá trị của thuộc tính daucac của Tag h1 được chọn
14. Đặt Biến?
 Biến được khai báo ở Node cha, sẽ có thể dùng lại ở Node con cháu
 Nếu 1 biến được khai báo 2 lần, thì lần nào Selector có độ ưu tiên cao hơn thì chọn, nếu
cùng độ ưu tiên thì lấy thằng viết sau
 Cú pháp
--<Tên Biến> : <Giá Trị>;
 Để trả về giá trị của 1 biến
var(--<Tên Biến>)
 Để nếu biến không tồn tại thì lấy giá trị mặc định nào đó
var(--<Tên Biến>, <Giá Trị Mặc Định>)
 Ví dụ
.foo {
--daucac: red;
--daulon: 10px;
}

.bar {
color: var(--daucac);
width: var(--daulon, 8px);
}
15. Padding?
 Để chỉ định Padding cho 1 phía
padding-<Phía>: <Kích Thước>;
 <Phía> phải là top, left, bottom hoặc right
 Ví dụ
padding-top: 10px;
 Để chỉ định Padding cho nhiều phía cùng lúc
padding: <Các Kích Thước>;
 Ta có

Số kích thước trong <Các Kích Thước> Áp dụng phía nào


1 Trái phải trên dưới
2 Trên dưới, trái phải
3 Trên, trái phải, dưới
4 Trên, phải, dưới, trái
 Ví dụ
padding: 10px 20px 30px;
 Khi này Padding trái = phải = 20px, Padding trên = 10px, Padding dưới = 30px
16. Margin?
 Cú pháp y chang Padding, thay mỗi chữ "padding" thành "margin"
17. Border?
 Border phân ra 4 phía, trên, dưới, trái, phải, bạn có thể tạo kiểu cách riêng cho mỗi phía
 Để chỉ định kích thước Border cho 1 phía
border-<Phía>-width: <Kích Thước>;
 Để chỉ định kích thước Border cho nhiều phía cùng lúc
border-width: <Các Kích Thước>;
 Để chỉ định kiểu Border cho 1 phía
border-<Phía>-style: <Kiểu Border>;
 Ta có

<Kiểu Border> Kết xuất


Đường thẳng bình thường, nếu kích thước
Border của phía nào không được chỉ định
solid
thì mặc định = 2px, nếu không chỉ định
màu cho Border thì mặc định màu đen
Đây là kiểu mặc định nếu không chỉ định
kiểu Border, tương đương việc không có
hidden
Border nào tồn tại, tương đương kích
thước = 0 bất chấp
 Để chỉ định kiểu Border cho nhiều phía cùng lúc
border-style: <Các Kiểu Border>;
 Để chỉ định màu Border cho 1 phía
border-<Phía>-color: <Màu>;
 Để chỉ định màu Border cho nhiều phía cùng lúc
border-color: <Các Màu>;
 Để ý thấy cú pháp nhiều phía tương tự Padding
 Để chỉ định cùng lúc nhiều thuộc tính CSS cho 1 phía
border-<Phía>: <Các Thuộc Tính>;
 <Các Thuộc Tính> bao gồm kiểu Border, kích thước, và màu
 Ví dụ
border-top: solid red 10px;
 Để chỉ định cùng lúc nhiều thuộc tính CSS chung cho 4 phía
border: <Các Thuộc Tính>;
 Ví dụ
border: solid red 10px;
18. Kích Thước Box?
 Dựa vào thuộc tính CSS box-sizing mà 2 thuộc tính sau áp cho Content Box, Padding Box,
hay Border Box
width: <Kích Thước>;
 Sau khi đã xác định được width, thì bạn có thể Clip nó lại bằng
min-width: <Chiều Rộng Tối Thiểu>;
max-width: <Chiều Rộng Tối Đa>;
 Để chỉ định chiều cao Content Box
height: <Kích Thước>;
 Sau khi đã xác định được height, bạn có thể Clip nó lại bằng
min-height: <Chiều Cao Tối Thiểu>;
max-height: <Chiều Cao Tối Đa>;
 Mặc định áp cho Content Box
 Để chuyển sang áp cho Box khác
box-sizing: <Box Khác>;
 Ví dụ
box-sizing: border-box;
 Khi này width và height chỉ định chiều rộng và chiều cao Border Box
 Lưu ý khi này nếu giảm width và height làm sao cho phần Content Box bị nén về hư vô,
thì có giảm xuống nữa vẫn không thay đổi gì
19. Màu Nền?
 Để chỉ định màu nền, lưu ý màu nền sẽ phủ kín Content Box, Padding Box hay Border
Box tùy thuộc vào thuộc tính CSS background-clip
background-color: <Màu>;
 Mặc định phủ Border Box, và bị tất cả những thứ như Border, chữ đè lên trên, để chỉ
phủ Box khác như Padding hay Content Box
background-clip: <Box Khác>;
 Ví dụ
background-clip: content-box;
20. Ảnh Nền?
 Để chỉ định ảnh nền, lưu ý ảnh nền sẽ phủ kín Content Box, Padding Box hay Border Box
tùy thuộc vào thuộc tính CSS background-clip
background-image: url(<Đường Dẫn Tới Ảnh>);
 Lệnh trên sẽ gửi yêu cầu tới <Đường Dẫn Tới Ảnh>
 Ví dụ
background-image: url("foo.png");
 Ngoài ra, bạn có thể chỉ định ảnh là 1 dải màu
linear-gradient(<Góc>, <Từ Màu>, <Đến Màu>)
 <Góc> = 0 tương ứng chiều mũi tên hướng từ dưới lên trên, tăng <Góc> thì quay cùng
chiều kim đồng hồ
 Dải màu sẽ từ gốc của mũi tên với màu = <Từ Màu>, lần theo hướng mũi tên mà chuyển
dần thành <Đến Màu>
 Các đơn vị <Góc>

deg Độ
 Dải màu coi như 1 ảnh nền, kích thước ảnh này mặc định = kích thước Box ứng với thuộc
tính CSS background-clip
 Ví dụ
background-image: linear-gradient(123deg, red, yellow);
 Bạn có thể chỉ định nhiều ảnh 1 lúc, ảnh viết trước thì hiện ở phía trên, một số thuộc
tính sẽ áp dụng chung cho các ảnh, ví dụ
background-image:
url("foo.png"),
url("bar.png"),
linear-gradient(123deg, red, yellow)
;
 Khi này, ta có thể chỉ định nhiều giá trị cho thuộc tính CSS background-clip, mỗi giá trị sẽ
ứng với 1 ảnh riêng, nghĩa là mỗi ảnh sẽ có vùng chứa khác nhau, thuộc tính CSS
background-color sẽ lấy Box đầu
 Ví dụ
background-clip: content-box, border-box;
 Gốc tọa độ để đặt ảnh sẽ tùy thuộc vào thuộc tính background-origin, mặc định là
Padding Box, do đó khi đặt ảnh, góc trái trên ảnh sẽ khít với góc trái trên Padding Box
background-origin: <Box Khác>;
 Phần ảnh vượt quá Box sẽ bị ẩn, tất cả mọi thứ sẽ đè lên ảnh nền trừ màu nền, mặc định
ảnh sẽ lặp lại theo cả chiều ngang và dọc, lặp theo cả chiều âm, để chỉ định nó chỉ lặp lại
theo 1 phương hoặc không lặp lại theo chiều nào
background-repeat: <Chiều Lặp>;
 Ta có

<Chiều Lặp> Cách lặp


Đây là mặc định, lặp theo cả phương ngang
repeat
lẫn dọc
repeat-x Chỉ lặp theo phương ngang
repeat-y Chỉ lặp theo phương dọc
no-repeat Không lặp
 Mặc định ảnh nền có chiều rộng và ngang = kích thước thực của nó, để điều chỉnh lại
background-size: <Chiều Rộng Mới> <Chiều Cao Mới>;
 Ví dụ
background-size: 10px 20px;
 Để đảm bảo tỉ lệ ngang / dọc như kích thước thực, dùng từ khóa auto và chỉ chỉ định 1
kích thước
 Ví dụ
background-size: 100px auto;
 Khi này chiều rộng ảnh = 100px, chiều cao sẽ tự xác định để tỉ lệ = tỉ lệ thực
 Để điều chỉnh lại tự động, giữ nguyên tỉ lệ ngang / dọc của các ảnh nền, thu nhỏ chúng
lại cho đến khi tất cả ảnh nền đều không có phần nào bị vượt biên khỏi Box ứng với
thuộc tính CSS background-clip
background-size: contain;
 Để điều chỉnh lại tự động, giữ nguyên tỉ lệ ngang / dọc của các ảnh nền, phóng to chúng
cho đến khi mỗi ảnh nền đều đủ sức bao kín Box ứng với thuộc tính CSS background-clip
background-size: cover;
 Để Offset ảnh nền khỏi gốc tọa độ
background-position: <Hoành Độ> <Tung Độ>;
 Lưu ý trục tung hướng xuống dưới
 Ví dụ
background-position: 10px 20px;
 Để tự động căn lề ảnh so với Box ứng với thuộc tính CSS background-clip
background-position: <Các Căn Lề>;
 Ta có
<Căn Lề>
center Căn giữa
left Căn trái
right Căn phải
bottom Căn dưới
top Căn trên
 Ví dụ
background-position: 10px center;
 Là ta đang Offset trái 10px và căn giữa ảnh theo chiều dọc
21. Tính Toán Với Các Đơn Vị Khác Nhau?
 Dùng hàm sau
calc(<Biểu Thức>)
 Ví dụ
width: calc(1em + 4px);
22. Lớp Giả?
 Loại lớp giả 1
<Selector>:<Trigger> {
<Mã CSS>
}
 <Mã CSS> sẽ được áp lên các Node chỉ định bởi <Selector> khi và chỉ khi hành động
<Trigger> được thực thi trên các Node này, và sau khi hành động này kết thúc, các kiểu
cách đã áp sẽ bị xóa
 Ta có

<Trigger> Khi nào kích hoạt


hover Khi bạn di chuột lên trên Node
active Khi bạn nhấn giữ chuột trái vào Node
Khi Node được chọn là Node con đầu tiên
first-child
của Node cha của nó
Khi Node được chọn là Node con cuối
cùng của Node cha của nó, lưu ý có vài
last-child trường hợp Tag Script vô tình được chèn ở
cuối Node Body, do đó Tag Script mới là
Node con cuối cùng của Node Body
Khi Node được chọn là Node con thứ
nth-last-child(<Index>) <Index> từ dưới lên của Node cha của nó,
<Index> = 1 tương đương last-child
 Ví dụ
h1:hover {
color: red;
}
 Loại lớp giả 2 tương tự

<Trigger> Áp vào đâu


:first-letter Kí tự đầu tiên
Dòng đầu tiên, tức là từ kí tự đầu tiên tới
:first-line
trước kí tự xuống dòng
 Ví dụ
h1::first-letter {
color: red;
}
 Loại lớp giả 3 đặc biệt

<Trigger> Cơ chế
Tạo 1 Node giả trước Node con đầu tiên,
:before
mặc định như 1 Node văn bản rỗng
Tạo 1 Node giả ngay sau Node con cuối
:after
cùng, mặc định như 1 Node văn bản rỗng
Nếu kí tự bị bôi đen thì áp kiểu không thì
:selection
thôi

 Ví dụ
h1::selection {
color: blue;
}
 Độ ưu tiên của lớp giả = độ ưu tiên của Class, ví dụ h1::selection = độ ưu tiên của h1 + độ
ưu tiên của selection = 0-0-0-1 + 0-0-1-0 = 0-0-1-1
23. Vị trí?
 Mặc định mỗi Node có thuộc tính CSS "position: static;", khi này, thuộc tính CSS top, left,
bottom, right sẽ vô tác dụng, nghĩa Node sẽ luôn đứng im tại chỗ
position: <Kiểu Vị Trí>;
 ta có

<Kiểu Vị Trí>
static Mặc định, không thể Offset
Gốc tọa độ là vị trí mặc định, tức là vị trí
khi position = static, có thể dịch sang phải
bằng left, dịch sang trái bằng right, dịch
xuống dưới = top và dịch lên trên bằng
relative bottom, nếu chỉ định left thì right vô dụng,
nếu chỉ định top, thì bottom vô dụng, khi
Offset, bản thể thật sự của nó vẫn đứng
yên, tức là phần nó chiếm chỗ vẫn như cũ,
chỉ có phần kết xuất ra là bị Offset
absolute Gốc tọa độ là góc trái trên Padding Box của
Node tổ tiên gần nhất có thuộc tính CSS
position khác static, nếu không tìm thấy thì
lấy Node HTML, tọa độ (0, 0) thì góc trái
trên của Border Box của Node này sẽ = gốc
tọa độ = góc trái trên của Padding Box của
Node tổ tiên đã nói, tuy nhiên điều này chỉ
áp dụng khi bạn chỉ sử dụng left và top,
nếu bạn sử dụng right và bottom, thì gốc
tọa độ sẽ là góc phải dưới của Padding Box
của Node tổ tiên đã nói, góc phải dưới
Border Box của Node này sẽ = gốc tọa độ
này khi tọa độ = (0, 0), cơ chế dịch tương
đồng với left và right, chỉ đảo chiều lại, nếu
cùng chỉ định left, right và width, thì right
bị lơ, nếu cùng chỉ định left và right nhưng
không chỉ định width, thì width sẽ tự điều
chỉnh, tương tự cho top và bottom và
height, còn một điều lưu ý nữa là Node
này sẽ bị bứt ra khỏi trang Web, nghĩa là
phần không gian nó chiếm khi position =
static sẽ được trả tự do, và Node này sẽ
trong trạng thái lơ lửng
Gốc tọa độ là góc trái trên màn hình, bứt
Node này ra khỏi trang Web cho nó nổi tự
do, phần không gian nó chiếm cũng bị trả
fixed
lại, coi màn hình là Node tổ tiên của nó, cơ
chế top, left, bottom, right y chang như
absolute
24. Xử Lí Tràn Biên?
 Giả sử nội dung bị tràn ra khỏi Padding Box của Node nào đó, bạn muốn ẩn nó đi và tạo
thanh cuộn, xử lí cả tràn ngang và tràn dọc
overflow: <Cách Xử Lí>;
 Ta có

<Cách Xử Lí>
Mặc định, không xử lí, hiện cả nội dung
visible
tràn
ẩn nội dung tràn khỏi Padding Box, kể cả
hidden
phần ảnh bị tràn
= hidden, nhưng có thêm 2 thanh cuộn, 1
cái nằm bên trái cạnh phải của Padding
scroll Box, 1 cái nằm bên trên cạnh dưới của
Padding Box, luôn hiện dù tràn hay không
tràn
auto = scroll, nhưng chỉ hiện thanh cuộn khi tràn
 Để chỉ xử lí tràn ngang hoặc tràn dọc
overflow-<Phương>: <Cách Xử Lí>;
 <Phương> = x là tràn ngang, = y là tràn dọc, nếu chỉ chỉ định 1 phương thì phương còn lại
mặc định = auto
 Nếu chỉ định theo cách này thì bạn không được phép chỉ định 1 phương visible và
phương còn lại không visible, để có thể làm được điều này, dùng clip, nó giống hidden
nhưng khi chỉ định lên 1 phương, thì phương còn lại được phép visible
 Ví dụ
overflow-x: hidden;
overflow-y: visible;
 Phương x hidden, phương y auto
overflow-x: clip;
overflow-y: visible;
 Phương x hidden, phương y visible
 Để hiện thêm 1 phần ngoài rìa Padding Box
overflow-clip-margin: <Kích Thước>;
 Lệnh này chỉ có tác dụng khi cả 2 phương đều dùng clip
 <Kích Thước> có thể là content-box, border-box, mặc định là 0px kể từ Padding Box
 Ví dụ
overflow: clip;
overflow-clip-margin: 20px;
 Nghĩa là sẽ hiện trong vùng Padding Box đã mở rộng thêm 20px ra 4 phía
25. Xử Lí Con Trỏ Chuột Khi Di Lên Content Box Của Node?
cursor: <Kiểu Con Trỏ>;
 Ta có

<Kiểu Con Trỏ>


auto Mặc định, hình con trỏ văn bản chữ I nếu
di lên chữ, hình mũi tên nếu di lên những
thứ khác
pointer Luôn là hình bàn tay
default Luôn là hình mũi tên
26. Căn Chữ?
text-align: <Kiểu Căn>;
 Thuộc tính CSS này có tính kế thừa, chỉ có tác dụng trên Node Inline Block hoặc Node
Block
 Ta có

<Kiểu Căn>
left Mặc định, đéo làm gì
Căn phải tất cả các Node con Inline và
right Inline Block, nghĩa là gạt chúng sang bên
phải
Căn giữa tất cả các Node con Inline và
center
Inline Block
Khi có từ 2 dòng chỉ chứa Node con Inline
hoặc Inline Block trở lên, các Node này sẽ
có khoảng trống cách nhau ra để Node đầu
justify
mỗi dòng chạm cạnh trái Content Box
Node cha, và Node cuối mỗi dòng chạm
cạnh phải Content Box Node cha
= left khi thuộc tính CSS direction = ltr và =
start
right khi thuộc tính CSS direction = rtl
= left khi thuộc tính CSS direction = rtl và =
end
right khi thuộc tính CSS direction = ltr
 Lưu ý tất cả kiểu căn chữ ở đây đều phụ thuộc vào điểm nhìn được xác định bởi thuộc
tính CSS writing-mode
 Để chỉnh sửa căn dòng cuối cùng
text-align-last: <Kiểu Căn>;
 Để thụt đầu dòng dòng đầu tiên, có thể thụt lùi, mặc định không thụt
text-indent: <Độ Thụt>;
27. Danh Sách?
display: list-item;
 Khi 1 Node có thuộc tính CSS trên, nó sẽ được xem là Node Block, đồng thời được tạo
thêm 1 lớp giả marker, đứng trước cả lớp giả before, lớp giả này có các thuộc tính CSS
mặc định sau

Thuộc tính Giá trị


font-variant-numeric tabular-nums
text-indent 0px !important
text-align start !important
text-align-last start !important
 Để tạo kiểu cho lớp giả này
<Tên Tag>::marker {
<Mã CSS>
}
 Trong <Mã CSS>, để xác định kí tự đánh dấu
content: "<Kí Tự>";
 Nếu <Kí Tự> gồm nhiều kí tự, nó lấy kí tự cuối cùng
 Ví dụ
span::marker {
content: "g";
}
 Để chỉ định kí tự đánh dấu từ Node cha cho Node con, đặt lệnh sau vào Node cha, lưu ý
bên phải kí tự đánh dấu sẽ có Margin ngắn
list-style-type: <Kí Tự>;
 Thuộc tính CSS này có tính kế thừa và sẽ bị thuộc tính CSS content của lớp marker của
Node con ghi đè
 Ta có

<Kí Tự>
disc Mặc định, chấm đen,
circle Đường tròn
Đánh số từ 1. trở đi, bắt đầu từ Node có
thuộc tính CSS này, lan truyền xuống phía
dưới bằng DFS, gặp Node có thuộc tính CSS
decimal display = list-item thì đánh số, gặp Node
con cũng có thuộc tính decimal thì tạo 1
Process con, DFS bên trong Node này, bắt
đầu từ 1.
28. Định Dạng Bảng?
 Các thuộc tính sau chỉ sử dụng được với Tag table
border-collapse: <Hợp Nhất Không>;
 Thuộc tính này có tính kế thừa
 Ta có
<Hợp Nhất Không>
seperate Các ô trong bảng sẽ có Border cho riêng nó
2 ô liền nhau trong bảng sẽ dùng chung
collapse
Border ở chỗ tiếp xúc
 Để Border của các ô cách nhau 1 khoảng, mặc định sát nhau, chỉ áp dụng khi border-
collapse = separate
border-spacing: <Khoảng Cách>;
29. Flex Box?
display: flex;
 Node Flex = Node Block, và khác khá nhiều thứ, nó có 2 trục là trục chính và trục phụ,
mặc định trục chính hướng từ trái sang phải, trục phụ từ trên xuống dưới
 Để thay đổi chiều trục chính và trục phụ
flex-direction: <Chiều>;
 Ta có

<Chiều> Chiều trục chính Chiều trục phụ


row Trái sang phải Trên xuống dưới
row-reverse Phải sang trái Dưới lên trên
column Trên xuống dưới Trái sang phải
column-reverse Dưới lên trên Phải sang trái
 Lưu ý chiều trục phụ ở đây đang xét trong trường hợp thuộc tính CSS flex-wrap = no-
wrap là cái mặc định hoặc wrap, nếu = wrap-reverse thì tất cả chiều trục phụ bảng trên
sẽ bị đổi ngược chiều
 Các bước để kết xuất 1 Node Flex
 Bước 1, khởi tạo, tất cả Node con đéo quan tâm thuộc tính CSS display, đều hành xử như
Inline Block, nghĩa là có thể chỉ định chiều rộng, chiều cao, …
 Bước 2, xếp các Node con dọc theo chiều trục chính lần lượt, sao cho cạnh phía gốc trục
phụ, ví dụ trục phụ từ trái sang phải, thì xét cạnh phía trái, của Margin Box của các Node
này thẳng hàng với nhau, và chỉ có 1 hàng duy nhất, có thu hẹp màn hình kiểu gì cũng 1
hàng
 Bước 3
 Trường hợp trục chính nằm ngang, các Node con thu hẹp tới chiều rộng tối thiểu, chiều
rộng này được xác định như sau, lưu ý đây là chiều rộng của Content Box
 Thuộc tính CSS flex-basis của Node con sẽ ghi đè thuộc tính CSS width của nó
 Nếu Node con đã chỉ định chiều rộng, và chiều rộng này < chiều rộng của từ có ít kí tự
nhất trong nó, thì đây là chiều rộng tối thiểu và cũng là chiều rộng tối đa
 Nếu Node con đã chỉ định chiều rộng = K, và chiều rộng này > chiều rộng của toàn bộ từ
trong nó, thì chiều rộng tối thiểu = chiều rộng từ có nhiều kí tự nhất, và chiều rộng tối đa
=K
 Nếu Node con không khai báo chiều rộng, chiều rộng tối thiểu = chiều rộng của từ có
nhiều kí tự nhất và chiều rộng tối đa = dòng có nhiều kí tự nhất
 Mỗi Node con có thuộc tính CSS flex-shrink mặc định = 1, nếu nó dần tới 0, thì chiều
rộng tối thiểu sẽ tăng dần tới chiều rộng tối đa, nghĩa là nếu = 0, thì chiều rộng tối thiểu
= chiều rộng tối đa, > 1 thì chiều rộng tối thiểu không đổi
 Trường hợp trục chính nằm dọc, thì cũng như trên, thay từ "rộng" thành "cao", "width"
thành "height", chỉ khác là chiều cao tối thiểu = chiều cao đủ đế chứa Full dòng, chiều
cao tối đa = chiều cao đã chỉ định, nếu không chỉ định thì = chiều cao tối thiểu
 Bước 4, nếu flex-wrap khác wrap, thì nếu chiều rộng Node Flex không đủ chứa toàn bộ
Node con khi chúng ở trạng thái tối đa kích thước, thì các Node sẽ xuống dòng, chiều
xuống dòng = chiều trục phụ
 Bước 5, dãn các Node con, các Node con từ kích thước tối thiểu sẽ dãn tới kích thước tối
đa, nếu không đủ chỗ thì ngừng dãn, cái nào mà chênh lệch giữa tối đa và tối thiểu lớn
hơn thì dãn nhanh hơn, đồng thời cái nào có flex-shrink lớn hơn sẽ tăng chậm hơn
 Bước 6, các Node con mặc định có thuộc tính CSS flex-grow = 0
 Xét phần không gian còn lại của Node Flex sau khi các Node con dãn ra tối đa, cho nó =
1, flex-grow chính là tỉ lệ phần trăm không gian này mà Node con có thể dãn ra để chiếm
nữa, ví dụ flex-grow = 0.3, thì sẽ dãn ra để chiếm 30% phần không gian còn lại, nếu tổng
flex-grow của các Node con > 1, thì sẽ được chuẩn hóa
 Ta có thể viết chung 3 thuộc tính CSS flex-grow, flex-shrink, flex-basis của mỗi Node con
trên 1 dòng bằng thuộc tính CSS flex
 Flex: <Flex Grow> <Flex Shrink> <Flex Basis>;
 Nếu chỉ chỉ định 2 giá trị
 Giá trị đầu tiên sẽ là <Flex Grow>
 Giá trị thứ 2 nếu là 1 số không có đơn, vị, thì nó sẽ là <Flex Shrink> và flex-basis tự động
= 0, ngược lại là <Flex Basis>, và flex-shrink tự động = 1
 Nếu chỉ định 1 giá trị
 Nếu là số không có đơn vị, nó sẽ là <Flex Grow>, flex-shrink = 1, flex-basis = 0
 Ngược lại, nó sẽ là <Flex Basis>, flex-grow = flex-shrink = 1
 Ta cũng có thể viết chung 2 thuộc tính CSS flex-direction, flex-wrap trong 1 dòng
flex-flow: <Flex Direction> <Flex Wrap>;
 Ta có thể tạo Node Inline Flex, giống Inline Block + Flex, Base Line là Base Line của kí tự
đầu tiên của Node con đầu tiên trong nó, nếu không có kí tự thì là cạnh dưới Padding
Box của Node con đầu tiên
display: inline-flex;
30. Căn Chỉnh Trong Node Flex?
 Để tạo khoảng không giữa các Node con trong Node Flex theo phương trục chính
justify-content: <Cách Chia>;
 Ta có

<Cách Chia>
Lấy hết phần không gian còn lại trong
space-between Node Flex, chia đều và đặt vào khe giữa
mỗi 2 Node con kề nhau
Giống space-between, nhưng trước Node
con đầu tiên và đằng sau Node con cuối
space-around
cùng sẽ có khoảng không = nửa khoảng
không giữa khe của 2 Node con liền kề
space-evenly Giống space-around, nhưng khoảng không
trước Node con đầu tiên và sau Node con
cuối cùng = khoảng không giữa khe của 2
Node con liền kề
 Ta có thể thay đổi thứ tự các Node con, ví dụ biến Node con đầu tiên thành Node con
thứ 2, …
order: <Index>;
 Ví dụ để biến Node con thứ 3 thành Node con thứ 5
order: 5;

YAML - YAML Ain't Markup Language:

1. Bố Cục?
 1 File YAML thường có phần mở rộng ".yml", nó cũng giống như JSON, dùng để lưu trữ
dữ liệu, cú pháp của nó = JSON nhưng bỏ tất cả ngoặc {} và dấu phẩy ngăn cách các phần
tử, các kiểu dữ liệu cho phép là String, số, Boolean, mảng, Object, String không cần bọc
trong dấu nháy, các thuộc tính của 1 Object thì phải thụt đầu dòng so với Object và
thằng hàng nhau, khoảng cách thụt bao nhiêu cũng được, nếu là mảng thì không dùng
dấu [], mà liệt kê ra mỗi phần tử trên 1 dòng, có thụt đầu dòng, đồng thời trước phần tử
phải có 1 dấu - và từ 1 dấu cách trở lên, các dấu - này phải thằng hàng nhau, nếu muốn
chỉ định 1 Object là 1 phần tử của mảng, thì chỉ cần dùng dấu - với Key đầu tiên, ví dụ
name: John Doe
age: 35
address:
street:
ggnore: 1
ga: 5
city: Anytown
state: CA
zip: 12345
hobbies:
- reading
- hiking
- cooking:
- shit
- cock
- longlon: 1
ggnore: 1
- longcu: 5
longchim:
gaga: 8
 Ở đây address là Key có nhiều thuộc tính, hobbies là mảng [reading, hiking, {cooking :
[shit, cock]}, {longlon : 1, ggnore : 1}, {longcu : 5, longchim : {gaga : 8}}]
 Giá trị Boolean thì có thể viết hoa hết, thường hết hoặc viết hoa chữ cái đầu, ví dụ true,
TRUE, True
SASS:

1. Cách Tải?
npm install node-sass --save-dev
 Khi này, trong thư mục con ".bin" của "node_modules", sẽ có File "node-sass.cmd"
2. Biên Dịch SCSS Ra CSS?
 File SCSS có phần mở rộng là ".scss"
 Để biên dịch 1 File SCSS thành 1 File CSS, dùng File "node-sass.cmd"
node_modules/.bin/node-sass.cmd <Đường Dẫn Tới File SCSS Có Phần Mở Rộng>
<Đường Dẫn Tới File CSS Có Phần Mở Rộng>
 Ví dụ
node_modules/.bin/node-sass.cmd foo/bar.scss boo/bob.css
 Để biên dịch tất cả các File SCSS con cấp 1 của thư mục A thành các File CSS cùng tên vào
thư mục B
node_modules/.bin/node-sass.cmd <Đường Dẫn Tới A> -o <Đường Dẫn Tới B>
 Ví dụ
node_modules/.bin/node-sass.cmd foo/bar -o alice/john/bob
 Để vào chế độ lắng nghe, tức nếu có thay đổi nào ở File SCSS thì nó sẽ tự động biên dịch
lại thành File CSS tương ứng, thêm cờ -w, tức là khi này sẽ có 1 Process tên "node.exe"
xuất hiện có nhiệm vụ lắng nghe các thay đổi trong các File SCSS chỉ định, ví dụ
node_modules/.bin/node-sass.cmd foo/bar.scss boo/bob.css -w
node_modules/.bin/node-sass.cmd foo/bar -o alice/john/bob -w
3. Cú Pháp SCSS?
 Y chang CSS, chỉ khác là có thêm 1 số lệnh mới
 Lệnh Import, trình biên dịch sẽ xử lí cái này trước
@import <Các Đường Dẫn>;
- <Các Đường Dẫn> bao gồm các đường dẫn tới các File SCSS không có phần mở rộng, mỗi
đường dẫn cách nhau dấu phẩy, bọc trong dấu nháy, khi biên dịch thì lần lượt toàn bộ
nội dung của từng File SCSS được liệt kê sẽ được đặt thẳng vào vị trí của lệnh Import kia,
thằng nào liệt kê sau thì đặt ở dưới, lệnh Import này đặt ở đâu cũng được, ví dụ
h1 {
background-color: red;
h2 {
color: red;
@import "conlon/concu1", "conlon/concu1";
}
}
- Lưu ý nếu tên File thật có dấu _ đằng trước, thì khi Import, bạn có thể bỏ 1 dấu _ này đi
 Lệnh Extend
@extend <Selector>;
- Khi trình biên dịch gặp lệnh này, thì nó sẽ rà soát lại toàn bộ các khối <Selector>, và
nhóm chúng lại với khối chứa lệnh trên, ví dụ
h2 {
color: black;
}
h1 {
background-color: red;
h3 {
color: blue;
@extend h2;
}
}
h2 {
font-size: 100px;
}
- Tương đương
h2, h1 h3 {
color: black;
}

h1 {
background-color: red;
}

h1 h3 {
color: blue;
}

h2, h1 h3 {
font-size: 100px;
}
 Lệnh Mixin, dùng để tạo hàm
@mixin <Tên Hàm>(<Các Tham Số>){
<Danh Sách Các Thuộc Tính CSS Có Sử Dụng Tham Số Truyền Vào>
}
- Tên hàm chỉ gồm chữ cái hoặc số hoặc dấu - hoặc _, không được bắt đầu bằng số, tên
tham số cũng vậy nhưng bắt đầu phải là kí tự $, ví dụ $foo-bar123
- Để truyền đối số cho hàm, rồi đặt phần bên trong hàm vào chính vị trí lệnh sau
@include <Tên Hàm>(<Các Đối Số>);
- Ví dụ
@mixin foo($bar, $alice){
background-color: $bar;
color: $alice;
}
h1 {
font-size: 100px;
@include foo(red, #fff);
width: 100px;
}
- Tương đương
h1 {
font-size: 100px;
background-color: red;
color: #fff;
width: 100px;
}
 Lồng nhau, bạn có thể lồng phần hiện thực các Selector vào bên trong nhau để thể hiện
tính cha con, ví dụ
nav {
color: red;
ul {
list-style: none;
margin: 0;
padding: 0;
}
li {
display: inline-block;
}
}
- Tương đương
nav {
color: red;
}
nav ul {
list-style: none;
margin: 0;
padding: 0;
}
nav li {
display: inline-block;
}
 Toán tử cộng 2 giá trị cùng kiểu như 1px + 2px, 1rem + 2rem, red + blue, …, toán tử trừ 2
giá trị cùng kiểu như 1px - 2px, …
 Khai báo biến
<Tên Biến>: <Giá Trị>;
- <Tên Biến> phải tuân theo quy tắc như tham số hàm, nó cũng tuân theo Scope, đặt
trong Scope nào thì chỉ dùng được ở Scope đó, và phải khai báo trước khi sử dụng, ví dụ
$foo-bar123: 100px;
h1 {
width: $foo-bar123;
}
4. Normalize CSS?
 Để cài thư viện Normalize CSS
npm install normalize.css
 Khi này, trong File SCSS, bạn có thể dùng lệnh sau để nhúng CSS của thư viện này vào,
thư viện này bản chất là có sẵn các CSS tiêu chuẩn đẹp
@import "normalize.css";
5. Font?
 Bạn có thể dùng Import với đường dẫn là URL trên mạng, thì nó sẽ tải CSS trên đường
dẫn này về
@import url(<URL Bọc Trong Nháy>);
 Bạn có thể kiếm Font thông qua Link https://fonts.google.com/
 Về Tab "Fonts"
- Nút "Filters" góc trái trên để ẩn hiện Panel lọc, Panel lọc gồm
a) Mục "Preview", bạn gõ thứ gì đó vào trong, thì phần bên phải sẽ hiện thị dòng chữ đó
với các Font được liệt kê
b) Thanh trượt Pixel ở dưới là Font Size
c) Mục "Language" để lọc ra các Font dành cho ngôn ngữ nào đó
- Phần bên dưới liệt kê tất cả các họ Font, bạn có thể lọc ra = cách nhập tên họ Font vào
thanh tìm kiếm trên cùng
- Click vào 1 họ Font sẽ vào phần chi tiết họ Font đó
a) Nút "Get font" để thêm họ Font này vào giỏ hàng
- Nút giỏ hàng góc phải trên, Click vào để xem giỏ hàng
a) Nút "Get embed code", Click vào, rồi Copy URL Import mong muốn, nó sẽ Import hết các
họ Font trong giỏ hàng, ở đây có hiện tên họ Font để bạn dùng cho thuộc tính font-
family trong CSS hoặc SCSS

Bootstrap:

1. Cách Tải?
 Vào Link https://getbootstrap.com/docs/ để xem tài liệu, muốn thành phần nào lên đây
Copy
 Tại mục "Getting started", Tab "Download"
 Tùy chọn "Compiled CSS and JS", Click "Download" để tải về File nén, trong File nén này
có 1 thư mục, trong đây lại có 2 thư mục tên "css" và "js", thư mục "css" sẽ chứa tất cả
File CSS bạn cần, Link hết chúng vào HTML, tương tự File "js" chứa tất cả File JS bạn cần,
Link hết chúng vào HTML
 Tùy chọn "CDN via jsDelivr", Copy 2 dòng đầu vào HTML để Link File Online
2. Thanh Điều Hướng?
 Vào mục "Components", Tab "Navbar"

Electron:
1. Cách Tải?
npm install electron electron-packager electron-builder --save-dev
 Khi này, trong thư mục con ".bin" của "node_modules", sẽ có File "electron.cmd",
"electron-packager.cmd", "electron-builder.cmd", Electron hoạt động khác giống Node
JS, là 1 môi trường chạy File JS
2. Chạy 1 File JS Trong Môi Trường Electron?
 Dùng File "electron.cmd"
node_modules/.bin/electron.cmd <Đường Dẫn Tới File JS Không Cần Phần Mở Rộng>
 Lưu ý nếu không chỉ định File JS, hoặc chỉ định nó là ".", thì Electron sẽ dò trong File
"package.json" trong thư mục làm việc hiện tại, xem có thuộc tính "main" hay không,
nếu không thì lỗi, nếu có thì sẽ chạy đường dẫn tới File JS được chỉ định bởi thuộc tính
"main" này
 Khi này sẽ có 3 Process tên "electron.exe" sẽ xuất hiện, File JS dừng thì môi trường
Electron vẫn chạy
3. Tạo Ứng Dụng Trên Windows?
 Trước tiên, lệnh Import sau chỉ có tác dụng trên môi trường Electron
 Common Module
const <Electron> = require("electron")
 ECMA Module
import <Electron> from "electron"
 Ngay sau khi Import, <Electron> sẽ tự động khởi tạo để có thể sử dụng
 Lệnh sau trả về 1 Promise bất đồng bộ, sẽ Fullfilled khi <Electron> khởi tạo xong
<Electron>.app.whenReady()
 <Electron> sẽ có nhiều Event, mỗi Event lại có 1 Stack các Call Back sẽ được gọi lần lượt
khi Event được kích, để thêm 1 Call Back vào 1 Event
<Electron>.app.on(<Tên Event>, <Call Back>)
 Ta có bảng Event sau

<Tên Event> Kích khi


"ready" <Eletron> được khởi tạo xong

 Trong <Electron>, bạn có thể tạo nhiều cửa sổ Windows, lệnh sau sẽ tạo ra 1 cửa sổ và
trả về <Window Object> ứng với cửa sổ này
<Electron>.BrowserWindow(<Tùy Chọn>)
 <Tùy Chọn> là 1 Object viết theo Dictionary, quy định các thuộc tính của cửa sổ, nếu
<Tùy Chọn> không được chỉ định thì nó = {}
 Bảng các thuộc tính của <Tùy Chọn>

Thuộc tính Giá trị


1 số nguyên = chiều rộng cửa sổ theo Pixel,
width
mặc định = 800
1 số nguyên = chiều cao cửa sổ theo Pixel,
height
mặc định = 600
4. Đóng Gói Electron Thành EXE?
 Dùng File "electron-builder.cmd"
node_modules/.bin/electron-builder.cmd build --win portable
 Lệnh trên sẽ dò trong thư mục làm việc hiện tại xem có File "package.json", nếu không
sẽ lỗi, nếu có thì File "package.json" này có thuộc tính "name", "author", "version" và
"main", "name" sẽ là tên của File EXE không có phần mở rộng, "author" phải là 1 Object
viết theo Dictionary, có thuộc tính "name" là tên người tạo ra ứng dụng, "version" là số
phiên bản ứng dụng, "main" là đường dẫn tới File JS ngõ vào chương trình
 Khi này sẽ có thư mục "dist" xuất hiện trong thư mục làm việc hiện tại, trong đây có thư
mục "win-unpacked", trong đây có File EXE, bạn có thể Copy File EXE ra bất kì chỗ nào
cũng chạy được

Mongo DB:

1. Mongo DB Atlas?
 Cái này dùng để lưu cơ sở dữ liệu trên máy chủ của nó không cần lưu trên máy của
mình, vào Link https://cloud.mongodb.com, đăng nhập = tài khoản Google
 Mỗi tài khoản sẽ thuộc nhiều tổ chức khác nhau, mỗi tổ chức sẽ gồm nhiều thành viên,
trong đó có 1 người làm chủ, các chức vụ khác, cấp thấp nhất là dân đen
 Mỗi tổ chức cũng sẽ có nhiều dự án khác nhau, mỗi dự án lại có nhiều Cluster
 Người làm chủ 1 tổ chức sẽ có quyền tuyển thành viên vào tổ chức, xóa tổ chức, tạo xóa
dự án, dự án chỉ có thể xóa được khi tất cả Cluster trong nó bị xóa, và tổ chức chỉ có thể
bị xóa khi tất cả dự án trong nó bị xóa
 Dân đen không có quyền tuyển thành viên hay xóa tổ chức hay tạo xóa dự án
 Mỗi dự án bao gồm một vài thành viên trong tổ chức đảm nhận, với các chức vụ khác
nhau, có thể nhiều người có cùng 1 chức vụ, kể cả chủ dự án, và 1 người có thể đảm
nhận nhiều chức vụ khác nhau, mỗi dự án cũng bao gồm nhiều đội, nhiều cảnh báo và
nhiều cặp Key Value
 Mỗi dự án sẽ bao gồm nhiều khách hàng, mỗi khách hàng có 1 khả năng khác nhau,
nhiều khách hàng có thể chung 1 khả năng
 Khi mời 1 người vào dự án, mà người đó đã có trong tổ chức, thì người đó sẽ vào ngay
không cần ý kiến, nếu mời người ngoài tổ chức, thì nếu người đó chấp nhận, họ cũng sẽ
vào tổ chức luôn với tư cách dân đen
 Replica Set là 1 tập hợp gồm các máy chủ ở những nơi khác nhau, lưu cùng 1 cơ sở dữ
liệu, nghĩa là nếu máy chủ này mất, thì sẽ có máy khác đảm nhận vai trò đọc ghi, khi ghi
vào 1 máy, thì các máy khác cũng ghi theo, Replica Set là 1 kiểu Cluster
 Kiểu Replica Set 3 Node, thì sẽ có 1 máy Primary và 2 máy Secondary, máy Primary có
quyền đọc ghi còn 2 máy kia chỉ có thể đọc
 1 Cluster sẽ đặt ở 1 khu vực nào đó, như Hồng Kông, được cung cấp bởi 1 nhà cung cấp
dịch vụ điện toán đám mây nào đó, như AWS, và có 1 dung lượng tối đa nhất định, tùy
theo loại Cluster, Cluster có các loại là M0 Sandbox, M10, …, trong đó 1 dự án chỉ có thể
có duy nhất 1 Cluster M0 Sandbox, vì nó miễn phí, những cái còn lại phải bỏ tiền
 1 Cluster sẽ có nhiều cặp Key Value, và nó chỉ cho phép 1 số Modem có địa chỉ IP nhất
định có thể kết nối tới nó, theo mô hình MVC, bạn sẽ đặt các IP này là IP của máy chủ
Host trang Web của bạn, để nó có thể truy cập cơ sở dữ liệu
 Về phương diện cơ sở dữ liệu, 1 Cluster sẽ bao gồm nhiều cơ sở dữ liệu, mỗi cơ sở dữ
liệu sẽ bao gồm nhiều Collection, mỗi Collection sẽ bao gồm nhiều Document, mỗi
Document giống như 1 Object viết theo Dictionary
 Về giao diện, ban đầu bạn sẽ trong trang con tổ chức, Link là
https://cloud.mongodb.com/v2#/org, gồm 3 phần
 Thanh trên cùng là thanh hoa tiêu
- Biểu tượng "Atlas", Click vào để về Tab "Projects"
- Mục kế bên là mục chọn tổ chức làm việc hiện tại, Click "View All Organizations" sẽ vào
trang con chỉnh sửa tổ chức tại Tab "Organizations"
- Biểu tượng bánh răng kế, Click vào để sang Tab "Settings"
- Mục "Access Manager" chọn "Organization Access" để sang Tab "Access Manager"
- Mục "Billing", Click để vào Tab "Billing"
- Mục "All Clusters", Click để vào trang con All Cluster
- Mục bên phải cùng là tên đại diện của bạn, Click vào để mở Panel cá nhân
a) Mục "Organizations", Click để vào trang con chỉnh sửa tổ chức tại Tab "Organizations"
b) Mục "Invitations", Click để vào trang con chỉnh sửa tổ chức tại Tab "Invitations"
 Panel bên trái là Panel điều hướng
 Phần to nhất bên phải là phần làm việc, khác nhau với mỗi Tab trong Panel điều hướng,
mọi Tab thì phần làm việc đều có phần Link điều khoản ở dưới cùng
- Về Tab "Projects", liệt kê tất cả dự án thuộc tổ chức làm việc hiện tại
a) Cột "Project Name", tên dự án, Click vào sẽ chuyển tới trang con dự án chi tiết tương
ứng
b) Cột "Clusters", số Cluster của dự án
c) Cột "Tags", hiện tất cả cặp Key Value của dự án lần lượt, Key in đậm đứng trước, Value
in nhạt đứng sau
d) Cột "Users", hiện số thành viên trong dự án, Click vào để vào trang con dự án chi tiết
tương ứng, nhưng vào phần con Project, tại Tab "Access Manager", Tab con "Users"
e) Cột "Teams", hiện số đội trong dự án, Click vào để vào trang con dự án chi tiết tương
ứng, nhưng vào phần con Project, tại Tab "Access Manager", Tab con "Teams"
f) Cột "Alerts", hiện số cảnh báo trong dự án, Click vào để vào trang con dự án chi tiết
tương ứng, nhưng vào phần con Project, tại Tab "Alerts", Tab con "Open Alerts"
g) Nút "New Project", tạo dự án mới, nhập tên dự án, các cặp Key Value + Click "Next" +
nhập Email mời người khác vào dự án, cơ chế mời đã biết, chỉnh chức vụ trong dự án
cho từng người được mời + Click "Create Project"
 Về trang con dự án chi tiết, Link là https://cloud.mongodb.com/v2
 Vẫn còn thanh hoa tiêu với chức năng đã biết ở trên cùng
 Thêm thanh hoa tiêu phụ ở dưới
- Mục đầu tiên chọn dự án làm việc hiện tại của tổ chức hiện tại
- Nút hình người bên phải, Click để vào phần con Project, tại Tab "Access Manager", phần
mời mọc
 Panel điều hướng khác so với cũ
 Phần làm việc khác nhau với mỗi Tab ở Panel điều hướng và Tab ở thanh hoa tiêu phụ,
nhưng cũng đều có phần Link điều khoản phía dưới cùng và dòng trên cùng bên trái là
tên tổ chức và tên dự án làm việc hiện tại, ở dưới là tên Tab
- Về Tab "Database" ở Panel điều hướng + Tab "Data Services" ở thanh hoa tiêu phụ
a) Phần bên dưới liệt kê từng Cluster trong dự án hiện tại từ trên xuống dưới trong các
khối, góc trái trên là tên Cluster, Click vào sẽ vào phần chỉnh sửa chi tiết Cluster đó, dòng
kế cuối, mục "VERSION" là phiên bản Cluster, "REGION" là nhà cung cấp và khu vực đặt
Cluster, "CLUSTER TIER" là loại Cluster, "TYPE" là kiểu Cluster, dòng cuối là các cặp Key
Value của Cluster, ô "Data size" hiển thị dung lượng bạn đã dùng / dung lượng tối đa,
nút 3 chấm phía trên, chọn "Terminate" để xóa Cluster này, nút "Connect" góc trái trên,
Click để hiện hướng dẫn kết nối với Cluster này, ví dụ cách để kết nối sử dụng Node JS
b) Ô tìm kiếm góc trái trên, để lọc các Cluster, chọn ra các Cluster có tên chứa chuỗi được
nhập
c) Nút "Create" góc phải trên để tạo thêm Cluster, bạn sẽ chọn loại Cluster, nhà cung cấp,
khu vực, tên Cluster, các cặp Key Value, phương pháp thanh toán bằng Credit Card hoặc
Paypal
- Về Tab "Network Access" ở Panel điều hướng + Tab "Data Services" ở thanh hoa tiêu
phụ
a) Tab con "IP Access List", liệt kê tất cả địa chỉ IP có thể kết nối với các Cluster thuộc dự án
này, cột "IP Address" là địa chỉ IPv4 kèm theo Subnet Mask viết theo kiểu CIDR để mô tả
khoảng địa chỉ IP cho phép, cột "Comment" là mô tả địa chỉ IP, cột "Actions" có nút
"DELETE" để xóa địa chỉ IP này và nút "EDIT" để chỉnh sửa địa chỉ IP và mô tả, nút "ADD
IP ADDRESS" góc phải trên để thêm địa chỉ IP, viết kiểu CIDR, thêm mô tả, Tick "This
entry is temporary and will be deleted in" và chọn khoảng thời gian phù hợp để địa chỉ
IP này tự động xóa, Click "Confirm" để thêm
- Về Tab "Database Access" ở Panel điều hướng + Tab "Data Services" ở thanh hoa tiêu
phụ
a) Tab con "Database Users", liệt kê tất cả khách hàng của dự án làm việc hiện tại, cột
"User Name" là tên khách hàng, Cột "Authentication Method" là phương pháp xác thực
khi khách hàng kết nối với các Cluster của dự án, ví dụ SCRAM, cột "MongoDB Roles" là
khả năng của khách hàng, cột "Resources" là số lượng Cluster khách hàng có thể dùng,
nút "DELETE" bên phải cùng để xóa khách hàng, nút "EDIT" để chỉnh sửa thông tin khách
hàng như mật khẩu mới, khả năng mới, nút "ADD NEW DATABASE USER" góc phải trên,
để tạo khách hàng mới, nhập tên khách hàng, phương thức xác thực là sử dụng mật
khẩu hay cái khác, điền mật khẩu, khả năng, giới hạn các Cluster khách hàng này có thể
dùng, thời gian khác hàng này tồn tại trước khi bị tự động xóa
 Về trang con All Cluster, Link là https://cloud.mongodb.com/v2#/clusters
 Nút lá góc trái trên, Click vào để về trang con dự án chi tiết
 Tên đại diện góc phải trên, cơ chế Panel cá nhân đã biết
 Thanh tìm kiếm bên phải
 Thanh dưới có 4 mục là thanh lọc
 Phần bên dưới liệt kê tất cả Cluster của tất cả dự án của tất cả tổ chức, mỗi dự án trong
1 tổ chức sẽ liệt kê tất cả Cluster trong nó trong 1 khối
- Dòng đầu là <Tên Tổ Chức>/<Tên Dự Án>
- Cột "Name", tên Cluster
 Về trang con chỉnh sửa tổ chức, Link là https://cloud.mongodb.com/v2#/preferences,
gồm 3 phần
 Thanh trên cùng là thanh hoa tiêu giống với trang con tổ chức, mất 1 số nút
 Panel bên trái là Panel điều hướng
 Phần to nhất bên phải là phần làm việc, khác nhau với mỗi Tab trong Panel điều hướng
 Về phần con Project của trang con dự án chi tiết
 Về Tab "Access Manager"
- Nút "Invite to Project" góc phải trên, Click để vào phần mời mọc, tại đây bạn nhập Email
của các người bạn muốn mời vào tham gia dự án kèm theo chức vụ của họ
- Về Tab con "Users", liệt kê tất cả thành viên trong dự án làm việc hiện tại
a) Cột "Display Name", tên đại diện
b) Cột "Email Address", địa chỉ Email
c) Cột "Project Role", các chức vụ người này đảm nhận trong dự án
d) Nút hình thùng rác bên phải cùng, để xóa thành viên này ra khỏi dự án
e) Nút hình bút chì bên phải, để chỉnh sửa chức vụ của thành viên này
2. Phần Chỉnh Sửa Chi Tiết Cluster?
 Góc trái trên là tên Cluster, góc phải trên là phiên bản, khu vực và loại Cluster
 Về Tab "Overview"
 Mục "TAGS" hiển thị các cặp Key Value của Cluster
 Mục "REGION" hiển thị khu vực Cluster được đặt
- Đối với kiểu Cluster Replica Set 3 Node, thì nó sẽ liệt kê 3 Link đến phần chi tiết máy chủ
Cluster, 2 máy Secondary và 1 máy Primary
 Về URI để kết nối với Cluster, bạn sẽ thấy nó trong phần hướng dẫn kết nối, lưu ý bỏ
phần Query đằng sau
mongodb+srv://<Tên Khách Hàng>:<Mật Khẩu Khách Hàng>@<Tên Cluster
Thường>.<Tên Cluster Thừa>.mongodb.net/
 Có thể thấy bạn sẽ kết nối với Cluster với tư cách là 1 khách hàng nào đấy của dự án
chứa Cluster này, và do đó sẽ có thể bị giới hạn quyền đọc, viết tùy theo khả năng của
khách hàng
 Khi bạn đặt tên Cluster là "FooBar123", thì đây là <Tên Cluster Thật>, còn <Tên Cluster
Thường> sẽ viết thường tất cả thành "foobar123", <Tên Cluster Thừa> là 1 chuỗi Mongo
DB Atlas đã tự thêm vào, nghĩa là tổ hợp <Tên Cluster Thường>.<Tên Cluster Thừa> là
độc nhất trên thế giới
3. Cách Tải Mongo DB Về Máy?
 Cái này dùng để tạo cơ sở dữ liệu trên chính máy tính của bạn luôn, máy của bạn sẽ vừa
là Server máy chủ, vừa là máy khách
 Vào Link https://www.mongodb.com/try/download/community, cuộn xuống Click
"Download" + chờ tải + chạy File vừa tải + Click "Next" + Tick chấp nhận điều khoản +
Click "Next" + chọn "Complete" + Click "Next" + bỏ Tick "Install MongoDB Compass" +
Click "Next" + Click "Install" + chờ cài đặt + Click "Finish"
 Sau khi làm xong, trong thư mục "C:\Program Files" sẽ xuất hiện thư mục "MongoDB",
trong đây có thư mục "Server", trong nữa có thư mục tên phiên bản Mongo DB, trong
nữa có thư mục "bin", trong đây chứa 2 File lệnh "mongod.exe" và "mongos.exe", nên
thêm thư mục "bin" vào biến môi trường Path
4. Mongo DB Compass?
 Vào Link https://www.mongodb.com/try/download/compass, cuộn xuống phần
"MongoDB Compass Download" + Click "Download" + chờ tải + chạy File vừa tải để cài
đặt và mở luôn phần mềm Mongo DB Compass
 Khi này, trong thư mục "C:\Users\<Tên Người Dùng>\AppData\Local" sẽ xuất hiện thư
mục "MongoDBCompass", trong đây có File "MongoDBCompass.exe" là phần mềm
Mongo DB Compass
 Về giao diện, có 2 loại cửa sổ là cửa sổ tổng quan và cửa sổ làm việc, ban đầu ở cửa sổ
tổng quan, cửa sổ làm việc sẽ chỉ làm việc trên 1 Cluster được kết nối
 Về cửa sổ tổng quan
- Thanh trên cùng là thanh tiêu đề
- Thanh dưới là thanh điều hướng
a) Tab "Connect", chọn mục "Exit" = nhấn "Ctrl" + "Q", rồi nhấn "Enter" để đóng cửa sổ,
chọn mục "New Window" = nhấn "Ctrl" + "N" để mở thêm cửa sổ tổng quan mới
b) Tab "Edit", chọn mục "Settings" = nhấn "Ctrl" + "," để mở cửa sổ cài đặt
- Panel bên trái là Panel kết nối
a) Nút bánh răng, Click để mở cửa sổ cài đặt
b) Mục "Saved connections", liệt kê các Connection đã lưu, đã lưu thì khi đóng cửa sổ mở
lại vẫn còn đó, có thể Click vào để chọn Connection, nút 3 chấm bên phải mỗi
Connection, Click để hiện 3 tùy chọn, "Copy connection string" để Copy URI của
Connection này, "Duplicate" để tạo ra bản sao của Connection này và lưu nó, "Remove"
để xóa Connection, nút 3 chấm bên phải dòng "Saved connections", Click để hiện 2 tùy
chọn, "Export saved connections", bạn sẽ chọn các Connection đã lưu để xuất ra File
JSON, nút "Select a file…" để chọn nơi lưu File và tên File, mục "Encryption Password"
điền mật khẩu bất kì để mã hóa File JSON, nếu không muốn mã hóa, Tick "Remove
Secrets", khi này bạn không cần đặt mật khẩu gì hết, sau đó Click "Export" để xuất, tùy
chọn thứ 2, "Import saved connections", mục "Select a file…" bạn sẽ chọn File JSON đã
xuất, mục "Decryption Password" nhập mật khẩu mã hóa File JSON nếu có, sau đó chọn
các Connection đã lưu trong File JSON này để Import vào phần "Saved connections" rồi
Click "Import", có thể sẽ ghi đè, lưu ý nếu bạn đặt mật khẩu mã hóa cho File JSON, thì
khi Import vào các URI của các Connection sẽ được giữ nguyên, nghĩa là bao gồm luôn cả
phần mật khẩu khách hàng, nhưng nếu chọn xuất ra mà không đặt mật khẩu mã hóa, thì
khi Import vào phần mật khẩu khách hàng sẽ biến mất
c) Mục "Recents", liệt kê các Connection được kết nối gần đây
d) Nút "New connection", Click để tạo thêm Connection, các thông tin điền ở phần chỉ định
kết nối
- Panel bên phải là Panel quảng cáo
- Phần ở giữa là phần chỉ định kết nối, sẽ ứng với 1 Connection được chọn
a) Góc trái trên là tên của Connection
b) Mục "URI", điền URI của Connection, chỉ chỉnh sửa được khi gạt "Edit Connection String"
sang phải, bạn có thể điền URI của Cluster trên Mongo DB Atlas để kết nối với nó, hoặc
URI của Mongo DB Server cục bộ, với Mongo DB Atlas thì Scheme là mongodb+srv,
nhưng Scheme của cục bộ sẽ chỉ là mongodb, ví dụ mongodb://localhost:27017/
c) Nút "Save", Click rồi đặt tên cho Collection rồi lưu
d) Nút "Connect" để tiến hành kết nối với Connection này và chuyển sang cửa sổ làm việc
tương ứng
e) Nếu là tạo mới 1 Connection thì còn có thêm nút "Save & Connect" để lưu rồi kết nối
luôn
 Về cửa sổ làm việc
- Thanh trên cùng là thanh tiêu đề, chứa đường dẫn tới cơ sở dữ liệu, Collection,
Document, kể từ tên Connection, ví dụ "tenconnection/coso1/collection1/doc1"
- Thanh dưới là thanh điều hướng giống cửa sổ tổng quan
- Phần dưới cùng là cửa sổ Mongo DB Shell
- Panel bên trái là Panel cơ sở
a) Nút 3 chấm góc phải trên, Click để ra các tùy chọn, "Copy connection string" để Copy URI
của Connection, "Edit favorite" để đổi tên Connection, "Connection info" để hiện cửa sổ
thông tin Cluster, "Compass Settings" để mở cửa sổ cài đặt
b) Ô "Search" và phần bên dưới, phần bên dưới liệt kê tất cả cơ sở dữ liệu của Cluster hiện
tại, chúng giống như cấu trúc thư mục, bên trong lại có các Collection giống như File, mỗi
File này lưu các Document bên trong, gõ vào ô "Search" để lọc các cơ sở dữ liệu và
Collection, cái nào mà tên chứa chuỗi được gõ thì hiển thị, bên phải mỗi cơ sở dữ liệu có
nút thùng rác, Click + nhập tên cơ sở dữ liệu này + Click "Drop Database" để xóa cơ sở
dữ liệu này, ngoài ra còn có nút dấu cộng, Click + nhập tên Collection mới + Click "Create
Collection" để tạo Collection mới, nút 3 chấm bên phải mỗi Collection, Click để hiện 3
tùy chọn, "Open in new tab", để mở Tab liệt kê Document ứng với Collection này ở phần
chỉnh sửa cơ sở, "Rename collection" để đổi tên Collection, "Drop collection", Click rồi
nhập tên Collection + Click "Drop Collection" để xóa nó
c) Mục "Databases", Click vào để mở Tab liệt kê cơ sở dữ liệu trong phần chỉnh sửa cơ sở,
nút 2 mũi tên vòng tròn bên phải để cập nhật lại dữ liệu từ Server và cập nhật lại các
thống kê, nút dấu cộng, Click + điền tên cơ sở dữ liệu mới và Collection đầu tiên trong nó
+ Click "Create Database" để tạo cơ sở dữ liệu mới
- Phần bên phải là phần chỉnh sửa cơ sở, giống VS Code
 Về Tab liệt kê cơ sở dữ liệu
 Tiêu đề Tab là "Databases"
 Thanh trên cùng là thanh công cụ
- Nút "Create database" để tạo cơ sở dữ liệu mới, cơ chế đã biết
- Nút "Refresh" để cập nhật lại các cơ sở dữ liệu từ Server và tính toán lại các thống kê
- Mục "View", chọn biểu tượng 3 sọc để liệt kê từ trên xuống dưới, 4 ô vuông để liệt kê
theo lưới ô
- Mục "Sort by"
a) "Database Name" để sắp xếp theo tên cơ sở dữ liệu
b) "Storage size" để sắp xếp theo lượng dữ liệu mà cơ sở dữ liệu chiếm
c) "Collections" để sắp xếp theo số lượng Collection của cơ sở dữ liệu
d) "Indexes" để sắp xếp theo số lượng Index của 1 cơ sở dữ liệu
- Nút bên phải cùng, Click để thay đổi trạng thái của nó, nếu nó đang là mũi tên chĩa
xuống thì từ trên xuống sắp xếp giảm dần, ngược lại tăng dần
 Phần dưới là phần liệt kê, với mỗi ô cơ sở dữ liệu liệt kê
- Nút thùng rác bên phải cùng để xóa cơ sở dữ liệu, cơ chế đã biết
- Trên cùng là tên cơ sở dữ liệu
- Mục "Storage size" là lượng dữ liệu đã chiếm
- Mục "Collections" là số Collection
- Mục "Indexes" là số Index
- Click vào 1 ô sẽ mở Tab liệt kê Collection của cơ sở dữ liệu tương ứng
 Về Tab liệt kê Collection
 Tiêu đề Tab là tên cơ sở dữ liệu
 Thanh dưới chứa đường dẫn tới cơ sở dữ liệu, cơ chế đường dẫn đã biết
 Thanh dưới là thanh công cụ
- Nút "Create collection" để tạo thêm Collection, cơ chế đã biết
- Nút "Refresh" để cập nhật lại dữ liệu từ Server và tính toán lại các thống kê
- Mục "View", tương tự như của Tab liệt kê cơ sở dữ liệu
- Mục "Sort by"
a) "Collection name", sắp xếp theo tên Collection
b) "Documents", sắp xếp theo số lượng Document của Collection
c) "Avg. document size", sắp xếp theo dung lượng trung bình của 1 Document trong
Collection
d) "Storage size", sắp xếp theo dung lượng của Collection, dung lượng Collection = tổng
dung lượng Document bị nén lại
e) "Indexes", sắp xếp theo số lượng Index của Collection
f) "Total index size", sắp xếp theo tổng dung lượng các Index của Collection
- Nút bên phải như để sắp xếp tăng dần hoặc giảm dần, cơ chế đã biết
 Phần dưới là phần liệt kê, với mỗi ô Collection liệt kê
- Nút thùng rác bên phải cùng để xóa Collection, cơ chế đã biết
- Trên cùng là tên Collection
- Mục "Storage size" là dung lượng Collection
- Mục "Documents" là số Document
- Mục "Avg. document size" là dung lượng trung bình của 1 Document
- Mục "Indexes" là số lượng Index
- Mục "Total index size" là tổng dung lượng các Index của Collection
- Click vào 1 ô sẽ mở Tab liệt kê Document của Collection đó
 Về Tab liệt kê Document
 Tiêu đề Tab là tên Collection
 Thanh dưới chứa đường dẫn tới Collection, cơ chế đường dẫn đã biết
 Thanh dưới là thanh điều hướng
 Phần bên dưới khác nhau với mỗi Tab ở thanh điều hướng
- Về Tab "Documents"
a) Thanh trên cùng là thanh Query, ô Input bạn sẽ nhập chuỗi Query, nút "Option" bên phải
cùng, Click để ẩn hiện Panel Projection, trong đây có mục "Project" bạn điền chuỗi
Projection
b) Thanh dưới là thanh công cụ, chùm 3 nút phải cùng là 3 chế độ hiển thị liệt kê, nút 3 sọc
là liệt kê trên xuống, nút ngoặc nhọn là liệt kê kiểu JSON, nút 4 ô vuông là liệt kê dạng
bảng, bên trái chùm 3 nút, có cú pháp <A> - <B> of <C>, tức là đang liệt kê Document có
số thứ tự là <A> đến Document có số thứ tự là <B>, trong tổng cộng <C> Document
được Query ra của Collection, nút mũi tên để thay đổi <A> và <B>, tức hiển thị liệt kê các
Document tiếp theo hoặc trước đó, nút 2 mũi tên tròn để tính toán lại các thống kê của
Document, nút "DELETE" ở giữa, Click + chọn "Delete <C> documents" 2 lần để xóa toàn
bộ Document được Query ra này
c) Phần bên dưới liệt kê tất cả Document của Collection thỏa mãn Query đã thực hiện gần
nhất, chỉ liệt kê các thuộc tính trong Document dựa vào Projection, và cách hiển thị liệt
kê tùy thuộc vào chế độ được chọn ở thanh công cụ, lưu ý chỉ liệt kê 1 vài Document khi
số lượng Document quá lớn, liệt kê phần nào tùy thuộc vào thanh công cụ
 Về các kiểu dữ liệu của Value trong Document
 Int32, số nguyên từ -2147483648 tới 2147483647
 Int64, số nguyên từ -9223372036854775808 tới 9223372036854775807
 Double, số thực bất kì với độ chính xác nhỏ, vô cực sẽ là Infinity, âm vô cực là -Infinity,
có thêm giá trị đặc biệt là NaN, tức không phải số
 Boolean, true hoặc false
 Null, chỉ có giá trị null
 Undefined, chỉ có giá trị undefined
 Decimal128, số thực bất kì với độ chính cao, vô cực sẽ là Infinity, âm vô cực là -Infinity,
có thêm giá trị đặc biệt là NaN, tức không phải số
 String, chuỗi kí tự với độ dài không giới hạn
 Array, mảng chứa phần tử thuộc kiểu dữ liệu bất kì
 Date, 1 chuỗi chỉ định thời điểm có cú pháp sau
<Năm>-<Tháng>-<Ngày>T<Giờ>:<Phút>:<Giây>.<Mili Giây>+<Lệch Giờ>:<Lệch Phút>
- Nếu <Năm> từ 0 đến 9999, thì sẽ giữ nguyên 4 chữ số, bù 0 vào bên trái để đủ 4 số, ví dụ
1234 vẫn giữ 1234, 123 thì thành 0123, nếu <Năm> nằm ngoài khoảng này, thì nó sẽ
phải có 6 chữ số, bù 0 nếu chưa đủ 6, và thêm dấu đằng trước, + nghĩa là dương, hay sau
công nguyên, - tức là âm, hay trước công nguyên, ví dụ năm 12345 sau công nguyên sẽ
thành +012345, năm 456 trước công nguyên sẽ thành -000456
- <Tháng> phải từ 1 đến 12, nếu có 1 chữ số thì thêm 0 đằng trước
- <Ngày> phải từ 1 đến 28, 29, 30, hoặc 31 tùy vào tháng và năm, nếu có 1 chữ số thì
thêm 0 đằng trước
- <Giờ>:<Phút>:<Giây>.<Mili Giây> phải từ 00:00:00.000 đến 23:59:59.999
- <Lệch Giờ>:<Lệch Phút> tượng trưng cho múi giờ, phải từ 00:00 đến 23:59
 Object, lại là 1 Object viết theo Dictionary
 ObjectID, là 1 số nguyên từ 000000000000000000000000 tới ffffffffffffffffffffffff, nghĩa là
nó sẽ được biểu diễn dưới dạng thập lục phân 24 chữ số
 Về dung lượng của 1 Document, nó sẽ = 5 Byte + tổng dung lượng các cặp Key Value,
dung lượng của 1 cặp Key Value = dung lượng Initial + số kí tự của Key + dung lượng
Value

Kiểu dữ liệu Dung lượng Inital Dung lượng Value


Int32 2 Byte 4 Byte
Int64 2 Byte 8 Byte
Double 2 Byte 8 Byte
Decimal128 2 Byte 16 Byte
Boolean 2 Byte 1 Byte
Null 2 Byte 1 Byte
Undefined 2 Byte 0 Byte
String 7 Byte Bằng số kí tự của Value
ObjectID 2 Byte 12 Byte
Tổng dung lượng các cặp Key Value trong
Object 7 Byte

Array 7 Byte Tổng dung lượng các cặp Key Value trong
nó, lưu ý các phần tử trong nó thì Index
coi là Key luôn, ví dụ Index 12 thì coi Key là
"12"
Date 2 Byte 8 Byte
 Về cửa sổ cài đặt, chỉnh sửa gì thì Click "Save" để có hiệu lực, "Cancel" để bỏ qua
 Tab "Theme", chọn màu chủ đạo cho các cửa sổ
5. Cách Viết Query Trong Mongo DB Compass?
 Viết dưới dạng JSON
{
<Điều Kiện 1>,
<Điều Kiện 2>,

}
 Query trên nghĩa là Document nào mà tất cả điều kiện trên thỏa mãn thì mới chọn
 Quy tắc viết 1 điều kiện như sau
 Điều kiện Value của Key nào đó phải = 1 giá trị nào đó
<Key>: <Giá Trị>
- Lưu ý ở đây là phải = kiểu dữ liệu và cũng phải = giá trị thì mới tính
a) Nếu muốn nói <Giá Trị> thuộc kiểu ObjectID, thì phải được bọc trong hàm ObjectId, ví dụ
foo: ObjectId("6680966c1b5ee92bad51bc10")
b) Nếu muốn nói <Giá Trị> thuộc kiểu Date, thì phải được bọc trong hàm ISODate, ví dụ
foo: ISODate("2000-03-04T00:00:00.000+00:00")
c) Nếu muốn nói <Giá Trị> thuộc kiểu Decimal128, thì phải được bọc trong hàm
NumberDecimal, ví dụ
foo: NumberDecimal("123.456")
d) Nếu muốn nói <Giá Trị> là null hoặc undefine hoặc Key không tồn tại, thì dùng null hoặc
undefined đều được, chúng là như nhau, ví dụ
foo: undefined
e) Với các kiểu Int32, Int64, Double, thì bạn chỉ cần ghi số thôi, ví dụ foo: 123 thì trích luôn
cả các Document có thuộc tính foo kiểu Int32, hoặc Int64, hoặc Double, miễn là có giá trị
= 123
f) Với kiểu String hoặc Boolean, thì ghi như bình thường, ví dụ
foo: true,
bar: "ggnore"
g) Với Object, thì ghi kiểu Object viết theo Dictionary, lưu ý phải đúng y chang, tính cả thứ
tự thuộc tính, chỉ có điều trong tình huống này null = undefined ví dụ
foo: {
bar: 12.45,
alice: true,
john: undefined
}
h) Nghĩa là sẽ chỉ lấy ra các Document mà thuộc tính foo được ghi như trên, thuộc tính john
có thể là null, nếu foo như sau thì cũng không được tính
{
alice: true,
bar: 12.45,
john: undefined
}
i) Với Array thì bọc dấu ngoặc vuông, thứ tự và giá trị phải chính xác, ví dụ
foo: [1, 2.5, "ggnore"]
 Điều kiện Value của Key nào đó phải = 1 trong các giá trị được liệt kê trong ngoặc vuông,
cơ chế so sánh đã biết, null, undefined và không tồn tại Key là như nhau
<Key>: {$in: <Các Giá Trị>}
- Ví dụ
foo: {$in: [1, 2.5, "gg"]}
 Điều kiện chỉ cần phải thỏa mãn 1 trong các điều kiện được liệt kê
$or: [{<Điều Kiện 1>}, {<Điều Kiện 2>}, …]
- Ví dụ
$or: [{foo: 123}, {bob: {$in: [1, 2, 3]}}]
 Điều kiện Value của Key nào đó phải nhỏ hơn 1 giá trị nào đó, tiêu chí so sánh tùy thuộc
vào kiểu dữ liệu
<Key>: {$lt: <Giá Trị>}
- Ví dụ
foo: {$lt: 30}
 Tương tự điều kiện lớn hơn, thay $lt thành $gt
 Nếu điều kiện bé hơn hoặc bằng, hay lớn hơn hoặc bằng, thì thêm e vào sau, ví dụ $lte,
$gte, nó tương đương kiểm tra 2 lần, 1 lần = $lt hoặc $gt, lần 2 là so sánh bằng, cơ chế
đã biết
 Nếu điều kiện liên quan đến Key được lồng trong Key, thì dùng dấu chấm để truy xuất,
và bọc Key vào cặp dấu nháy, lưu ý Array cũng như Object, chỉ khác là Key là số tăng dần
từ 0, ví dụ
"foo.bar.0.bob": 123
- Nghĩa là tìm Document có thuộc tính foo, sao cho foo là 1 Object có thuộc tính bar, và
bar này là 1 Array, sao cho phần tử Index 0 của nó là 1 Object, Object này có thuộc tính
bob = 123
- Cho dù trong foo không có bar, hoặc bar không phải Array, … thì lỗi không xảy ra, và vẫn
có thể dùng null, undefined để chỉ rằng Key không tồn tại
 Có thể gộp các điều kiện cùng Key với nhau, dùng dấu phẩy ngăn cách, ví dụ
foo: {$lt: 100, $gt: 50}
- Tương đương
foo: {$lt: 100},
foo: {$gt: 50}
 Điều kiện 1 Key nào đó mà Value của nó phải là Array, và Array này chứa tất cả phần tử
được liệt kê trong dấu ngoặc vuông
<Key>: {$all: <Các Giá Trị>}
- Ví dụ
foo: {$all: [1, 2, "gg", 1]}
a) Nghĩa là sẽ chọn Document có thuộc tính foo là 1 Array, và Array này phải chứa ít nhất 1
phần tử có giá trị 1, 1 phần tử có giá trị 2 và 1 phần tử có giá trị "gg"
- Nếu chỉ có 1 giá trị được liệt kê, thì Value không phải Array cũng có thể dính, ví dụ
foo: {$all: [1]}
a) Thì kể cả foo không phải Array nhưng có giá trị = 1 thì cũng dính
b) Điều kiện trên tương đương
foo: 1
c) Nghĩa là foo: 1 ngoài lấy các Document có thuộc tính foo = 1, sẽ lấy cả Document có
thuộc tính foo là Array chứa ít nhất 1 phần tử có giá trị = 1
d) Quy luật trên áp dụng cho cả các điều kiện khác như lớn hơn, bé hơn, …, chỉ cần 1 phần
tử trong Array thỏa mãn là dính, ví dụ
foo: {$gt: 100}
e) Nghĩa là lấy cả foo là Array với ít nhất 1 phần tử có giá trị > 100
f) Tuy nhiên, với Key là chuỗi lồng nhau như foo.bar, thì quy tắc trên không áp dụng
 Điều kiện 1 Key nào đó mà Value của nó phải là Array, và Array này phải chứa ít nhất 1
phần tử thỏa mãn cùng lúc tất cả điều kiện được chỉ định
<Key>: {$elemMatch: <Các Điều Kiện>}
- Ví dụ
foo: {$elemMatch: {$lt: 100, $gt: 50}}
 Điều kiện 1 Key nào đó, mà Value của nó phải là Array, và Array này phải có số phần tử =
giá trị chỉ định
<Key>: {$size: <Số Phần Tử>}
- Ví dụ
foo: {$size: 3}
 Tiêu chí so sánh lớn, bé

Kiểu dữ liệu
Cả 2 toán hạng thuộc 1 trong 4 kiểu Int32,
So sánh số học bình thường
Int64, Double, Decimal
Cả 2 đều là String So sánh bình thường theo từ điển
1 thằng là null hoặc undefined Luôn False
6. Cách Viết Projection?
 Viết như Object theo Dictionary, tất cả Value phải cùng có giá trị = 1 hoặc cùng có giá trị
=0
 Nếu chuỗi Projection rỗng, tức là {}, thì hiển thị tất cả
 Nếu Value Full 1, thì chỉ hiển thị các Key có trong chuỗi Projection, ví dụ
{foo: 1, bar: 1}
- Thì các Document được Query ra, chỉ hiển thị thuộc tính foo và bar của chúng, còn lại ẩn
hết
 Nếu Value Full 0, thì ẩn các Key có trong chuỗi Projection, các Key còn lại hiện hết
 Trường hợp 1 Value nào đó là Array, chịu ảnh hưởng của 1 phép Query trên từng phần
tử, ví dụ phép Query "trong Array này phải có ít nhất 1 phần tử < 10", thì nếu muốn, bạn
có thể chỉ hiển thị phần tử đầu tiên thỏa mãn Query, bằng cách thêm .$ vào Key, bọc
dấu nháy, Value vẫn = 1, ví dụ
{a: 1, "foo.$": 1}
 Nghĩa là, chỉ hiện thị thuộc tính a và foo, trong đó foo là Array và chỉ hiện thỉ phần tử
đầu tiên thỏa mãn Query, ví dụ kết quả hiển thị có thể là
{
a: 123,
foo: [80]
}
7. Khởi Chạy Mongo DB Server Cục Bộ?
 Để chỉ định đường dẫn đến thư mục Cluster, nghĩa là bây giờ ta sẽ coi 1 thư mục là 1
Cluster, gọi thư mục này là A, đồng thời khởi chạy Server luôn và kết nối với Cluster này,
mở Task Manager ra, bạn sẽ thấy có Process "mongod.exe" chính là Server
mongod --dbpath <Đường Dẫn Đến A>
 <Đường Dẫn Đến A> phải đã tồn tại
 Địa chỉ mặc định của Server là localhost:27017
 Ví dụ
mongod --dbpath C:\data\db

SQL - Structured Query Language:

1. MySQL?
 Giống Mongo DB, là hệ quản trị cơ sở dữ liệu, dùng ngôn ngữ SQL, để cài đặt
 Vào Link https://dev.mysql.com/downloads/mysql/, Click "Download" ứng với cái MSI
Installer + Click "No thanks, just start my download." + chờ tải + chạy File vừa tải + Click
"Next" + đồng ý điều khoản + Click "Next" + Click "Typical" + Click "Install" + chờ cài đặt +
Click "Finish" + Click "Next" 3 lần + tại mục "MySQL Root Password" điền mật khẩu đăng
nhập, gọi là Root Password, khi này tên người dùng là root + tại mục "Repeat Password"
điền lại mật khẩu + Click "Next" + Untick "Start the MySQL Server at System Startup" +
Click "Next" 3 lần + Click "Execute" + Click "Next" + Click "Finish"
 Khi này trong thư mục "C:\Program Files" sẽ xuất hiện thư mục "MySQL", trong đây chứa
1 thư mục có tên là phiên bản MySQL bạn đã cài đặt, và có thể chứa nhiều thư mục ứng
với nhiều phiên bản khác nhau
 Đồng thời trong thư mục "C:\ProgramData" cũng sẽ xuất hiện thư mục "MySQL", trong
đây có chứa các thư mục với tên là các phiên bản MySQL, bên trong mỗi thư mục sẽ
chứa các File và thư mục liên quan đến Database
 Trong thư mục "C:\ProgramData\Microsoft\Windows\Start Menu\Programs" cũng xuất
hiện thư mục "MySQL", bên trong là 1 hoặc nhiều thư mục có tên là các phiên bản bạn
đã tải + bên trong mỗi thư mục này sẽ chứa File EXE "Command Line Client", giúp bạn
giao tiếp với MySQL
 Bạn cần thêm đường dẫn "C:\Program Files\MySQL\MySQL Server 8.3\bin" vào biến môi
trường Path để có thể dùng lệnh thông qua CMD
2. Command Line Client (CLC)?
 Ban đầu, nó sẽ bắt bạn nhập mật khẩu, khi này bạn sẽ nhập Root Password, sau đó nó sẽ
kết nối với Server MySQL đang chạy trên máy, nếu Server chưa chạy thì không có gì xảy
ra
 Để bắt đầu chạy Server MySQL, vào ứng dụng Services (giống như khi vào Settings) +
cuộn xuống cho đến khi thấy tên MySQL + chọn nó + Click "Start the service" để chạy
hoặc "Stop the service" để đóng Server, Server sẽ được chạy ở Port 3306
 Sau khi CLC đã kết nối với Server MySQL, bạn có thể bắt đầu sử dụng lệnh của ngôn ngữ
SQL
3. PopSQL?
 Là giao diện thân thiện với người dùng, dùng để giao tiếp với Server MySQL chạy trên
máy bạn, ngon hơn CLC, để cài đặt
 Vào Link https://popsql.com/download, Click "Download for Windows" + chờ tải + chạy
File vừa tải + thoát
 Khi này, trong thư mục
"C:\Users\<Tên Người Dùng Hiện Tại>\AppData\Local\Programs" sẽ xuất hiện thư mục
"@popsqldesktop", trong đây lại chứa File EXE "PopSQL" là phần mềm bạn muốn chạy
 Sau đó, chạy phần mềm PopSQL lên, đăng nhập bằng tài khoản Google + nó chuyển
hướng đến trang đăng ký + điền thông tin + xác nhận Email + mở lại phần mềm PopSQL
rồi đăng nhập bằng tài khoản Google hồi nãy + điền tên công ty + điền số người trong
công ty + Click "Create organization" + Click "Skip this" + chọn 1 vài thông tin cá nhấn +
Click "Next" + chọn mục tiêu làm việc hôm nay + Click "Next" + Click "Start querying" +
đóng phần mềm
 Như vậy là xong bước cài đặt, từ giờ chỉ cần mở phần mềm và làm việc
4. Cấu Trúc Database Trong MySQL?
 1 Port sẽ chứa nhiều Database, mỗi Database là 1 thư mục, và mỗi cái lại chứa nhiều
bảng, mỗi bảng là 1 File có phần mở rộng là ".ibd"
 Nếu bạn lưu Database trong máy, ứng với localhost và Port 3306, thì các Database ứng
với Port này được lưu trong thư mục "C:\ProgramData\MySQL\<Phiên Bản MySQL>\
Data"
5. Cách Dùng PopSQL?
 Cửa sổ PopSQL bao gồm thanh tác vụ trên cùng và thanh công cụ bên trái, khi Click vào 1
biểu tượng ở thanh công cụ thì cửa sổ tương ứng với công cụ đó sẽ hiện trồi ra hoặc rút
vào
 Quá tình làm việc với PopSQL sẽ giống như chỉ làm trên 1 dự án duy nhất, bạn không cần
nhấn lưu File hay gì hết, tất cả tự động lưu và mỗi khi bạn mở PopSQL lên thì sẽ tiếp tục
với phần việc dở dang trước đó
 Phần 1, cài đặt
 Để vào cài đặt
 Vào Tab "File" + chọn "Preferences…" = nhấn "Ctrl" + ","
 Để thoát cài đặt, Click "Preferences" to đùng
 Phần 2, danh sách có thể kết nối, nằm trong phần cài đặt
 Để vào danh sách có thể kết nối, vào thẻ "Connections"
 Để thêm 1 Port vào danh sách có thể kết nối, lưu ý bản PopSQL Free chỉ được phép có
tối đa 2 Port trong danh sách
 Click "New connection" + chọn "MySQL" + tại mục "Connection name" điền tên sẽ hiển
thị ở danh sách có thể kết nối, tạm gọi là tên kết nối + tại mục "Hostname/Port" lần lượt
điền tên miền và Port lưu trữ các Database, nếu cục bộ thì điền localhost và Port 3306 +
tại mục "Database" điền tên Database muốn kết nối + tại mục "Username/Password"
điền tên người dùng và mật khẩu, tên người dùng và mật khẩu này phải có quyền truy
cập vào các Database tại Port, ví dụ root và matkhau123 + tại mục "Connection Type"
gạt sang phải để chỉ định Port nằm trên máy mình + Click "Save"
 Phần 3, bố cục, vào Tab "Schemas" ở thanh công cụ
 Ở đây sẽ hiển thị bố cục tổng thể của 1 Database nào đó
 Bước 1, chọn tên kết nối ứng với Port chứa Database muốn hiện bố cục
 Bước 2, chọn Database muốn hiện bố cục
 Bước 3, xem bố cục ở bên dưới
 Bạn có thể đồng bộ lại cấu trúc Database bằng cách Click biểu tượng 2 mũi tên tròn bên
phải tên kết nối, khi này PopSQL sẽ cập nhật các File và thư mục trong Port tương ứng
vào trong PopSQL
 Phần 4, mẫu hỏi, nằm ở Tab "Queries" ở thanh công cụ
 Mẫu hỏi tương đương 1 File, chạy File này sẽ trích xuất dữ liệu trong Database nào đó và
hiển thị lên màn hình PopSQL, phần bên trái là Code, bên phải là màn hình thông báo kết
quả chạy lệnh
 Dự án bao gồm 3 thư mục to nhất là "Team queries", các File nằm ở đây sẽ được dùng
chung bởi tất cả thành viên trong công ty, "My queries", chỉ có người dùng hiện tại mới
truy cập được, "Drafts", các bản nháp
 Để tạo 1 File mẫu hỏi trong 1 thư mục, Click dấu cộng bên phải thư mục đó + chọn "New
query" để tạo 1 File mẫu hỏi, hoặc chọn "New folder" để tạo 1 thư mục con + đặt tên
File hoặc thư mục
 Để chỉnh sửa 1 File mẫu hỏi, Click vào File đó, khi này Tab ứng với nó sẽ được chèn vào
thanh trên cùng, Click dấu x trên Tab để đóng File tương ứng
 Để chạy 1 File mẫu hỏi trên 1 Database nào đó
 Bước 1, vào Tab của nó
 Bước 2, chọn tên kết nối ứng với Port chứa Database đích, nằm ở góc phải trên
 Bước 3, chọn Database đích trong Port này, nằm ở góc phải trên
 Bước 4, Click mũi tên chỉ xuống bên phải nút "Run" + Tick "Run all statements" nếu
muốn chạy nguyên File mẫu hỏi, Untick nó để chỉ chạy câu lệnh ở vị trí con trỏ văn bản
hoặc nguyên đoạn Code đang được bôi đen
 Bước 5, Click nút "Run", Database sẽ bị thay đổi trực tiếp
 Phần 5, tạo File Database thủ công
 Không được tạo hay thay đổi File Database thủ công, khi này bạn sẽ không được phép
chạy Server MySQL, tất cả phải thông qua lệnh
6. Cú Pháp SQL?
 Không phân biệt hoa thường
 Kết thúc lệnh bằng chấm phẩy
 String được đặt trong cặp dấu nháy đơn hoặc kép
7. Tạo 1 Database Mới?
create database <Tên Database>;
 Khi này trong Port sẽ xuất hiện thư mục rỗng có tên là <Tên Database> nếu chưa tồn tại,
và báo lỗi nếu đã tồn tại
 Ví dụ
create database foo;
8. Các Kiểu Dữ Liệu?
varchar(<Số Kí Tự Tối Đa>)
 <Số Kí Tự Tối Đa> phải là số nguyên trong đoạn từ 0 đến 16383
 Giá trị hợp lệ là String với số kí tự không vượt quá <Số Kí Tự Tối Đa>
int
 Giá trị hợp lệ là số nguyên có dấu 32 Bit, nằm trong đoạn từ -2147483648 tới
2147483647
 Giá trị mặc định cho 1 ô trong bảng là null
9. Tạo 1 Bảng Rỗng?
create table <Tên Bảng>(<Các Cột>);
 <Các Cột> ngăn cách nhau bởi dấu phẩy, mỗi cột sẽ có cú pháp
<Tên Cột> <Kiểu Dữ Liệu> <Hiệu Ứng>
 <Hiệu Ứng> có thể có hoặc không
 Đồng thời ta có thể chỉnh định các cột nào sẽ làm khóa chính bằng cách đặt lệnh sau vào
bất kì chỗ nào trong <Các Cột>
primary key(<Tên Các Cột Làm Khóa Chính>)
 Các cột làm khóa chính không được phép chứa dù chỉ 2 tổ hợp giá trị giống nhau, ví dụ
cột A và B làm khóa chính, thì không được phép có 2 bản ghi mà thuộc tính A của chúng
đều = 2 và B của chúng đều = 5, nhưng sẽ hợp lệ khi 1 thằng có A = 2, B = 5, 1 thằng có A
= 3, B = 5
 Các cột làm khóa chính sẽ phân ra khóa cấp 1, cấp 2, … dựa theo thứ tự ghi trong <Tên
Các Cột Làm Khóa Chính>
 Mỗi khi chèn 1 bản ghi vào bảng, thì nó sẽ được đặt ở vị trí sao cho khóa cấp 1 tăng dần
từ trên xuống, nếu 2 giá trị bằng nhau, thì sắp xếp tăng dần theo khóa cấp 2, nếu 2 giá trị
trong khóa cấp 2 bằng nhau, thì tiếp tục xét đến khóa cấp 3, …
 Ví dụ
primary key(bar, alice, john)
 Thì bar là khóa cấp 1, alice cấp 2, john cấp 3
 Bạn cũng có thể đặt cụm từ primary key ở cột làm khóa chính, khi này chỉ được phép đặt
ở 1 cột, nghĩa là khóa chính chỉ gồm 1 cột
 Danh sách <Hiệu Ứng>

Báo lỗi khi chèn thêm 1 bản ghi mà thiếu giá trị của cột này
Nếu bạn đã tạo bảng rồi, và nó có vài bản ghi rồi, mà bạn lại tạo
not null
cột mới có hiệu ứng này, thì giá trị cột này thay vì là null sẽ = 0
nếu kiểu số nguyên và = "" nếu là String
Báo lỗi khi chèn thêm 1 bản ghi mà giá trị của cột này bị lặp
unique
Cho phép giá trị null có thể bị lặp
Khi chèn thêm 1 bản ghi mà không chỉ định giá trị của cột này thì
default <Giá Trị>
mặc định nó có giá trị là <Giá Trị>
auto_increment Cột có hiệu ứng này phải thuộc khóa chính, và là khóa cấp 1, có
kiểu dữ liệu số nguyên
Khi chèn thêm 1 bản ghi mới mà không có chỉ định giá trị cho cột
này, thì giá trị của nó tự động = giá trị lớn nhất hiện tại của cột
này + 1, nếu đang là giá trị tối đa của kiểu dữ liệu tương ứng thì
không tăng
Cho 1 bảng đã có vài bản ghi, nếu bạn chèn thêm cột có hiệu ứng
này vào thì cột đó sẽ tự động đánh số tăng dần từ 1
 Khi này trong thư mục Database hiện tại sẽ xuất hiện File có tên là
"<Tên Bảng>.ibd" nếu chưa tồn tại, và báo lỗi nếu đã tồn tại
 Ví dụ tạo bảng foo, có 3 cột là bar, alice và john, trong đó bar và alice làm khóa chính,
bar là cột số thứ tự, john là cột có giá trị mặc định 4
create table foo(
bar int auto_increment,
primary key(bar, alice),
alice varchar(100),
john int default 4
);
 Ví dụ khóa chính chỉ gồm 1 cột là bar
create table foo(
bar int auto_increment primary key,
alice varchar(100),
john int default 4
);
 Để hiện thị thông tin về toàn bộ cột của bảng, như tên cột, kiểu dữ liệu, giá trị mặc định,

describe <Tên Bảng>;
 Để xóa 1 bảng ra khỏi thư mục Database
drop table <Tên Bảng>;
 Nếu không tồn tại bảng để xóa thì báo lỗi
10. Thêm 1 Cột Mới Vào Bảng?
alter table <Tên Bảng> add <Thông Tin Cột Mới>;
 Bản chất là đặt nguyên cái <Thông Tin Cột Mới> vào cuối phần cấu hình khi bạn create
table
 Ví dụ
create table foo(
alice int,
john varchar(10),
primary key(alice)
);
alter table foo add bar int not null;
 Tương đương
create table foo(
alice int,
john varchar(10),
primary key(alice),
bar int not null
);
11. Xóa 1 Cột Trong Bảng?
alter table <Tên Bảng> drop column <Tên Cột Muốn Xóa>;
 Ví dụ
alter table foo drop column bar;
12. Thêm 1 Bản Ghi Vào Bảng?
insert into <Tên Bảng> values(<Tất Cả Các Giá Trị Của Các Cột>);
 Ví dụ
insert into foo values(20, "daubuoi", 4);
 Để thêm 1 bản ghi mới nhưng chỉ xác định giá trị cho 1 số cột thay vì toàn bộ
insert into <Tên Bảng>(<Tên Các Cột>) values(<Giá Trị Các Cột Tương Ứng>);
 Ví dụ
insert into foo(bar, alice) values(4, "daubuoi");
13. Trích Xuất Các Cột Và Bản Ghi Trong Bảng Thỏa Mãn Điều Kiện Gì Đó Rồi In Ra Màn
Hình?
 Để trích xuất 1 số cột
select <Tên Các Cột> from <Tên Bảng>;
 Các cột sẽ sắp đúng thứ tự trong <Tên Các Cột>
 Ví dụ
select alice, bar from foo;
 Nếu <Tên Các Cột> là *, thì tương đương trích xuất tất cả cột, hay toàn bộ bảng
 Ví dụ
select * from foo;
 Bạn cũng có thể đổi tên cột khi trích xuất ra bằng cú pháp
<Tên Cột Cũ> as <Tên Cột Mới>
 Ví dụ
select alice as kenny, bar as bob from foo;
 Để trích xuất 1 số bản ghi từ trích xuất cột
select <Tên Các Cột> from <Tên Bảng> where <Điều Kiện>;
 Ví dụ
select bar, alice from foo where john = 5 and bob <> 9;
 Nghia là trích xuất cột bar và alice trong bảng foo, từ 2 cột này, trích những hàng mà có
ô john = 5 và ô bob khác 9
 Để trích xuất sau đó sắp xếp các cột theo thứ tự nào đó
select <Tên Các Cột> from <Tên Bảng> where <Điều Kiện>
order by <Chiều Sắp Xếp Các Cột>;
 <Chiều Sắp Xếp Các Cột> là 1 dãy các phần tử có cú pháp sau
<Tên Cột> <Tăng Hay Giảm Dần>
 <Tăng Hay Giảm Dần> chỉ có thể là asc hoặc desc, asc là tăng dần, desc là giảm dần
 Nếu không chỉ định <Tăng Hay Giảm Dần> thì nó mặc định là asc
 Thứ tự ưu tiên sắp xếp theo đúng thứ tự cột ghi trong <Chiều Sắp Xếp Các Cột>
 Ví dụ
select bar, alice from foo order by john desc, alice;
 Nghĩa là sắp xếp lại bảng foo thành 1 bảng sao cho cột john của nó giảm dần, nếu 2 giá
trị bằng nhau thì xét đến cột alice tăng dần, sau đó trích xuất cột bar và alice từ bảng đã
sắp xếp này
 Để chỉ lấy N cột trích xuất đầu tiên
select <Tên Các Cột> from <Tên Bảng> where <Điều Kiện>
order by <Chiều Sắp Xếp Các Cột> limit <N>;
 Ví dụ
select bar, alice from foo order by alice limit 10;
 Tức là trích xuất cột bar và alice từ bảng foo, sau đó sắp xếp tăng dần theo alice rồi cắt
lấy 10 bản ghi đầu tiên
 Để kết quả trích xuất không có 2 bản ghi nào có tổ hợp giá trị hoàn toàn giống nhau thì
thêm distinct vào trước <Tên Các Cột>
 Ví dụ
select distinct bar, alice, john from foo;
 Nghĩa là giả sử trích xuất được các tổ hợp giá trị là (4, 5, 6), (4, 5, 6), (4, 5, 7) thì sẽ chỉ
còn (4, 5, 6), (4, 5, 7)
14. Cập Nhật Lại Giá Trị Cho 1 Số Ô Thỏa Mãn Điều Kiện Nào Đó Trong Bảng?
update <Tên Bảng> set <Các Lệnh Gán Lại Giá Trị> where <Điều Kiện>;
 ví dụ
update foo set bar = 4, alice = "haha" where john = 6 or bob > 8;
 Lệnh trên nghĩa là xét trong bảng foo, hàng nào có ô ứng với cột john có giá trị = 6 hoặc
ô ứng với cột bob có giá trị > 8 thì ô ứng với cột bar của hàng đó sẽ bị chuyển thành 4 và
ô ứng với cột alice sẽ bị chuyển thành "haha"
 Nếu không có vế where, thì tương đương tất cả các ô trong cột sẽ bị thay đổi giá trị
 Ví dụ
update foo set bar = 4, alice = "haha";
 Tất cả các ô thuộc cột bar sẽ có giá trị = 4 và các ô thuộc cột alice sẽ có giá trị là "haha"
15. Xóa 1 Số Bản Ghi Thỏa Mãn Điều Kiện Nào Đó Trong Bảng?
delete from <Tên Bảng> where <Điều Kiện>;
 Ví dụ
delete from foo where bar = 6 and alice >= 8;
 Nghĩa là xóa tất cả bản ghi trong bảng foo nếu bản ghi đó có ô ứng với cột bar mang giá
trị 6 và ô ứng với cột alice mang giá trị >= 8
 Nếu không có vế where thì xóa hết mẹ bản ghi trong bảng
 Ví dụ
delete from foo;
16. Toán Tử?

= Bằng
<> Khác
>= Lớn hơn hoặc bằng
Tương đương biểu thức
A in (B, C, D, …)
A = B or A = C or A = D or …
Tương đương biểu thức
A=B
A like B
Trong đó B phải là 1 String Regex, A tự
động được ép kiểu sang String
B là trích xuất gồm duy nhất 1 cột
Trả về True nếu chỉ cần A có giá trị = 1 ô
A in (B) trong B, nếu không thì False
Ví dụ
foo in (select bar from bob)
B là trích xuất gồm duy nhất 1 ô
Trả về True nếu A có giá trị = ô này, nếu
A = (B) không thì False
Ví dụ
foo = (select count(bar) from bob)
 Regex

Đại diện cho chuỗi kí tự hoặc số bất kì với


%
độ dài bất kì
_ Đại diện cho 1 kí tự bất kì

17. Thống Kê?


 Để trích xuất ra vài cột rồi áp dụng từng hàm lên cột
select <Các Hàm Cột> from <Tên Bảng>;
 <Các Hàm Cột> là 1 dãy các cú pháp sau, ngăn cách bởi dấu phẩy
<Hàm>(<Cột>)
 Các hàm

count Đếm số phần tử khác null trong cột


Tính giá trị trung bình của các phần tử khác
avg
null trong cột
sum Tính tổng các phần tử khác null trong cột
 Kết quả trả về sẽ là 1 bảng gồm duy nhất 1 hàng chứa kết quả tính
 Ví dụ
select avg(bar), sum(alice) from foo;
 Nghĩa là trả về 1 bảng gồm 1 hàng, hàng này gồm 2 ô, ô đầu tiên chứa giá trị trung bình
của cột bar và ô thứ 2 chứa tổng các giá trị trong cột alice
 Để chia nhóm xong mới áp hàm lên từng nhóm
select <Các Hàm Cột Tính> from <Tên Bảng> group by <Tên Các Cột Nhóm>;
 Trước tiên các bản ghi trong bảng sẽ được sắp xếp lại theo tổ hợp cột nhóm, sao cho tổ
hợp giá trị ở các cột nhóm bằng nhau thì xếp sát nhau, bản ghi tạo ra sau thì nằm dưới
 Ví dụ
 Bảng ban đầu

bar alice john


1 2 10
8 4 2
1 2 3
1 2 4
5 2 5
8 4 6
5 2 7
8 9 88
 Bảng sau khi sắp theo tổ hợp cột nhóm là cột bar và cột alice

bar alice john


1 2 10
1 2 3
1 2 4
8 4 2
8 4 6
5 2 5
5 2 7
8 9 88
 Mỗi màu là 1 nhóm, sau đó áp dụng hàm lên từng nhóm và rút gọn, giả sử ta dùng hàm
sum, cột tính là john
 Kết quả

bar alice john


1 2 17
8 4 8
5 2 12
8 9 88
 Ở <Các Hàm Cột Tính>, ta có thể chèn thêm <Tên Các Cột Nhóm> để hiển thị cả các cột
nhóm, như ở ví dụ trên ta hiển thị luôn cả cột bar và cột alice trong phần kết quả
 Ví dụ
select bar, alice, sum(john), avg(bob) from foo group by bar, alice;
18. Hợp Nhiều Trích Xuất?
 Ví dụ ta trích xuất được bảng A, và trích xuất được bảng B, khi này ta muốn hợp A và B
lại theo chiều dọc
<Trích Xuất A> union <Trích Xuất B>;
 <Trích Xuất A> và <Trích Xuất B> phải có cùng số cột và các cột tương ứng phải cùng kiểu
dữ liệu, tên cột sau khi hợp nhất sẽ lấy theo tên cột của <Trích xuất A>
 Cơ chế hợp như sau
 Đầu tiên <Trích xuất A> sẽ tự nhóm các bản ghi của nó lại với nhau, cơ chế nhóm tương
tự group by với các cột nhóm là toàn bộ nhóm của <Trích Xuất A>, được C
 <Trích Xuất B> cũng tự nhóm như <Trích Xuất A>, được D
 Sau đó lặp qua tất cả bản ghi của D, nếu bản ghi đó có tổ hợp giá trị chưa có trong C thì
chèn vào dưới C
 Cuối cùng trả về C
 Ta có thể nhóm nhiều trích xuất cùng lúc
 Ví dụ
select bar, alice from foo where alice = 5
union
select john, bob from fool
union
select john, shit from fool where john > 4;

Sandbox:

1. Sandbox?
 Là nơi thực thi Code mà không sợ ảnh hưởng tới môi trường xung quanh, nghĩa là mã
độc sẽ vô tác dụng
2. WASM (Web Assembly)?
 Giả sử bạn muốn chạy Code C++ trên trình duyệt, thì khi này, đoạn Code bạn nhập vào
sẽ được gửi đến máy chủ, sau đó nó biên dịch thành mã WASM và được lại trình duyệt
của bạn để chạy, nghĩa là nó khá giống JS, nhưng ngôn ngữ bậc thấp hơn

React:

1. Cách Tải?
 Đặt Tag Script vào File HTML, đây là React dành cho phát triển, có tích hợp thêm vài hàm
phục vụ cho Debug
<script src = "https://unpkg.com/react@<Phiên
Bản>/umd/react.development.js"></script>
 Tương tự như trên, nhưng dùng khi triển khai dự án, đã được tối giản
<script src = "https://unpkg.com/react@<Phiên
Bản>/umd/react.production.min.js"></script>
 Khi này bạn có thể dùng được biến toàn cục React, để trả về String phiên bản React
React.version
 Đặt Tag Script vào File HTML, đây là React DOM dành cho phát triển, lưu ý phiên bản =
phiên bản của React, phải đặt sau Tag Script của React
<script src = "https://unpkg.com/react-dom@<Phiên Bản>/umd/react-
dom.development.js"></script>
 Tương tự như trên, nhưng tối giản
<script src = "https://unpkg.com/react-dom@<Phiên Bản>/umd/react-
dom.production.min.js"></script>
 Khi này bạn có thể dùng được biến toàn cục ReactDOM
2. Tạo React Element?
 Lệnh sau sẽ trả về 1 Object, tạm gọi là <React Element>
React.createElement(<Type>, <Props>, <Các React Element Con>)
 <Type> phải là String hoặc hàm, chính là thuộc tính Type của <React Element>
 <Props> là null hoặc 1 Object viết theo Dictionary, nó chính là thuộc tính Props của
<React Element>, nếu không chỉ định thì = null
 <Các React Element Con> không chỉ định cũng được, các React Element được liệt kê ở
đây sẽ trở thành con của <React Element>, chúng có thể là String
 Ví dụ
const foo = React.createElement(
"ggnore", {concac: 1, daubuoi: 2},
React.createElement("haha"),
React.createElement("haha", null),
"concucac"
)
3. Tạo React DOM Root?
 Lệnh sau sẽ trả về 1 Object, tạm gọi là <React DOM Root>, nó sẽ ứng với 1 Node trong
DOM
ReactDOM.createRoot(<DOM Element>)
 Ví dụ
const root = ReactDOM.createRoot(document.getElementById("ggnore"))
 Để Node tương ứng với <React DOM Root> trong DOM bị mất hết Node con, thay vào
đó là 1 <React Element>, khi này thuộc tính Type của <React Element> sẽ là tên Tag,
thuộc tính Props bao gồm các cặp Key Value chính là thuộc tính của Tag, và các React
Element con cũng được triển khai tương tự
<React DOM Root>.render(<React Element>)
4. JSX?
 Để sử dụng cú pháp JSX, trước tiên cần đặt Tag Script sau vào File HTML để sử dụng thư
viện Babel
<script src="https://unpkg.com/babel-standalone@<Phiên Bản>/babel.min.js"></script>
 Code của thư viện trên sẽ chỉ được chạy sau khi DOM tải xong, nên bạn đặt Tag Script
trên chỗ nào cũng được, khi Code của thư viện này chạy, nó sẽ dò tất cả Tag Script của
DOM, gặp Tag Script A nào có thuộc tính type = "text/babel", nó sẽ ngay lập tức thêm 1
Tag Script B vào cuối Node Head, lưu ý A sẽ không bao giờ được chạy do thuộc tính type
của nó không phải "text/javascript", B có được bằng cách biên dịch A từ JSX sang JS
thông thường và B sẽ có thuộc tính type = "text/javascript", do được thêm bằng
document.createElement, nên thời khắc thêm, B sẽ chạy ngay lập tức, lưu ý cần có thư
viện React và React DOM do Babel biên dịch ra cú pháp JSX sang React Element
 Về cú pháp JSX, bạn có thể viết HTML ngay bên trong Code, và nó tự biên dịch thành
React.createElement, ví dụ
const foo = <ul>
<li>foo</li>
<li>bar</li>
<ul>
 Trong chuỗi HTML trên, bạn có thể lồng vào nó Code JS, giống như nội suy, bằng cách
đặt Code JS vào cặp dấu {}, ví dụ
const foo = <div>ggnore{"haha" + 1}</div>
 Tương đương
const foo = <div>ggnorehaha1</div>
 Nếu giá trị nội suy thuộc kiểu Boolean, Undefined, Null, Symbol, Function thì không hiển
thị, còn là Number hoặc String thì sẽ ép về String để hiển thị, nếu là Object thì lỗi, nếu là
1 React Element thì hiển thị, nếu là Array thì phần tử nào hiển thị được thì hiển thị, tuy
nhiên, mỗi phần tử trong Array, nếu là 1 React Element thì tất cả chúng phải có thuộc
tính Props, và trong Props phải có thuộc tính key, với giá trị độc nhất không giống các
React Element còn lại trong Array
 Khi chỉ định thuộc tính cho Tag bằng JSX, thì giá trị của thuộc tính có thể viết bằng String,
hoặc phải bằng kiểu dữ liệu khác, tùy vào thuộc tính, và tên thuộc tính có thể bị thay đổi
- Với các thuộc tính sự kiện, ví dụ onclick, onmouseup, …, thì phải viết theo Camel Case, ví
dụ onClick, onMouseUp, và giá trị của chúng phải viết = Call Back, ví dụ
const foo = <span onClick = {(e) => console.log(9)}>ggnore</span>
- Với thuộc tính style, phải viết = Object theo Dictionary, và các thuộc tính CSS phải viết
theo Camel Case, ví dụ
const foo = <span style = {{color: "red", fontSize: "16px"}}>ggnore</span>
- Với thuộc tính for của Tag Label, phải đổi nó thành htmlFor
- Với thuộc tính class, phải đổi nó thành className
- Mọi Tag có thể thêm thuộc tính ref, giá trị của nó phải là tham chiếu đến 1 Object có
thuộc tính current, một khi Tag này được Mount vào DOM, thì thuộc tính current của
Object này sẽ được gán giá trị = tham chiếu đến Tag này, tức DOM Element
 Có thể dùng toán tử Spread để ghi nhanh các thuộc tính trong Tag, ví dụ
const foo = {
id: "thanglon",
className: "ggnore"
}
const bar = <span {...foo}>haha</span>
5. Function Component?
 Là 1 hàm trả về 1 React Element, khi này bạn có thể dùng cú pháp JSX với Function
Component như sau
<<Function Component> <Các Đối Số> />
 Lệnh trên sẽ trả về 1 React Element, là thứ được trả về bởi <Function Component> sau
khi xử lí <Các Đối Số>
 <Các Đối Số> viết giống thuộc tính của Tag, kiểu dữ liệu gì cũng được, nếu không phải là
String thì phải bọc trong cặp dấu {}, khi này thứ được truyền vào <Function Component>
sẽ là 1 Object viết theo Dictionary, tuy nhiên, đối số có Key là ref trong <Các Đối Số> sẽ
không được truyền vào, để có thể truyền vào ref, ta phải dùng lệnh sau, lệnh này sẽ trả
về 1 Function Component có khả năng được truyền ref, nhưng ref không truyền vào
trong Object đầu tiên, mà nó sẽ được truyền với tư cách là đối số thứ 2
React.forwardRef(<Function Component>)
 Tên của <Function Component> phải bắt đầu = 1 chữ cái viết hoa
 Ví dụ 1
function Foo(bar){
console.log(bar.ref) // Dòng này in ra undefined, do ref không thể truyền vào
return <div>{bar.alice + bar.john}</div>
}
<Foo alice = "haha" john = {1} ref = {456} />
- Dòng cuối ở ví dụ trên trả về <div>haha1</div>
 Ví dụ 2
function Foo(bar, naruto){
console.log(naruto) // Dòng này in ra 456
return <div>{bar.alice + bar.john}</div>
}
const Boo = React.forwardRef(Foo)
<Boo alice = "haha" john = {1} ref = {456} />
 Ta có thể sử dụng cặp Tag Function Component, phần ở giữa sẽ là thuộc tính children
của Object truyền vào, lưu ý phần ở giữa chỉ là đối số, nên nó không được hiển thị, nếu
phần ở giữa chỉ có 1 thằng, thì children = giá trị thằng đó, nhưng nếu nó là nhiều React
Element, thì children sẽ là Array chứa các React Element đó, ví dụ
function Foo(bar){
console.log(bar.children)
return <span></span>
}
<Foo>ggnore<span>haha</span></Foo>
- Màn hình Console sẽ là 1 Array gồm phần tử thứ nhất là "ggnore", thứ 2 là React
Element <span>haha</span>
 Lệnh sau trả về 1 Function Component, nó vô hình, tức chỉ có tác dụng bọc các React
Element lại với nhau
React.Fragment
 Ví dụ
const foo = <React.Fragment>
<span>foo</span>
<span>bob</span>
</React.Fragment>
 Có thể viết ngắn gọn cặp Tag React.Fragment thành <> và </>, ví dụ
const foo = <>
<span>foo</span>
<span>bob</span>
</>
 Lệnh sau cũng trả về 1 Function Component vô hình, nhưng nó sẽ khiến cho các Function
Component con của nó phải viết với cú pháp như trong Strict Mode, đồng thời nếu trong
chế độ phát triển thì nó sẽ được Render 2 lần mỗi lần Render lại
React.StrictMode
6. Thư Viện React Và React DOM Với Node JS?
 Thư viện React
 Để cài đặt
npm install react
 Để Import
- Common Module
const <React> = require("react")
- ECMA Module
import <React> from "react"
 Thư viện React DOM
 Để cài đặt
npm install react-dom
 Để Import
- Common Module
const <React DOM> = require("react-dom/client")
- ECMA Module
import <React DOM> from "react-dom/client"
7. Thư Viện CRA (Create React App)?
 Để cài đặt
npm install create-react-app
 Khi này, trong thư mục con ".bin" của "node_modules", sẽ có File "create-react-
app.cmd"
 Để tạo 1 dự án React, ta sẽ dùng File "create-react-app.cmd"
node_modules/.bin/create-react-app.cmd <Tên Dự Án>
 Khi này, trong thư mục làm việc hiện tại sẽ xuất hiện thư mục con có tên là <Tên Dự Án>
 Bên trong nó là cấu trúc đầy đủ của 1 dự án React, bao gồm
- File "README.md", là File hướng dẫn
- File "package.json" và "package-lock.json", cơ chế đã biết, ở đây nó cài các thư viện sau
và thêm 1 số thư viện đéo cần quan tâm khác
a) React
b) React DOM
c) React Scripts, trong File "package.json" cũng đã ghi sẵn các lệnh để chạy React Scripts,
bao gồm "npm start" = "react-scripts start", "npm rub build" = "react-scripts build"
- File ".gitignore", nó Ignore thư mục "node_modules", "build" và 1 số thứ khác
- Thư mục "src", chứa File "index.js" là ngõ vào chương trình, kèm theo 1 số File khác có
thể xóa đi nếu muốn
- Thư mục "public" chứa File "index.html" là ngõ vào chương trình, kèm theo 1 số ảnh
khác có thể xóa nếu muốn
- Thư mục "node_modules" chứa các thư viện
 Tóm lại, bây giờ bạn có thể tiến hành phát triển, sử dụng React Scripts để Build
8. Hook?
 Là các hàm như useState, useEffect, …, chỉ được sử dụng trong Function Component, ta
phải tuân theo các quy tắc sau
 Các lệnh Hook phải đặt ở Scope cao nhất trong Function Component, ví dụ sau là đúng
function foo(){
const [state1, setState1] = React.useState(1) // Scope cao nhất
const [state2, setState2] = React.useState(2) // Scope cao nhất
return <span>gg</span>
}
- Ví dụ sau là sai
function foo(){
if (true){
const [state1, setState1] = React.useState(1) // Đặt trong Scope của if
}
const [state2, setState2] = React.useState(2) // Scope cao nhất
return <span>gg</span>
}
 Về Hook useState, lệnh sau sẽ trả về 1 Array có đúng 2 phần tử, phần tử thứ nhất tạm
gọi là <State>, thứ 2 gọi là <Set State>
<React>.useState(<Giá Trị Khởi Đầu>)
 Lần đầu Function Component được Render, lệnh trên sẽ tạo ra 1 State bên trong
Function Component, có giá trị = <Giá Trị Khởi Tạo>, nếu nó là 1 Call Back, thì Call Back
này sẽ được gọi, giá trị trả về cũng sẽ được gán cho State bên trong, <State> cũng sẽ =
giá trị của State bên trong, còn <Set State> là 1 hàm có tác dụng ta sẽ nói sau
 Khi có 1 Call Back A bất kì nào đó được trình duyệt chạy, mà trong đó có sử dụng hàm
<Set State>, thì sẽ có cơ chế như sau, <Set State> là 1 hàm nhận 1 đối số, khi nó được
gọi, thì State bên trong Function Component tương ứng sẽ bị thay đổi = giá trị của đối
số, nếu đối số này là 1 Call Back B, thì B sẽ được gọi, được truyền vào 1 đối số là giá trị
hiện tại của State bên trong Function Component tương ứng, giá trị trả về của B sẽ được
gán lại cho State bên trong, trong suốt quá trình A chạy, thì sẽ có 1 đồ thị biến động
State bên trong vì có thể có nhiều lần <Set State> được gọi, sau khi A chạy xong, nó sẽ
phân tích đồ thị biến động này, nếu có ít nhất 1 biến động hoặc bộ các State bên trong
ngay sau lần Render gần nhất khác với bộ các State bên trong ngay sau lần Render gần
nhì, thì Function Component sẽ Render lại 1 lần, tức bị gọi lại 1 lần, và khi này, lệnh
useState ở trên sẽ bị lơ đi, tuy nhiên phần <Giá Trị Khởi Đầu> vẫn được tính toán 1 cách
vô nghĩa nếu nó là biểu thức, còn nếu nó là Call Back thì Call Back không được gọi, khi
này <State> lệnh trên trả về sẽ = State bên trong hiện tại của Function Component
 Có thể tạo ra nhiều State bên trong cùng lúc, cho dù dùng <Set State> tùm lum, nhưng
chỉ cần đặt chung trong 1 Call Back thì phải đợi Call Back chạy xong mới Render lại 1 lần
 Ví dụ
function App() {
const [a, seta] = React.useState(1)
const [b, setb] = React.useState(2)
const [c, setc] = React.useState(3)

console.log(a)
console.log(b)
console.log(c)

function foo(){
seta(a + 1)
setb(prev => prev + 1)
setc(c + 2)
setc(prev => prev + 3)
}

return <span onClick={foo}>Hello World!</span>


}
- Lần đầu tiên khi App được Render, màn hình Console sẽ in ra 1, 2, 3, khi Click vào dòng
chữ "Hello World!" của App, thì hàm foo được gọi, nó gán State a thành a + 1 = 2, State b
thành giá trị hiện tại + 1 = 3, còn State c sẽ được gán thành c + 2 = 5, rồi gán thành giá trị
trước đó là 5, + thêm 3 = 8, cuối cùng foo chạy xong, nên App được Render lại, và
console.log ra màn hình 2, 3, 8, những lần Click vào "Hello World!" tiếp theo cũng tương
tự
 Về Hook useEffect, có 2 trường hợp
 Lệnh sau sẽ đặt <Call Back> vào hàng đợi, chờ cho đến khi Function Component được
Render ra trình duyệt thì mới gọi
<React>.useEffect(<Call Back>)
- Mỗi lần Function Component được Mount vào DOM, tức từ không xuất hiện trở thành
xuất hiện trong DOM, và mỗi lần nó bị Render lại, <Call Back> đều được gọi
- Nếu <Call Back> trả về 1 hàm, thì hàm này gọi là Cleanup Function, Cleanup Function này
sẽ được đưa vào hàng đợi và chỉ được gọi khi nào Function Component bị Unmount, tức
từ xuất hiện trong DOM trở thành không xuất hiện trong DOM, lưu ý cho dù <Call Back>
có thể bị gọi nhiều lần vì Function Component bị Render lại nhiều lần, thì khi Unmount,
chỉ có Cleanup Function trả về của <Call Back> gần nhất là được gọi
 Lệnh sau cũng tương tự như trên, nhưng khi Function Component bị Render lại, thì <Call
Back> chưa chắc bị gọi lại, nó chỉ bị gọi lại nếu các giá trị trong <Dependencies> của lần
Render lại này khác so với <Dependencies> của lần Render trước đó, <Dependencies>
phải là 1 Array, nếu nó là Array rỗng, thì dễ thấy <Call Back> chỉ được gọi duy nhất 1 lần
lúc Mount, còn các lần Render lại tiếp theo sẽ không gọi, lưu ý việc so sánh dùng toán tử
3 bằng
<React>.useEffect(<Call Back>, <Dependencies>)
 Về Hook useLayoutEffect, nó y chang useEffect, nhưng thay vì Call Back được gọi ngay
sau khi Function Component được Render ở trình duyệt, thì nó sẽ được gọi ngay trước
lúc bị Render, nghĩa là lúc Function Component được chạy từ đầu đến đuôi và trả về
React Element rồi, chỉ chờ Render thôi
 Về Hook useRef
useRef(<Giá Trị Khởi Tạo>)
 Lệnh trên sẽ trả về 1 Object, Object này chỉ bao gồm 1 Key duy nhất là current, có giá trị
= <Giá Trị Khởi Tạo>, có điều là lệnh trên chỉ chạy khi Function Component bị Mount,
còn các lần Render lại tiếp theo, cái Object được trả về, chính là tham chiếu đến Object
được trả về trong lần đầu tiên, chính là lần Function Component bị Mount
 Dễ thấy, bạn có thể thay đổi Value của Key current trong các lần Render lại, khi này các
lần Render lại tiếp theo sẽ không làm mới lại Value của Key current
 Về React Memo, nó có tác dụng trong trường hợp 1 Function Component cha bị Render
lại, thì tất cả các thằng Function Component con cũng bị chạy và Render lại, trong khi
chúng chẳng thay đổi mẹ gì, tức là, nếu các đối số truyền vào Function Component con
từ Function Component cha không thay đổi, cơ chế so sánh = toán tử 3 bằng, thì
Function Component con sẽ không bị Render lại khi thằng cha Render lại, lệnh sau sẽ trả
về Function Component con đã cải tiến thêm chức năng này
<React>.memo(<Function Component Con>)
 Về Hook useCallback
<React>.useCallback(<Call Back>, <Dependencies>)
 Trong lần Mount, thì lệnh trên sẽ chạy và trả về chính <Call Back>, trong các lần Render
lại tiếp theo, nếu các giá trị trong <Dependencies> bị thay đổi thì mới trở về bản Copy
<Call Back> mới, còn không thì vẫn trả về tham chiếu đến <Call Back> ở lần
<Dependencies> bị thay đổi gần nhất, cơ chế <Dependencies> tương tự useEffect
 Về Hook useMemo, khá giống useCallback, chỉ có điều đối số <Call Back> của nó không
được trả về, mà nó trả về thứ <Call Back> trả về
<React>.useMemo(<Call Back>, <Dependencies>)
 Về Hook useReducer, y chang useState về mấy cái cơ chế Render lại, tạo State bên trong,

<React>.useReducer(<Reducer>, <Giá Trị Khởi Tạo>)
 Lệnh trên cũng trả về 1 Array có đúng 2 phần tử, phần tử thứ nhất là <State>, thứ 2 gọi
là <Dispatcher>, <State> ban đầu sẽ = <Giá Trị Khởi Tạo>
 <Reducer> là 1 hàm, nhận vào 2 đối số là State bên trong hiện tại và <Hành Động>, nó sẽ
trả về State bên trong tiếp theo tùy theo <Hành Động> do bạn chỉ định
 <Dispatcher> có vai trò giống như <Set State>, nhưng thay vì nhận đối số là State tiếp
theo, thì nó sẽ nhận đối số là hành động, từ hành động này, <Reducer> sẽ được gọi, Pass
hành động cho <Hành Động> và trả về State tiếp theo, Render lại Function Component
 Về hook useContext, nó dùng để Pass đối số từ Function Component cha xuống Function
Component con cháu mà không cần phải truyền trung gian, trước tiên phải tạo ra 1
Object, gọi là <Context>, tạo đâu cũng được nhưng phải ngoài Function Component,
lệnh sau trả về 1 <Context>
<React>.createContext()
 Lệnh sau sẽ trả về 1 Function Component, gọi là Provider
<Context>.Provider
 Có thể bọc Provider gom chung các Function Component con lại, khi này trong Function
Component con có thể lấy được giá trị của thuộc tính value được truyền vào Provider
bằng lệnh sau, lệnh này phải đặt trong Function Component con, nó sẽ trả về giá trị của
thuộc tính value của Provider
<React>.useContext(<Context>)
 Ví dụ
const context = React.createContext()
function Grandpa(){
return
<context.Provider value = {123}>
<Father />
<Father />
<context.Provider />
}
function Father(){
return
<>
<Kiddo />
<Kiddo />
</>
}
function Kiddo(){
const foo = React.useContext(context)
return <span>{foo}</span>
}
- Khi này, Grandpa sẽ trả về 2 Father, mỗi Father có 2 Kiddo, vậy tổng cộng có 4 Kiddo,
mỗi Kiddo lại lấy được giá trị 123 từ thuộc tính value của Provider, và gán nó vào foo,
như vậy kết quả là 4 Tag <span>123</span>, để ý thấy ta không cần truyền 123 cho
Father rồi từ Father truyền cho Kiddo mà truyền thẳng vào Kiddo
9. Thư Viện React Router DOM?
 Để cài đặt
npm install react-router-dom
 Để Import
 Common Module
const <React Router DOM> = require("react-router-dom")
 ECMA Module
import <React Router DOM> from "react-router-dom"
 Để sử dụng chức năng Routing, và sử dụng các Function Component của thư viện này
trong Function Component của bạn, cần bọc Function Component của bạn trong
Function Component sau
<React Router DOM>.BrowserRouter
 Ví dụ
<BrowserRouter>
<App />
</BrowserRouter>
 Không được phép có nhiều BrowserRouter lồng nhau, nếu không sẽ lỗi
 Lệnh sau sẽ trả về 1 Function Component, nó khá giống Tag liên kết, nhưng thay thuộc
tính href thành to, và khi Click vào thì không tải lại trang, tức không gửi yêu cầu tới
Server, chỉ thay đổi URL thôi
<React Router DOM>.Link
 Ví dụ
<Link to = "/concac">Vao trang concac</Link>
 Lệnh sau sẽ trả về 1 Function Component, gọi là Routes
<React Router DOM>.Routes
 Lệnh sau sẽ trả về 1 Function Component, gọi là Route, nó có thể được truyền các thuộc
tính là path và element, path sẽ ứng với Path trên URL, còn element sẽ là 1 React
Element
<React Router DOM>.Route
 Ta phải kết hợp Routes và Route để hoạt động, Routes bọc các Route, ví dụ
<Routes>
<Route path = "/" element = {<Home />} />
<Route path = "/news" element = {<News />} />
<Route path = "/ggnore" element = {<Foo />} />
</Routes>
 Khi Path trên URL là /, thì <Home /> được chọn để hiển thị, nếu là /news, thì <News />
được chọn để hiển thị, nếu là /ggnore, thì <Foo /> được chọn để hiển thị, tức là thế
nguyên cái Routes trên = 1 trong 3 React Element được liệt kê tùy theo Path trên URL

Webpack:

1. Cách Tải?
npm install webpack webpack-cli
 Khi này, trong thư mục con ".bin" của "node_modules", sẽ có File "webpack.cmd"
2. Gộp Chung Nhiều File JS Liên Quan Thành 1 File JS Duy Nhất?
 Đảm bảo trong thư mục làm việc không có File nào tên "webpack.config.js", rồi chạy
lệnh sau, dùng File "webpack.cmd"
node_modules/.bin/webpack.cmd --entry <File Entry> --output-filename <Tên File
Output> --output-path <Thư Mục Lưu> --mode <Mode>
 <File Entry> là đường dẫn tới File JS không cần phần mở rộng, tương đối hoặc tuyệt đối,
đây sẽ là File đầu vào của chương trình, nó có thể Import nhiều File xung quanh, nếu
không chỉ định thì mặc định = "./src/index"
 <Tên File Output> là tên File JS có phần mở rộng, chính là 1 File duy nhất được gộp bởi
tất cả File JS trong dự án, bắt đầu từ File đầu vào, nếu không chỉ định thì mặc định =
"main.js"
 <Thư Mục Lưu> là đường dẫn tới thư mục để lưu File gộp, tuyệt đối hoặc tương đối, nếu
không chỉ định thì mặc định = "./dist"
 <Mode> nếu là production, thì File JS gộp sẽ được tối giản hóa, nếu là development thì
không, dễ đọc Code hơn, nếu không chỉ định thì = production
 Lưu ý đây chỉ là lệnh biên dịch, tức nó đéo quan tâm Code có chạy hay không, đồng thời
các lệnh import, require, module.exports, export, bạn muốn chạy cái nào cũng được,
nhưng khi Export bằng lệnh gì thì phải Import bằng lệnh tương ứng, không được thằng
import, thằng module.exports, đồng thời lệnh trên còn xem xét cả thư mục
"node_modules" trong trường hợp Import thư viện
 Không thể đóng hộp các File JS nếu có sử dụng thư viện Express
3. File Config?
 Khi chạy lệnh sau
node_modules/.bin/webpack.cmd --mode <Mode>
 Thì nó sẽ dò trong thư mục làm việc hiện tại xem có File "webpack.config.js" hay không,
nếu có thì nó sẽ xét Object được xuất ra từ File này, nếu là Common Module thì không
có gì để nói, nếu là ECMA Module thì xét Object được xuất ra bởi export default
 Object này phải chứa các Key Value sau, các Value như tham số khi dùng CMD
{
entry: <Đường Dẫn Tương Đối Hoặc Tuyệt Đối Tới File Entry>,
output: {
path: <Đường Dẫn Tuyệt Đối Tới Thư Mục Lưu>,
filename: <Tên File Output>
}
}
 Cơ chế <Mode> đã biết
 Để các File JS được hiểu là viết theo JSX, để nó biên dịch ra JS, và đồng thời cũng biên
dịch ra phiên bản JS thấp hơn để tương thích với nhiều trình duyệt, ta cần sử dụng thư
viện Babel kết hợp với Webpack, trước tiên là cài đặt
npm install babel-loader @babel/preset-react @babel/preset-env @babel/core --save-
dev
 Sau đó thêm thuộc tính này vào Object được xuất ra ở File "webpack.config.js", nó nghĩa
là chỉ có các File JS không nằm trong thư mục "node_modules" là được biên dịch, còn
trong "node_modules" giữ nguyên không cần dịch
module: {
rules: [
{
loader: "babel-loader",
test: /\.js$/,
exclude: /node_modules/,
options: {
presets: [
"@babel/preset-env",
"@babel/preset-react"
]
}
}
]
}
 Cách khác, thêm thuộc tính sau thay cho thuộc tính trên
module: {
rules: [
{
use: ["babel-loader"],
test: /\.js$/,
exclude: /node_modules/
}
]
}
- Sau đó, tạo File ".babelrc" trong thư mục làm việc hiện tại, File này viết giống JSON,
thêm thuộc tính sau vào nó
"presets": [
"@babel/preset-env",
"@babel/preset-react"
]
 Thư viện @babel/preset-react có tác dụng chuyển đổi JSX về JS, nếu bỏ đi thì bạn không
thể dùng JSX, còn thư viện @babel/preset-env có tác dụng chuyển JS về phiên bản thấp
hơn để tương thích với nhiều trình duyệt, ví dụ chuyển cú pháp của hàm mũi tên sang cú
pháp thông thường, nếu bỏ đi thì vẫn để hàm mũi tên, và @babel/preset-env cần
@babel/core để hoạt động
 Ngoài ra, khi sử dụng cách Load File ".babelrc", thì ta trong File ".babelrc", ta còn có thể
cấu hình thêm 1 số tiện ích khác, bao gồm
- Thư viện Babel Plugin Module Resolver, để cài đặt
npm install babel-plugin-module-resolver --save-dev
a) Tiếp theo, thêm thuộc tính sau vào File ".babelrc"
"plugins": [
[
"module-resolver",
{
"alias": {
<Alias 1>: <Thế 1>,
<Alias 2>: <Thế 2>,

}
}
]
b) Khi này, mỗi khi bạn dùng lệnh import hay require, thì cái đường dẫn bên trong sẽ được
xử lí như sau, các chuỗi con <Alias 1> trong nó sẽ được thế = <Thế 1>, các chuỗi con
<Alias 2> trong nó sẽ được thế = <Thế 2>, …, và đường dẫn sau khi thế sẽ tính từ File
".babelrc", không phải File JS chứa lệnh import hay require đó, ví dụ
"plugins": [
[
"module-resolver",
{
"alias": {
"~": "./src",
}
}
]
c) Nghĩa là ví dụ bạn truyền đường dẫn "~/foo/bar" cho import hay require thì nó sẽ được
biến thành "./src/foo/bar", và đường dẫn này tính từ File ".babelrc", không phải từ File
JS
 Để khi biên dịch ra File JS gộp, thì tự động Link File này vào File HTML nào đó, trước tiên
cần cài đặt thư viện HTML Webpack Plugin
npm install html-webpack-plugin --save-dev
 Sau đó vào File "webpack.config.js", Import thư viện này
- Common Module
const <HTML Webpack Plugin> = require("html-webpack-plugin")
- ECMA Module
import <HTML Webpack Plugin> from "html-webpack-plugin"
 Cũng trong File "webpack.config.js", thêm thuộc tính sau vào Object nó xuất ra
plugins: [
new <HTML Webpack Plugin>({
template: <File HTML>
})
]
- <File HTML> là đường dẫn tương đối hoặc tuyệt đối tới File HTML bản mẫu, có phần mở
rộng
 Khi này, bất cứ khi nào biên dịch, thì bên cạnh File JS gộp cũng sẽ có 1 File tên
"index.html", nó y chang File HTML bản mẫu, nhưng có Tag Script Link tới File JS gộp bên
trong, Tag Script này nằm cuối Node Head, và có thuộc tính defer
 Để tạo 1 Server giống Live Server tại nơi lưu File JS gộp và File "index.html", nhưng khác
Live Server, mỗi lần mỗi lần ta chỉnh sửa File JS liên quan đến File JS gộp hoặc File HTML
bản mẫu, thì lập tức Webpack sẽ biên dịch lại, tuy nhiên bản chất nó biên dịch rồi chạy
luôn, chứ không lưu File JS gộp và HTML vào thư mục nào hết, và bất cứ thứ gì ở thư
mục "public", đều có thể truy cập được bằng cách thêm Path trên URL, trước tiên cài thư
viện Webpack Dev Server, lưu ý thư viện này cần thư viện Webpack đã cài thì mới sử
dụng được, nó cũng sẽ dựa vào File "webpack.config.js" để biên dịch
npm install webpack-dev-server --save-dev
 Khi này, trong thư mục con ".bin" của "node_modules", sẽ có File "webpack-dev-
server.cmd", ta sẽ dùng File này để khởi tạo Server
node_modules/.bin/webpack-dev-server.cmd --mode <Mode>
- Cơ chế <Mode> đã biết, cái này liên quan đến biên dịch chứ không phải Server
- 1 Server sẽ được khởi tạo ở địa chỉ localhost:8080, vào địa chỉ này sẽ nhận được File
"index.html"
- Để khi chạy lệnh trên thì mở luôn trình duyệt và nhập URL http://localhost:8080, thì
thêm cờ --open
- Để không phải biên dịch lại toàn bộ mà chỉ biên dịch 1 phần khi chỉ có 1 bộ phận nhỏ của
1 File thay đổi, thêm cờ --hot
4. Thư Viện React Scripts?
 Có tác dụng giúp bạn không cần phải tạo File "webpack.config.js", nói rộng ra là đéo cần
Webpack, đéo cần Babel, đéo cần tất cả các thư viện khác liên quan, tất cả chúng nó đều
đã nằm trong thư viện React Scripts và cấu hình đều đã chỉ định trong thư viện này,
trước tiên cài đặt như sau
npm install react-scripts
 Khi này, trong thư mục con ".bin" của "node_modules", sẽ có File "react-scripts.cmd"
 Sau đó vào File "package.json", thêm thuộc tính sau
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
- Cái này là để khi ta chạy React Scripts, nó sẽ biên dịch như thế nào và lựa chọn trình
duyệt nào để mở, mục "production" liên quan đến khi Build ra thành phẩm cuối, mục
"development" là trong quá trình phát triển
 Sau khi xong xuôi, để khởi chạy Server trong chế độ phát triển, dùng lệnh sau
node_modules/.bin/react-scripts.cmd start
 Trình duyệt ngay lập tức mở lên, lưu ý lệnh trên không tạo File JS gộp và HTML, tức là nó
biên dịch rồi chạy luôn, ngõ vào JS sẽ là File "index.js" nằm trong thư mục "src" trong thư
mục làm việc hiện tại, File HTML bản mẫu sẽ là File "index.html" nằm trong thư mục
"public" trong thư mục làm việc hiện tại
 Bạn có thể sử dụng cú pháp JSX tùy ý, khi thay đổi File thì Server cũng sẽ biên dịch và cập
nhật lại
 Bạn có thể Import File CSS vào File JS nếu nó là ECMA Module, khi biên dịch, những dòng
Import này đều được chuyển thành Tag Style với mã CSS bên trong ở cuối Node Head, ví
dụ
import "./App.css"
 Địa chỉ mặc định của Server là localhost:3000, bạn có thể thay đổi Port 3000 thành Port
khác bằng cách thêm File ".env.local" vào thư mục làm việc hiện tại, và thêm dòng PORT
= <Port Mặc Định Mới> vào, ví dụ PORT = 4000
 Có thể truy cập các File trong thư mục "public" bằng cách nhập Path lên URL
 Để Build ra trong chế độ thành phẩm, dùng lệnh sau
node_modules/.bin/react-scripts.cmd build
 Ngõ vào các File thì đã nói, khi này nó sẽ tạo ra thư mục "build" ở thư mục làm việc hiện
tại, trong đó có File "index.html" thành phẩm cùng với 1 số File liên quan, nghĩa là các
File CSS, ảnh, … trong thư mục "public" được Link vào File HTML cũng sẽ được thêm vào
thư mục "build"
 Tương tự như start, bạn có thể Import CSS vào File JS, nhưng khi biên dịch ra thì nó
không tạo Tag Style, mà gộp tất cả File CSS bị Import thành 1 File CSS duy nhất, File CSS
này được tối giản tối đa, sau đó Link File CSS này vào File "index.html"
 Ở cả 2 chế độ start và build, bạn đều có thể sử dụng CSS Module, chúng là các File với
phần mở rộng ".module.css", khi biên dịch, chúng cũng giống như File CSS bình thường,
là biến thành Tag Style hoặc bị gộp vào File CSS duy nhất, cách viết CSS Module đéo khác
gì CSS thông thường, nhưng với các Selector có dạng .<Tên Class> hoặc chứa .<Tên
Class>, thì các .<Tên Class> đều bị biến thành .<Tên Class Biến Đổi>, ví dụ .foo trở
thành .Bar_foo__abc123, mỗi File CSS Module sẽ có cách mã hóa tên khác nhau, do
đó .foo trong File này có thể là .Bar_foo__abc123 nhưng .foo trong File kia thì
là .Bob_foo__def456, tất cả các Selector còn lại không bị biến đổi
import <Style> from <Đường Dẫn Đến File CSS Module Có Phần Mở Rộng>
 Ví dụ
import style from "./App.module.css"
 Thông qua <Style> ta có thể biết tên Class biến đổi ứng với mỗi tên Class gốc trong File
CSS Module được Import, lệnh sau trả về String tên Class biến đổi ứng với <Tên Class
Gốc>
<Style>.<Tên Class Gốc>
- Ví dụ
const bar = style.foo
- Lệnh trên trả về "Bar_foo__abc123"
 Ngoài ra, bạn cũng có thể sử dụng SCSS hoặc SCSS Module, React Scripts đã tự cấu hình
để chạy SCSS và SCSS Module rồi, bạn chỉ cần cài đặt thư viện SASS là được, File SCSS sẽ
được Import như File CSS, còn File SCSS Module có phần mở rộng là ".module.scss",
cách hoạt động y chang CSS Module, chỉ khác là có thể sử dụng cú pháp SCSS, để cài đặt
thư viện SASS
npm install sass
 Về thư viện CLSX
 Để cài đặt
npm install clsx
 Để Import
- Common Module
const <CLSX> = require("clsx")
- ECMA Module
import <CLSX> from "clsx"
 Lệnh sau chỉ đơn giản là nối tất cả các String lại, cách nhau = 1 dấu cách, rồi trả về String
nối
<CLSX>(<Các String>)
- Ví dụ
clsx("gg", "nore", "foo")
- Lệnh trên trả về "gg nore foo"
 Ngoài ra, ta cũng có thể nối cả String và Object lại với nhau, các Object này phải viết theo
Dictionary, có Value chỉ là true hoặc false, cái nào true thì được nối vào String, ngược lại
không nối, ví dụ
clsx("Gg", {"buma": true, "haha": false}, "taro", {"gg": true})
- Lệnh trên trả về "Gg buma taro gg"
5. Thư Viện React App Rewired?
 React App Rewired bản chất đã chứa thư viện React Scripts luôn rồi, có tác dụng cho
phép bạn ghi đè cấu hình Webpack mặc định của React Scripts, trước tiên ta cần cài đặt
thư viện React App Rewired cùng với Customize CRA
npm install react-app-rewired customize-cra --save-dev
 Khi này, trong thư mục con ".bin" của "node_modules", sẽ có File "react-app-
rewired.cmd"
 Sau đó vào File "package.json", thêm thuộc tính sau
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
- Cái này y chang như của React Scripts
 Sau khi xong xuôi, để khởi chạy Server trong chế độ phát triển, dùng lệnh sau
node_modules/.bin/react-app-rewired.cmd start
 Lệnh trên y chang như start của React Scripts, chỉ có điều trước khi biên dịch nó sẽ dò
trong thư mục làm việc hiện tại xem có File "config-overrides.js" hay không, nếu không
tồn tại thì lỗi, nếu có thì nó sẽ xét thứ được xuất ra từ File này, File này phải là Common
Module, thứ được xuất ra sẽ chứa các cấu hình ghi đè lên Webpack
 Thứ này sẽ phải được tạo ra từ thư viện Customize CRA, do đó trước tiên trong File
"config-overrides.js" ta cần Import thư viện này
const <Customize CRA> = require("customize-cra")
- Tiếp theo, thứ được xuất ra phải là giá trị trả về của lệnh sau
<Customize CRA>.override(<Các Cấu Hình Ghi Đè>)
- <Các Cấu Hình Ghi Đè> nếu không chỉ định thì xài cấu hình Webpack mặc định, nếu chỉ
định thì nó sẽ là 1 loạt các đối số, mỗi thằng sẽ có 1 chức năng khác nhau, ví dụ
module.exports = cra.override(cra.useBabelRc(), cra.disableEsLint())
 Mấy lệnh build cũng tương tự React Scripts, thay react-scripts thành react-app-rewired,
nó vẫn sẽ xem xét File "config-overrides.js" để biên dịch cho phù hợp
 Các đối số bạn có thể truyền vào <Các Cấu Hình Ghi Đè> bao gồm
 Thằng dưới này sẽ khiến cho React App Rewired đọc thêm cấu hình trong File ".babelrc"
trong thư mục làm việc hiện tại, và cấu hình trong File này sẽ được ghi đè vào cấu hình
của File ".babelrc" nội bộ bên trong thư viện React Scripts
<Customize CRA>.useBabelRc()
Development:

1. Front End?
 Ta có cấu trúc thư mục sau
public
index.html Ngõ vào Web
src
index.js File được chạy đầu tiên
routes Định nghĩa các tuyến đường, công khai và ẩn, công
khai thì không cần đăng nhập vẫn xem được, ẩn thì
phải đăng nhập
App.js Function Component bao toàn dự án, sử dụng các
tuyến đường trong routes
components
GlobalStyle Chứa CSS bao toàn dự án
Layout
DefaultLayout Chứa các thành phần cơ bản của Layout như
Header, Footer, Panel, dùng để bao Function
Component con
<Các Layout Khác>
pages
Home Trang đầu tiên khi vào Web
<Các Trang Con Khác>

Nginx:

1. Cài Đặt Trên Windows?


 Vào Link https://nginx.org/en/download.html, ở mục "Stable version" Click vào dòng có
chữ "Windows" + chờ tải + giải nén File vừa tải được 1 thư mục, tạm gọi là A, trong đây
có chứa File "nginx.exe", nên cho A vào biến môi trường Path để có thể dùng lệnh nginx
 Để in ra phiên bản của Nginx
nginx -version
 Để bắt đầu khởi chạy 1 Web Server trên máy bạn, tức dùng máy bạn để lưu trang Web,
cho các máy khác gửi yêu cầu tới, thì bạn phải chạy trực tiếp File "nginx.exe" = Double
Click vào nó, khi này bạn có thể vào trình duyệt tại địa chỉ localhost:80, hay localhost,
bạn sẽ thấy dòng chào mừng, vì nó lấy File HTML trong thư mục A, khi Web Server này
chạy thì cũng có 1 Process tên "nginx.exe" trong Task Manager, có thể xóa Process này
để dừng Web Server
 Để cấu hình Web Server, vào thư mục A, vào thư mục con "conf", chỉnh sửa File
"nginx.conf", bạn có thể chỉnh lại Port thay vì 80 thành 1 số khác, hoặc cấu hình để khi
yêu cầu được gửi tới Web Server này, nó sẽ chuyển hướng tới 1 Server khác, nghĩa là
máy chạy Nginx được xem như 1 Reverse Proxy
 Để chạy lại Web Server
nginx -s reload
2. Cấu Hình Nginx?

Hosting:

1. Vietnix?
 Vào Link https://portal.vietnix.vn/ + đăng nhập bằng tài khoản Google
 Mỗi tài khoản Vietnix sẽ độc lập, nhưng khi nhiều tài khoản hợp lại với nhau, thì chúng
sẽ như dùng chung 1 tài khoản, trong có ít nhất 1 người làm chủ, người chủ có thể xóa
các thành viên khác ra khỏi tổ chức, khi này họ sẽ lại được tự do độc lập
 Dịch vụ Hosting có nghĩa là bạn thuê 1 phần của máy chủ để lưu trữ Web, nghĩa là đéo
thể truy cập được máy chủ này, do đó cần thêm việc dịch vụ đăng ký tên miền, 1 tên
miền được đăng ký sẽ phải chĩa đến địa chỉ IP của máy chủ lưu trữ Web thì mới dùng tên
miền này truy cập được Web, như vậy, bạn phải bỏ tiền riêng để thuê dịch vụ Hosting,
và bỏ tiền riêng để thuê dịch vụ tên miền
 Các dịch vụ có thể thuê là Hosting, VPS, tên miền, …
 Về giao diện, gồm 3 phần
 Thanh trên cùng là thanh lối tắt
- Nút hình cái giỏ góc phải trên, Click vào để vào trang giỏ hàng
 Thanh dưới là thanh điều hướng chính
- Nút tên tài khoản bên phải cùng, Click vào
a) "Chi tiết tài khoản", chuyển tới Tab "Thông tin tài khoản", Tab con "Chi tiết tài khoản"
b) "Quản lí người dùng", chuyển tới Tab "Thông tin tài khoản", Tab con "Quản lí người
dùng"
c) "Chi tiết liên hệ", chuyển tới Tab "Thông tin tài khoản", Tab con "Chi tiết liên hệ"
d) "Quản lí đăng nhập", chuyển tới Tab "Thông tin tài khoản", Tab con "Quản lí đăng nhập"
e) "Lịch sử Email", chuyển tới Tab "Thông tin tài khoản", Tab con "Lịch sử Email"
f) "Mật khẩu", chuyển tới Tab "Thông tin tài khoản", Tab con "Mật khẩu"
g) "Thiết lập bảo mật", chuyển tới Tab "Thông tin tài khoản", Tab con "Thiết lập bảo mật"
- Nút "Đăng ký dịch vụ", Click vào để vào trang con đăng ký dịch vụ, Tab "Hosting"
 Panel bên trái là Panel hoa tiêu
 Phần ở giữa khác nhau với từng Tab trong Panel hoa tiêu
- Về Tab "Thông tin tài khoản"
a) Tab con "Chi tiết tài khoản", chỉnh sửa thông tin cá nhân, có mục "Phương thức thanh
toán" chọn "Momo Payment" để thanh toán mọi dịch vụ bằng Momo
- Về Tab "Dịch vụ của tôi", liệt kê các dịch vụ bạn đã đăng ký trừ dịch vụ tên miền, nó có
thống kê số lượng dịch vụ đang chạy với mỗi loại Hosting, VPS, …
a) Cột "Gói đăng ký", tên gói dịch vụ
b) Cột "Giá", là giá gốc chưa bao gồm thuế VAT
c) Cột "Chu kỳ", là khoảng thời gian giữa mỗi lần thanh toán để duy trì dịch vụ
d) Cột "Ngày hết hạn", ngày bạn phải thanh toán để duy trì
e) Cột "Trạng thái" , hiển thị trạng thái dịch vụ
f) Khi Click vào 1 dịch vụ, sẽ vào phần chỉnh sửa dịch vụ đó
- Về Tab "Quản lý tên miền", liệt kê tất cả tên miền đã đăng ký, nó có thống kê số lượng
tên miền ứng với mỗi đuôi ".com", ".vn", …
a) Cột "Tên miền" là tên miền
b) Cột "Ngày đăng ký" là ngày đăng ký tên miền
c) Cột "Ngày hết hạn" là ngày cần gia hạn
d) Cột "Tình trạng" là trạng thái tên miền
e) Nút "Quản lý", Click vào để vào phần chỉnh sửa tên miền đó
 Về phần chỉnh sửa tên miền
 Thanh trên cùng là tên miền đang chỉnh sửa, nút mũi tên bên trái để quay về
 Tab "Tổng quan", hiển thị tên miền, trạng thái, ngày đăng ký, gia hạn, số tiền thanh toán
lần đầu, số tiền cần để gia hạn, hình thức thanh toán
 Tab "Hồ sơ tên miền", sau khi đăng ký tên miền bạn cần vào Tab này ngay lập tức để tải
ảnh CCCD lên, mặt trước và mặt sau, sau đó Click nút "Tải bản khai" + vào File vừa tải để
ký tên lên đó, màu đen, dùng phần mềm chỉnh sửa PDF, rồi nộp File PDF đó lên
 Tab "Nameservers", tại đây sẽ hiển thị các ANS của tên miền bạn, có thể chỉnh sửa,
chúng là các NS Record trong TLD Server
 Tab "Quản lý DNS", tại đây liệt kê tất cả DNS Record trong Zone File ứng với tên miền
của bạn trong ANS
- Cột "NAME", là tên miền của bạn hoặc các tên miền cùng nó với nó
- Cột "TYPE", loại DNS Record
- Cột "CONTENT", giá trị của DNS Record
- Cột "TTL", là TTL của DNS Record, lưu ý nếu < Minimum TTL của SOA Record thì sẽ chọn
Minimum TTL
- Bạn có thể xóa DNS Record bằng nút thùng rác bên phải cùng, không thể xóa SOA
Record, Email quản trị trong SOA Record này là hostmaster.<Tên Miền>, dấu chấm ở đây
thay cho @, nghĩa là bạn phải tự tạo Email hostmaster@<Tên Miền> để làm Email quản
trị, chứ nó không tạo giúp bạn
- Bạn có thể chỉnh sửa DNS Record bằng cách Click vào nút bút chì + nhập lại thông tin +
Click nút chữ V
- Bạn có thể thêm DNS Record bằng cách Click dấu cộng góc phải trên + điền thông tin +
Click "Add", mới khi tạo tên miền, bạn cần phải tạo 1 A Record, ánh xạ tên miền của bạn
tới địa chỉ IP của máy chủ đang Host trang Web của bạn thì mới sử dụng được tên miền
này
 Về phần chỉnh sửa dịch vụ loại Hosting
 Thanh trên cùng là tên gói dịch vụ, nút mũi tên bên trái hoặc nút "Quản lí dịch vụ" để
quay trở lại
 Khối phía dưới, chứa tên dịch vụ, trạng thái dịch vụ, tên miền Fake tương ứng, lưu ý tên
miền Fake đéo có tác dụng gì ngoài việc làm phần mở rộng cho các Email thuộc trang
Web của bạn, bạn chỉnh cái mẹ gì cũng được, số tiền không bao gồm thuế VAT đã thanh
toán lần đầu và cần thanh toán định kỳ, chu kỳ thanh toán, hình thức thanh toán, ngày
đăng ký dịch vụ và ngày cần gia hạn
 Khối dưới nữa
- Nút "Đổi tên miền chính", Click rồi nhập tên miền mới để đổi tên miền Fake, các Email
với tên miền cũ cũng tự động được cập nhật thành tên miền Fake
- Nút "Cài đặt lại hosting", Click vào rồi nhập đúng tên miền Fake sau đó Click "Xác nhận"
để xóa hết tất cả Web của bạn ở máy chủ Host, nghĩa là làm lại như mới, các Email thuộc
Host cũng xóa luôn
- Nút "Tải lại hosting", Click + Click "Xác nhận" để làm mới lại RAM của máy chủ Host
 Khối "Liên kết nhanh"
- "Đăng nhập vào cPanel", Click để vào trang C Panel, Tab "Tools"
- "Đăng nhập vào Webmail", Click để vào trang Web Mail
 Khối "Tạo nhanh tài khoản Email"
- Ô "Tên tài khoản" nhập tên người dùng bất kì, nó sẽ được thêm @<Tên Miền Fake> ở
phía sau
- Ô "Mật khẩu" nhập mật khẩu cho Email này, phải nhập mật khẩu mạnh mới tạo được +
Click "Tạo Email" để tạo Email
 Khối "Liên kết với cPanel"
- "Email Accounts", Click để vào trang C Panel, Tab "Tools", khối "Email", mục "Email
Accounts"
- "File Manager", Click để vào trang File Host
 Về trang con đăng ký dịch vụ
 Về Tab "Hosting"
- Phần bên dưới liệt kê các bộ gói Hosting, trong mỗi bộ sẽ có nhiều gói khác nhau, Click
vào 1 bộ để tiếp tục, phần bên dưới sẽ liệt kê các gói thuộc bộ đó, với mỗi gói có các
thông tin sau
a) Tên gói
b) Số Core của CPU
c) Dung lượng RAM
d) Dung lượng đĩa
e) Số tên miền, nói cách khác, số trang Web có thể được Host trên máy
f) Thanh chọn chu kỳ thanh toán
g) Nút "Đăng ký", Click vào + nhập tên miền đầu tiên muốn chõ vào cái Host này, tên miền
phải đã đăng ký + Click "Kiểm tra" + Click "Thêm vào giỏ hàng" để thêm vào trang giỏ
hàng + Click "Thanh toán" rồi thanh toán bằng Momo bằng quét mã QR
 Về Tab "Tên miền"
- Tab con "Đăng ký tên miền mới", nhập tên miền muốn đăng ký, phải không trùng với tên
miền nào + Click "Kiểm tra" + Click "Thêm vào giỏ" để thêm vào trang giỏ hàng + xem và
chỉnh sửa các Authoritative Name Server nếu muốn + Click "Thêm vào giỏ hàng" + Click
"Thanh toán" để trả tiền bằng Momo quét QR
- Sau khi đăng ký tên miền mới với đuôi ".com", ".net", ".info", ".org", thì phải lập tức vào
Link https://thongbaotenmien.vn/thongbaomoi.xhtml + nhập tên miền vừa đăng ký +
Click "Tra cứu" + Click "Thông báo sử dụng tên miền" + mục "Nhà đăng ký quản lí" chọn
cái nào có "VIETNIX" + nhập mật khẩu bất kì + điền phần thông tin còn lại + Click "Thực
hiện"
 Về trang Web Mail, Link của nó sẽ độc nhất cho mỗi Host, bạn có thể chia sẽ Link này
cho mọi người, trang này như Gmail, nhưng chỉ cho phép các Email với tên miền Fake
được đăng nhập vào, ban đầu khi đăng nhập vào sẽ ở trang con thông tin chung, ở phần
con chính
 Trang con thông tin chung
- Thanh trên cùng không đổi với các phần con khác nhau
a) Biểu tượng "Webmail" bên trái Click để về phần con chính
b) Nút "LOGOUT" Click để đăng xuất ngay
c) Nút hình biểu đồ tròn, có ghi dung lượng đã dùng để lưu trữ thư của tài khoản Email này
/ dung lượng tối đa cho phép của Email này, Click vào để vào phần con dung lượng
d) Nút hình người, có ghi Email hiện tại, Click để ẩn hiện Panel cá nhân, gồm mục
"Roundcube", Click để vào trang con thư nhận gửi, mục "Spam Filters" Click để vào phần
con lọc rác, mục "Password & Security", Click để vào phần con bảo mật, mục "Manage
Disk Usage", Click để vào phần con dung lượng
- Về phần con chính
a) Tick "Open my inbox when I log in" góc trái trên để thay vì mỗi lần đăng nhập là vào
trang con thông tin chung, thì nó sẽ vào luôn trang con thư nhận gửi
b) Click nút "Open" góc trái trên để vào trang con thư nhận gửi
 Trang con thư nhận gửi
- Thanh công cụ lề bên trái là cố định
a) Nút tròn đỏ dưới cùng, Click để đăng xuất ngay
b) Nút mặt trăng gần dưới cùng, Click để đổi màu chủ đạo từ trắng thành đen, nó sẽ thành
nút mặt trời, Click lại để đen thành trắng
c) Nút hình vô cực màu đỏ cam ở giữa, Click để về trang con thông tin chung
d) Nút hình phong bì, Click để vào phần con thư nhận gửi
e) Nút bút chì, Click để tiến hành soạn thư và gửi thư, chỉ gửi được cho các Email có cùng
tên miền Fake
2. Trang C Panel?
 Vietnix sẽ cấp cho bạn tài khoản mật khẩu để bạn đăng nhập vào C Panel, trang đăng
nhập của C Panel có Link là độc nhất với mỗi Host, nên bạn có thể chia sẻ nó, tuy nhiên
cũng sẽ chỉ có duy nhất 1 tài khoản có thể đăng nhập được là tài khoản được cung cấp
như đã nói
 Giao diện gồm 3 phần
 Thanh trên cùng là thanh tài khoản
- Nút Avatar bên phải, Click để ẩn hiện Panel cá nhân
a) "Password & Security", Click để vào phần con bảo mật
b) "Contact Information", Click để vào phần con thông tin liên hệ
c) "Log Out", đăng xuất ngay
 Panel bên trái là Panel điều hướng, gồm các Tab
 Phần bên phải khác nhau với mỗi Tab và phần con
- Về Tab "Tools"
a) Khối "General Information" bên phải, mục "Current User" hiện tên tài khoản C Panel,
mục "Primary Domain" là tên miền Fake, mục "Shared IP Address" là địa chỉ IP của máy
chủ Host, mục "Last Login IP Address" là địa chỉ IP của máy đăng nhập vào tài khoản C
Panel này gần đây nhất, mục "Server Information", Click đê vào phần con thông tin
Server, mục "Home Directory", là đường dẫn tới thư mục chứa trang Web, thông
thường do Server là Linux nên đường dẫn sẽ là /home/<Tên Tài Khoản C Panel>, tạm gọi
đây là đường dẫn gốc
b) Khối "Email" ở đầu tiên, mục "Email Accounts", Click để vào phần con tài khoản Email
c) Khối "Files" ở giữa, mục "File Manager", Click để vào trang File Host
d) Khối "Software" ở gần cuối, mục "Setup Node.js App", Click để vào phần con Node JS
- Về phần con bảo mật, dùng để đổi mật khẩu tài khoản C Panel, nhập mật khẩu hiện tại
và mật khẩu mới + Click "Change your password now!"
- Về phần con thông tin liên hệ, điền Email sẽ nhận được thông báo khi mật khẩu C Panel
thay đổi + Click "Save"
- Về phần con thông tin Server
a) "Server Name", tên Server, tức tên máy chủ Host
b) "Hosting Package", tên viết tắt của gói Hosting đăng ký
c) "Operating System", tên hệ điều hành của Server, thông thường là linux
d) "Shared IP Address", địa chỉ IP của Server, tức địa chỉ IP của máy chủ Host
- Về phần con tài khoản Email, ở đây sẽ liệt kê các Email thuộc Host, có phần sau @ là tên
miền Fake, tuy nhiên trong các Email này sẽ có 1 Email hệ thống được tạo mặc định, địa
chỉ Email của nó có cú pháp <Tên Tài Khoản C Panel>@<Tên Server>.vietnix.vn, không
thể thay đổi hay xóa Email này, nó vẫn có thể đăng nhập được vào trang Web Mail
a) Nút "Create" để thêm 1 Email mới, gồm địa chỉ Email, mật khẩu, dung lượng tối đa +
Click "Create"
b) Phần "Filter", chọn "All" để liệt kê tất cả Email, "System Account" để liệt kê mỗi Email hệ
thống
c) Có thể Tick vào ô vuông trước mỗi Email được liệt kê rồi Click "Delete" để xóa các Email
này
d) Nút "Check Email" bên phải mỗi Email, Click để đăng nhập vào trang Web Mail
e) Nút "Manage" để vào phần chỉnh sửa Email như đổi mật khẩu mới, giới hạn lại dung
lượng tối đa, xóa Email
- Về phần con Node JS, 1 tên miền sẽ có nhiều Web Application trên nó, mỗi Web
Application sẽ trú ngụ tại 1 Path khác nhau, Path của Web Application này có thể nằm
trong Path của Web Application kia, mỗi Web Application cũng sẽ định cư trong 1 thư
mục con cháu trong đường dẫn gốc
a) Tab "WEB APPLICATIONS" liệt kê tất cả các Web Application hiện tại trên tên miền Fake,
nghĩa là bạn nên chỉnh tên miền Fake trùng với tên miền thật để có thể hoạt động, cột
"App URI" có cú pháp <Tên Miền><Path Tương Ứng>, cột "App Root Directory" là đường
dẫn tuyệt đối tới thư mục mà Web Application định cư, cột "Mode" là chế độ phát triển
= "development" hoặc đã thành phẩm = "production", cột "Status" là trạng thái Web
Application, "started" tức đã chạy, "stopped" tức đã dừng, nó còn kèm theo phiên bản
Node JS để chạy Web Application, cột "Actions", nút ô vuông đầu tiên để dừng Web
Application, thành nút tam giác để chạy, nút mũi tên tròn để chạy lại, nút thùng rác để
xóa Web Application, nút bút chì để vào phần Tab chỉnh sửa Web Application
b) Tab chỉnh sửa Web Application, nút "DESTROY" để xóa Web Application, "CANCLE" để
quay về, "SAVE" để lưu chỉnh sửa, mục "Node.js", nút "STOP APP" để dừng, "RESTART"
để chạy lại, mục "Node.js version", chọn phiên bản Node JS để chạy, mục "Application
Mode", chọn chế độ phát triển hoặc đã thành phẩm, mục "Application root", ghi đường
dẫn tới thư mục mà Web Application định cư, bắt đầu từ trong đường dẫn gốc, ví dụ
foo/bar, mục "Application URL", kế tên miền bạn sẽ điền Path mà Web Application trú
ngụ, cách khi như "Application root", mục "Application startup file" điền đường dẫn tới
File JS có phần mở rộng, bắt đầu từ trong thư mục định cư, cách viết tương tự như vừa
nói, File JS này được gọi là File Entry, mục "Detected configuration files", nếu trong thư
mục định cư chứa File "package.json", thì nút "Run NPM Install" có thể nhấn được để cài
đặt các thư viện được nêu trong File này, y chang lệnh npm install, mục "package.json"
sẽ hiển thị nếu File này tồn tại, nút "Edit" Click vào để chỉnh sửa File "package.json" +
Click "SAVE" để lưu
c) Nút "CREATE APPLICATION" góc phải trên Click để tạo Web Application, điền thông tin
như khi chỉnh sửa + Click "CREATE", khi tạo Web Application, nếu các đường dẫn bạn
điền chưa tồn tại thì sẽ tự động tạo trong dự án, chính là tạo các thư mục và File trong
đường dẫn gốc, riêng Path trú ngụ bạn điền, ví dụ bạn điền foo/bar, thì trong thư mục
"public_html" của đường dẫn gốc sẽ xuất hiện thư mục "foo" và trong "foo" có thư mục
"bar", thư mục "bar" rỗng
d) Khi chạy lần đầu hoặc chạy lại 1 Web Application, thì tương đương việc bạn vào thư mục
định cư của Web Application đó, rồi chạy lệnh node <Đường Dẫn Tới File Entry>, nhưng
trong Code JS, bạn sẽ không thể chỉ định cụ thể Port mà bạn sẽ lắng nghe, ví dụ với
Express JS, nếu bạn ghi app.listen(3000) thì nó tương đương app.listen(), nghĩa là bạn
không được phép chỉ định Port, khi bạn viết app.listen(), thì tự động nó lắng nghe trên
Port 80 và 443, chính là Port mặc định của giao thức HTTP và HTTPS, các phương thức
get thì vẫn lấy Path truyệt đối trên URL, đéo quan tâm Path trú ngụ của Web Application,
ví dụ app.get("/concac/foo", () => {}) thì vẫn bắt gg.com/concac/foo, cho dù Web
Application trú ngụ ở gg.com/concac, nghĩa là nếu bạn viết app.get("/foo", () => {}), thì
không bắt gg.com/concac/foo mà bắt gg.com/foo, nhưng gg.com/foo lại không thuộc
gg.com/concac nên không bắt được, nghĩa là chỉ bắt được những Path nằm trong Path
trú ngụ
 Về trang File Host, thư mục to nhất là đường dẫn gốc, ở đây bạn có thể chỉnh sửa thêm
xóa các File và thư mục tùy thích
 Về cơ chế URL, xét phần Path của nó, đối chiếu xem có Path nào tương tự trong thư mục
"public_html" trong đường dẫn gốc không, ví dụ Path của URL là /foo/bar, thì nếu trong
thư mục "public_html" có thư mục "foo", và trong "foo" có "bar", thì sẽ xét trong "bar"
xem, nếu trong đây có File "index.html" thì ngay lập tức phản hồi về File này, tức phần
Response Body sẽ là File "index.html", nếu tất cả điều kiện trên không xảy ra, thì sẽ tiến
hành phân tích Path của URL, lần lượt đi ngược lại, ví dụ Path là /foo/bar/alice thì đi
ngược lại sẽ là /foo/bar/alice, rồi /foo/bar, rồi /foo, rồi cuối cùng là /, cho tới khi có 1
Web Application đang chạy trú ngụ tại Path đó, ví dụ sẽ dùng lại tại /foo nếu có 1 Web
Application đang trú ngụ tại /foo, sau đó tiếp tục kiểm tra xem Path trú ngụ của Web
Application này có tồn tại trong "public_html" không, tiếp tục ví dụ trên thì thư mục
"foo" phải ở trong thư mục "public_html" thì điều kiện mới thỏa mãn, sau đó sẽ xử lí
URL theo Web Application này, ví dụ theo Web Application này, thì với Path
/foo/bar/alice của URL sẽ trả về chuỗi "ggnore", thì Response Body sẽ là "ggnore", nếu
điều kiện không thỏa mãn, thì sẽ gửi về lỗi 404
 Các File ảnh, văn bản hay gì đó trong thư mục "public_html" đều có thể truy cập bằng
URL
3. Về Máy Chủ Của Vietnix?
 Nó đã được cài đặt python3, tức là bạn có thể kết nối SSH rồi chạy lệnh như python3.py,
…, và nhiều lệnh khác nữa, tuy nhiên khi bạn đóng Shell ở máy bạn thì các Process này
cũng bị giết, tuy nhiên để khắc phục điều này, tức Process vẫn chạy cho dù bạn đóng
Shell, thì dùng lệnh Linux sau
nohup <Lệnh> &
 Ví dụ
nohup python3 foo.py &
4. WHOIS?
 Vào Link https://www.whois.com/
 Về giao diện, gồm 2 phần
 Thanh trên cùng là thanh điều hướng
- Ô Input nhập 1 tên miền + Click "WHOIS" để vào phần tra cứu tất cả thông tin về tên
miền này
 Phần dưới khác nhau với mỗi Tab ở thanh điều hướng
5. ICANN (Internet Corporation For Assigned Names And Numbers)?
 Là 1 tổ chức phi lợi nhuận có nhiệm vụ đánh địa chỉ IP cho các thiết bị kết nối với
Internet
6. Cloudflare?
 Vào Link https://dash.cloudflare.com/, đăng nhập = tài khoản Cloudflare
 Giao diện gồm 3 phần
 Thanh trên cùng là thanh công cụ
- Biểu tượng "CLOUDFLARE" bên trái, Click vào để tải lại trang, Tab "Account Home"
- Nút Avatar bên phải cùng
a) "My Profile", Click vào để vào phần con Profile
b) "Account Home", để vào Tab "Account Home"
c) "Billing", để vào Tab "Billing"
d) "Appearance", để vào phần con Profile, cuộn xuống 1 chút
e) "Log Out", đăng xuất
 Panel bên trái là Panel điều hướng
- Phần trên cùng là địa chỉ Email tài khoản
 Phần bên phải khác nhau với mỗi Tab ở Panel điều hướng
- Về Tab "Websites", vào Tab này để thêm tên miền của bạn vào, khi này, nó sẽ cấp cho
bạn địa chỉ của 2 ANS của Cloudflare, bạn phải thêm 2 NS Record vào danh sách các DNS
Record trong trang Web của nhà cung cấp tên miền của bạn, và xóa tất cả NS Record
khác, với Vietnix thì bạn còn phải vào Tab "Nameservers" của phần chỉnh sửa tên miền
để đặt lại các tên miền của Cloudflare, sau đó chờ 1 ngày để nó cập nhật lại, 2 ANS này
có 1 cơ chế đặc biệt, khi 1 DNS Resolver gửi yêu cầu tới, nó sẽ gửi thêm địa chỉ IP của
CDN (Content Delivery Network) Server gần nhất với người gửi yêu cầu tới trang Web,
nhờ đó mà DNS Resolver thay vì gửi yêu cầu trực tiếp lên Server lưu trang Web ở tút xa,
thì nó chỉ gửi tới CDN Server gần đó, CDN Server nhận được yêu cầu, nếu nó thấy trong
bộ nhớ đệm của nó đã có trang Web đó rồi thì gửi thẳng về cho người dùng luôn, còn
không thì vẫn gửi yêu cầu lên Server lưu trang Web, và 1 khi Server này gửi về trang
Web, thì CDN Server cũng lưu nó vào bộ đệm, đồng thời lan truyền cho tất cả CDN
Server khác trên thế giới trang Web này, nhờ đó mà bất cứ ai cũng có thể truy cập nhanh
được trang Web
- Về Tab "DNS", liệt kê các DNS Record của 2 ANS của Cloudflare cấp cho bạn, cần có 1 A
Record chĩa tên miền của bạn vào địa chỉ IP của Host

You might also like