Banner 1
Banner 2
hero

Phạm Văn Tú

4518 thành viên

Giới thiệu

Developer, Blogger, Freelancer... Và một số cái đơ lơ thơ mơ khác...

Developer tại KOZOCOM - Viet Nam
Từng làm Developer tại GCO Software
Từng làm Developer tại IZI Software
Sống tại Đà Nẵng
Từng học tại Trường Đại học Sư phạm - ĐH Đà Nẵng
Đã học tại THPT Phan Thành Tài, Đà Nẵng

Đột nhập vào VPS mượt hơn cùng TuPV

04/14/2025
Đột nhập vào VPS mượt hơn cùng TuPV
Bài viết này mình sẽ giới thiệu vài cách truy cập vào VPS nha, cách cuối là xịn mịn nhất 😋 #### Cách 1: Dùng username và password để truy cập vào VPS Khi mình mua VPS, thường nhà cung cấp sẽ gửi cho mình username và password qua email. Để truy cập vào VPS thì mình: ``` ssh ten_dang_nhap@ip_vps # Ví dụ: ssh root@103.173.66.22 ``` Tiếp theo nhập mật khẩu là có thể truy cập vào được rồi. 📌 Mặc định SSH sử dụng cổng 22. Nếu VPS của bạn dùng cổng khác, thêm `-p`: ``` ssh root@103.173.66.22 -p 8686 ``` --- #### Cách 2: Dùng SSH key thay vì mật khẩu Thay vì mỗi lần truy cập vào VPS phải nhập username & password, bạn có thể dùng SSH key — **an toàn và tiện hơn nhiều**. 👉 Cách tạo SSH key trên máy cá nhân mình có bài viết ở [đây](http://localhost:3000/ssh-key-trong-github), bạn có thể xem qua trước. Sau khi bạn đã tạo SSH key (gồm 2 file: `id_rsa` và `id_rsa.pub`, hoặc tên tuỳ bạn đặt), tiếp theo là copy **public key** (`.pub`) lên VPS để xác thực. ##### 🛠 Cách 1: Copy public key bằng `ssh-copy-id` (nhanh, gọn) ``` ssh-copy-id -i ~/.ssh/id_rsa.pub root@ip_vps ``` Sau khi nhập mật khẩu lần đầu, key của bạn sẽ được copy vào file `authorized_keys` trên VPS. ##### 🛠 Cách 2: Thêm SSH key thủ công (khi VPS chưa có gì sẵn) **Bước 1:** Trên máy bạn, copy nội dung public key: ``` cat ~/.ssh/id_rsa.pub ``` → Copy toàn bộ dòng hiển thị. **Bước 2:** Đăng nhập vào VPS bằng mật khẩu: ``` ssh root@ip_vps ``` **Bước 3:** Trên VPS, tạo thư mục `.ssh` nếu chưa có: ``` mkdir -p ~/.ssh && chmod 700 ~/.ssh ``` **Bước 4:** Tạo và mở file `authorized_keys`: ``` nano ~/.ssh/authorized_keys ``` → Dán public key, nhấn `Ctrl + O` để lưu, `Ctrl + X` để thoát. **Bước 5:** Kiểm tra lại file chứa đúng key chưa: ``` cat ~/.ssh/authorized_keys ``` → Nếu thấy key vừa dán là xong! ✅ Giờ thì bạn có thể SSH mà không cần gõ mật khẩu nữa: ``` ssh root@ip_vps ``` 📌 Nếu private key không nằm ở vị trí mặc định (`~/.ssh/id_rsa`), bạn dùng: ``` ssh -i /duong_dan_den/id_rsa root@ip_vps ``` --- #### 🔥 Cách 3: Dùng Visual Studio Code (VSCode) để kết nối vào VPS Cách này khá tiện lợi và mình đang dùng để quản lý & chỉnh sửa trực tiếp trên VPS thông qua **VSCode + extension Remote - SSH**. Bạn không cần dùng terminal mà vẫn thao tác được như local 😄 --- **Bước 1: Cài đặt extension Remote - SSH** - Mở VSCode - Nhấn `Ctrl + Shift + X` để vào Extensions - Tìm “Remote - SSH” và cài đặt ![Thumbnail VPS](http://localhost:4000/static/2bfb5db5873c81460fef46701.webp) > 📎 Shortcut cài nhanh: [Remote - SSH](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-ssh) --- **Bước 2: Cấu hình SSH trong file `config`** - Nhấn `Ctrl + P`, dán `~/.ssh/config` để mở nhanh file config. - Thêm thông tin VPS của bạn như sau: ``` Host TenVpsCuaBan # đặt tên tuỳ ý để hiển thị trong VSCode HostName 103.173.66.22 # IP VPS User root # User để SSH IdentityFile ~/.ssh/id_rsa # đường dẫn tới private key ``` 📌 Nếu VPS dùng cổng SSH khác, thêm dòng: ``` Port 8686 ``` --- **Bước 3: Kết nối tới VPS từ VSCode** - Nhấn `Ctrl + Shift + P` - Gõ: `Remote-SSH: Connect to Host...` - Chọn `TenVpsCuaBan` bạn vừa cấu hình - VSCode sẽ mở ra một cửa sổ mới bên trong môi trường VPS 🎉 --- #### ✨ Lợi ích khi dùng Remote - SSH với VSCode - **Tiết kiệm thời gian** khi chỉnh sửa file trực tiếp trên VPS. - **Tận dụng full tính năng** của VSCode như Prettier, ESLint, Git... - **Không cần terminal**, thao tác nhanh như đang làm việc local. 💡 Đây là cách mình dùng mỗi ngày để làm việc với project trên VPS. Cực kỳ tiện và chuyên nghiệp luôn! --- Hy vọng bài viết này giúp bạn làm chủ việc kết nối và quản lý VPS nhanh hơn nha 🚀

JavaScript Class

04/12/2025
JavaScript Class
Bài này mình cùng tìm hiểu Class trong Javascript nó là gì nhé. Từ khi được giới thiệu trong ES6 (ECMAScript 2015), Class đã trở thành một tính năng không thể thiếu khi phát triển ứng dụng JavaScript theo hướng đối tượng. ### 1. Class là gì? Class trong JavaScript giúp ra các object có cùng thuộc tinh và phương thức nhất định. Đồng thời tăng tính tái sử dụng code và dễ dàng quản lí hơn ### 2. Tạo Class đầu tiên với `User` Chúng ta ví dụ tạo 1 class `User`, đại diện cho một người dùng trong hệ thống nhé. ```js class User { constructor(hoTen) { // this.name: thuộc tính của đối tượng // hoTen: tham số truyền vào constructor this.name = hoTen; } // Phương thức greet() { return `Xin chào, tôi là ${this.name}`; } } // Tạo các object (instance) từ class User const user1 = new User("TuPV"); const user2 = new User("VuPV"); console.log(user1.greet()); // Xin chào, tôi là TuPV console.log(user2.greet()); // Xin chào, tôi là VuPV ``` ### 3. Kế thừa Class với `Admin` Giả sử bạn muốn có một loại người dùng đặc biệt — đó là **Admin** (quản trị viên). Admin cũng là một `User`, nhưng có thêm quyền hạn (permissions) riêng biệt. Lúc này, bạn có thể **kế thừa** từ class `User` để tạo ra class `Admin`. ```js class Admin extends User { constructor(hoTen, quyenHan) { super(hoTen); // Gọi constructor của class cha (User) để khởi tạo this.name this.role = "Admin"; this.permissions = quyenHan; // mảng các quyền } // Ghi đè phương thức greet greet() { // Gọi lại phương thức greet của class cha và mở rộng nội dung return ( super.greet() + ` Tôi là quản trị viên có quyền: ${this.permissions.join(", ")}` ); } // Thêm phương thức riêng của Admin hasPermission(quyen) { return this.permissions.includes(quyen); } } const admin1 = new Admin("Admin TuPV", ["create", "delete", "update"]); console.log(admin1.greet()); // Xin chào, tôi là Admin TuPV Tôi là quản trị viên có quyền: create, delete, update console.log(admin1.hasPermission("delete")); // true console.log(admin1.hasPermission("read")); // false ``` ### 4. Tại sao nên sử dụng Class và kế thừa? - **Tổ chức mã nguồn tốt hơn** khi ứng dụng phát triển lớn. - **Tái sử dụng code** thông qua kế thừa (`extends`). - **Dễ mở rộng**: Bạn có thể thêm nhiều loại người dùng khác nhau (Admin, Editor, Guest...) mà không phải viết lại logic chung. --- ### 5. Tổng kết - `class` là cách hiện đại để định nghĩa và tổ chức code theo hướng đối tượng. - `constructor` giúp khởi tạo dữ liệu ban đầu cho đối tượng. - `extends` dùng để kế thừa từ class khác, tái sử dụng logic và mở rộng chức năng. - `super()` gọi constructor của class cha. --- ## 6. Từ khóa `static` là gì? Từ khóa `static` trong JavaScript được dùng để định nghĩa **phương thức hoặc thuộc tính tĩnh** cho class. Điều đặc biệt là các phương thức/thuộc tính `static` **không thể gọi từ object (instance)**, mà phải gọi **trực tiếp từ class**. Nói cách khác, `static` thường được dùng cho các hành vi hoặc thông tin chung mà không phụ thuộc vào dữ liệu cụ thể của một object. ### Ví dụ: ```js class User { constructor(hoTen) { this.name = hoTen; } greet() { return `Xin chào, tôi là ${this.name}`; } test() { console.log(this.sayHello()); } // Phương thức static static sayHello() { return "Chào mừng bạn đến với hệ thống!"; } } const userTest = new User("TuPV"); console.log(userTest.greet()); // Xin chào, tôi là TuPV console.log(User.sayHello()); // Chào mừng bạn đến với hệ thống! console.log(userTest.sayHello()); // error: userTest.sayHello is not a function console.log(User.test()); // error: User.test is not a function vì static method không thể gọi từ instance ``` > ⚠️ Gọi `userTest.sayHello()` sẽ bị lỗi vì `sayHello` là static method và chỉ có thể gọi qua class `User`. --- Bạn cũng có thể dùng `static` trong class con kế thừa từ class cha: ```js class Admin extends User { constructor(hoTen, quyenHan) { super(hoTen); this.permissions = quyenHan; } greet() { return `${super.greet()} Tôi là Admin.`; } static getRoleName() { return "Quản trị viên"; } } console.log(Admin.getRoleName()); // Quản trị viên ``` --- ## 7. Khi nào nên dùng `static`? - Khi bạn muốn tạo các **hàm tiện ích dùng chung**, ví dụ như kiểm tra dữ liệu đầu vào, định dạng chuỗi, kiểm tra quyền truy cập... - Khi bạn không cần truy cập đến `this` của từng object. - Khi bạn muốn lưu **biến dùng chung** cho toàn bộ class, không gắn với từng instance. --- ## 8. Tổng kết thêm | Khái niệm | Mô tả | | ------------- | ---------------------------------------------------------------- | | `class` | Tạo khuôn mẫu đối tượng | | `constructor` | Hàm khởi tạo khi tạo object | | `extends` | Kế thừa từ class khác | | `super()` | Gọi constructor hoặc method của class cha | | `static` | Định nghĩa phương thức/thuộc tính tĩnh, dùng trực tiếp qua class | --- Hy vọng sau bài viết này bạn đã hiểu rõ hơn về cách sử dụng `class`, `extends`, `super` và `static` trong JavaScript một cách thực tiễn và dễ hiểu.

Tên miền và VPS

04/10/2025
Tên miền và VPS
Hé looooo, lâu ngày quá blog mốc mêu rùi 😄, mới hôm nào kêu viết bài mở hàng 2025 mà vèo cái đã tháng 4 rồi nhanh thiệt á =))). Hứa trong tháng 4 này sẽ hoàn thành các bài viết hướng dẫn deploy dự án cơ bản như Html Css hoặc React, Next hay Node lên VPS như thế nào và thiết kế CI, CD qua Github Action luôn nhen Mình hay mua tên miền ở [Inet](https://inet.vn/). Các bạn có thể lựa các tên miền tiết kiệm chi phí để demo như .fun, .id.vn... #### VPS **VPS** ở Việt Nam thì mình có thể mua ở [TinoHost](https://tinohost.com/) hay [ZHost](http://zhost.vn/) chỗ nào cũng được miễn các bạn thấy i tín là quất thui. Cấu hình thì để demo thì mình có thể chọn gói thấp nhất của các nhà cung cấp để demo cũng tẹc ga rồi, còn thực tế thì tuỳ dự án mình chọn gói cho phù hợp nha Khi mua VPS mọi người chọn version cho Ubuntu hỗ trợ lâu dài tí nha có dạng LTS (Long term support) có thể lên trang này check [wiki.ubuntu.com/Releases](https://wiki.ubuntu.com/Releases) vì khi không để ý sẽ chọn nhầm sang version cũ như `23.04` không còn support nữa thì khi chạy `sudo apt-get update` sẽ không được. Lỡ chọn rồi thì fix bằng command ở dưới để update lại version Ubuntu nhé ``` sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak sudo sed -i -re 's/([a-z]{2}.)?archive.ubuntu.com|security.ubuntu.com/old-releases.ubuntu.com/g' /etc/apt/sources.list sudo apt-get update && sudo apt-get dist-upgrade ``` #### DNS **DNS** là viết tắt của (Domain Name System) giúp mình dịch từ tên miền sang địa chỉ IP. Thay vì gõ `103.173.66.24:3002` thì mình gõ `phamvantu.com` thì đó là nhờ vào DNS dịch giúp mình đó > **Note:** Để biết được trang web đang dùng địa chỉ ip nào thì chỉ cần ping domain_name là được. Ví dụ `ping phamvantu.com` thì nó ra địa chỉ ip là 103.173.66.24 thì đây là địa chỉ IP của trang web mình đó. Nhưng các bạn vào thì có thể ra trang Nginx thì đó là do mình không config nó. Tuỳ trang có hay không chứ không phải lúc nào nhập ip cũng ra trang web tương ứng nhen #### Tên miền Khi mua 1 tên miền thì họ sẽ cho 2 thông tin mình chỉnh sửa - Name Server: Sửa máy chủ DSN của tên miền (Mặc định sẽ dùng máy chủ của nhà bán tên miền) - Bản ghi DNS: Sửa các bảng ghi DNS của tên miền theo máy chủ đó > Tên miền dùng máy chủ DNS nào thì phải sửa các bản ghi DNS theo máy chủ DNS đó Ví dụ mình có 1 tên miền `setkeo.fun` ở inet thì mặt định DNS của inet như sau - ![image](https://api.phamvantu.com/static/3206ab266b656bda0bfd2a906.webp) Mình muốn kết nối IP VPS của mình vào tên miền `setkeo.fun` thì thông thường sẽ chỉnh sửa bảng ghi, chứ không đụng vào DNS cứ để mặc định đó luôn nha Một tên miền có thể tạo vô số subdomain(sub.example.com, sub2.example.com, sub3.example.com...), nên 1 tên miền có thể dùng có nhiều dự án khác nhau Khi mình change A record thì nên chờ 1 phút rồi mới truy cập lại, không thì có thể bị dính cache vài ngày Có thể dùng `https://dnschecker.org/`, `https://www.whois.com/whois` để kiểm tra máy chủ dns, bản ghi dns, người đăng ký tên miền... Bài tiếp theo mình sẽ SSH vào VPS nha

Routing trong nextjs

Routing trong nextjs
Bài tiếp theo của nextjs thì mình sẽ nói về routing trong nextjs nhé. Mình sẽ nói ngắn gọn nhất có thể để ae đọc hình dung dứt liền luôn nha ### Basic Thư mục **sign-in** có file **page.tsx** thì nextjs sẽ tạo ra đường dẫn webapp là **/sign-in** Trong thư mục phải có file page.tsx là bắt buộc nhen, file chỉ mục đường dẫn của nó luôn á. ### Nested routes Ví dụ mình muốn url **/course/lession** trong đó course sẽ là dynamic, mong muốn get value tên khoá học về để dùng query data. Thì mình sẽ tạo folder như sau **[ course]/lesson/page.tsx** thì nó sẽ có url kiểu kiểu như **react-course/lesson?slug=bai-1** đương nhiên `react-course` là động nha. Case này gọi là `dynamic segment`. Segment ae hiểu như là thư mục cho dễ hiểu hen. Tóm cái quần lại là mục đích để lấy params ra để xử lý gọi api hay gì đó…À đừng để 2 thư mục [dynamic] cùng cấp nha ae, vì nextjs không hiểu mình vô thằng nào á nè Còn nếu ae muốn url cứng hết thì đơn giản chỉ cần tạo **folder course** trong folder course có **folder lession** thì url sẽ luôn luôn là course/lession nè. Nếu không đúng url course/lession thì nó bắn lẹ page 404 liền. Cái này thì đơn giản hơn nhiều hen ### Group Group thì nó không tạo ra routing nha ae. Mục đích là để gom nhóm các routing liên quan vào chung ví dụ mình sẽ tạo thư mục **(dashboard)** thì sẽ không tạo ra route /dashboard đâu nha nếu vào thì ra 404 liền đoá ### Catch-all Segments Ví dụ mình có folder như sau **shop/[…shop]** thì nó sẽ chấp nhận các route như /sign-in/a, /sign-in/b nếu vào /sign-in thì sẽ báo not-found liền ### Catch-all Segments Ví dụ mình có folder như sau **shop/[…shop]** thì nó sẽ chấp nhận các route như /sign-in/a, /sign-in/b và bao gồm luôn route /sign-in luôn nha. Khác mỗi cái trên vậy thui đó ### Params Thông thường là dynamic routes. Như ví dụ ở trên có thư mục **[** **course]/lesson** có url là **react-course/lesson** thì params là 1 object có key là course value là “react-course”. Dễ chưa =)) ### SearchParams Thường là những query ở trên URL ví dụ **lesson?slug=html-css.** Thì slug chính là searchParams. Log ra thì nó cũng là 1 object có key là slug value là ‘html-css” Sương sương vậy thui đó, dễ ăn, dễ trúng thưởng 😜. Hẹn ae bài tiếp theo nhennn

Sử dụng font trong nextjs

Sử dụng font trong nextjs
Say hi những người ae, TuPV comeback đây kaka lâu ngày quá rồi để cái blog mốc mêuuuu luôn á kaka. Thôi thì NextJs ra vừa ra bản [NextJs15 RC](https://nextjs.org/blog/next-15-rc) cách đây mấy ngày thì thôi đu theo luôn cho nó trending tí nhen. Bài này sẽ là khởi đầu cho những bài về NextJs về sau nha, viết vội chứ chuẩn bị cưới vợ rồi dí lắm 😆. Bài viết này mình sẽ list những cách dùng font như từ google fonts, font weight, variables, multiple fonts, local fonts, tailwind fonts…gét goooooo 😜 Mình sẽ để font ở trong layout.tsx nha. Mặc định cài nextJs đã có next/font và tối ưu luôn cho mình sẵn rồi. Nếu mình dùng link cdn để nhúng font vào thì cũng được okie, nhưng load lần tiên sẽ bị kiểu như nháy 1 phát từ font mặc định sang font mình nhúng cdn, nó chưa apply vô kịp á gọi là [Layout Shift](https://web.dev/articles/cls) cho nó bài bản 😁. Nhưng mà nếu dùng font google có sẵn những font trong này [Font Google](https://fonts.google.com/variablefonts) thì sẽ tự động cache lại bất kỳ font nào ở đây. ``` import { Manrope, Roboto } from "next/font/google" // Khai báo const manrope = Manrope({ subsets: ["latin"] }) const roboto = Roboto({ subsets: ["latin"], weight: ["400", "500"]}) // Sử dụng {children} Pham Van Tu ``` Tuỳ font mà nó sẽ yêu cầu weight hay không nhưng thường nên note những font weight mình dùng trong hệ thống và 1 mảng nha. `Vì nếu không truyền là nó auto lấy hết font weight của chữ đó có luôn á :D`, thừa quá không cần nè. Dự án sẽ có nhiều font thì mình nên đặt tên biến cho từng font ``` // Khai báo variable export const manrope = Manrope({ subsets: ["latin"], variable: "--font-manrope", }) export const roboto = Roboto({ subsets: ["latin"], variable: "--font-roboto", weight: ["400", "500"], }) // Khai báo variable sử dụng {children} // Defined common body { font-family: var(--font-manrope) } p { font-family: var(--font-roboto) } ``` **Vậy sử dụng biến trong Tailwind Css như thế nào và ví dụ như font không có trên google font thì sao nào 👇** Tại file tailwind.config khai báo giúp mình như sau ``` theme: { extend: { fontFamily: { primary: ["var(--font-manrope)"], secondary: ["var(--font-roboto)"], }, }, } ``` Khi sử dụng thì đơn giản là `

` là có font manrope rồi nè Vậy sử dụng local font dưới máy thì ae bỏ font trong app rồi ae dùng như dưới nha, dùng thì tương như ở trên mình có thể để class trong thẻ body sét fontName.classname là okela rồi ``` import localFont from "next/font/local"; // Nếu mà font có 1 style thôi thì ae có thể để string thôi cũng được cho ngắn gọn const dm_sans = localFont({ src: "" || [ { path: "", weight: "", style: "italic", }, ], display: "swap", }); ``` **Note** : Ae nên sẽ tạo ra 1 file fonts.ts chẳng hạn rồi defined font các kiểu gì đó ra rồi import dùng ở layout cho okie hơn hi. Cái này nextjs khuyến cáo nên zị á 😇 cho nó smooth performer hơn Đến đây là hết gòi, hóng bài sau cùng TuPV nhen, buy mọi ngườiiiiiiii 🤭

Responsive hình ảnh, video theo tỉ lệ

01/02/2024
Responsive hình ảnh, video theo tỉ lệ
Hello mấy ae 2024, lâu lâu lại chọt 1 bài lên gọi là có tính duy trì viết bài chút 😆. Bài viết này mình sẽ làm giới thiệu responsive hình ảnh, video theo tỉ lệ tuỳ thích nhé, gét goooo Khi chúng ta làm theo thiết kế có sẵn khung nào đó thì khoẻ rồi hen, có nhiêu xét nhiêu thui không thành vấn đề nhưng đôi khi người ta muốn hiển thị video, hình ảnh theo tỉ lệ 16: 9 hoặc 4:3 hoặc tỉ lệ nào đó…thì các bạn xem ví dụ ở dưới nha

Viết script tự động hoá Postman

09/24/2023
Viết script tự động hoá Postman
Sau khi ae biết Postman là gì và dùng cơ bản được qua bài viết [Sử dụng Postman cho test API](https://phamvantu.com/su-dung-postman-cho-test-api) thì bài viết này mình thử viết script cho nó xem sao nhé. Gét gooooo 🤪 Bài biết này mình sẽ viết script để nó tự động hoá lưu access_token và refresh_token vào environment của Postman nhé. Tương tự như bài trước thì mình sẽ set access_token cho foder cha cho nó nhé nhưng token thì mình sẽ lấy từ trong environment ra nha Viết script tự động hoá Postman Nếu như cách thủ công thì sau khi login xong trả về access_token và refresh_token rồi mình copy set nó vào biến environment để các api các cần token để dùng. Trường hợp access_token hết hạn mau quá thì mình phải gọi request refresh_token để nhận được access_token mới rồi copy sang nữa thì hơi… 😳. Hên là Postman hỗ trợ mình viết script để nó tự động hoá cho mình luôn ròiiii Viết script tự động hoá Postman Ae sẽ thấy 2 loại Script là Pre-request Script và Test thì tương ứng đó là script chạy trước khi gửi và script chạy sau khi gửi. Cái này viết theo ngôn ngữ Javascript nhưng viết theo format Postman. Khi mình chạy request login xong thì nó kiểm tra thử status có bằng 200 hông, nếu bằng thì đoạn test mình okie chạy thành công. Mình sẽ lấy response từ Postman ra bằng cách `pm.response.json()` và sẽ set vào các giá trị mong muốn environment thuii Tương tự các request khác thì ae muốn set vào environment thì làm tương tự như trên còn không thì chỉ cần check status = 200 là thành công gòiii Viết script tự động hoá Postman Trường hợp access_token hết hạn thì mình gọi request refresh-access-token để cập nhật lại access_token mới trong environment và những api khác cần token để gửi lên headers vẫn mướt mườn mượt luôn 😝 Viết script tự động hoá Postman Hết ròi!!!. Hy vọng bài viết này giúp ae khỏi copy gán gán như mình lúc trước nữa ahihi 😁

Sử dụng Postman cho test API

09/24/2023
Sử dụng Postman cho test API
Chắc ae cũng khá quen với công cụ Postman dùng để test api rồi. Nhưng mình cũng cũng nói sơ lại cho ae newbie có đọc bài này thì cũng hình dung nó là gì nha. Thường ae backend code api thì họ test ở trên này luôn cho tiện thay vì gọi javascript hay axios bla bla để test xem okie hay chưa. Hoặc như ae nhận 1 list api từ BE và ae muốn check lại api trả về đúng định dạng ae muốn hay chưa thì dùng postman test luôn. Ae có thể download phiên bản phù hợp tại link chính thức của nó [tại đây](https://www.postman.com/) nhé. Bên sidebar có `Collection` nằm đầu tiên. Nó như 1 folder vậy á, thường mình sẽ chia mỗi dự án là mỗi Collection riêng. Vd mình có 2 api get list user và api create user như bên dưới Sử dụng Postman cho test API Sử dụng Postman cho test API Ở đây mình đang bị lặp `https://reqres.in/api` nên mình sẽ tạo 1 biến để dùng lại. Thì biến ở Postman gọi là environment. Ae có thể chọn bên sidebar dưới mục Collection rồi tạo mới 1 environment để dùng nha. Sử dụng Postman cho test API Và khi tạo xong qua lại 2 request lúc nãy mình cập nhật lại `https://reqres.in/api thành {{host}}` rồi test lại nhé, nhớ là mình phải set environment bên góc phải trên cho nó rồi mới chạy được nha. Sử dụng Postman cho test API Trường hợp request cần truyền token lên thì mình set bên tab Authorization và chọn type tương ứng với bên api setup nha, thường sẽ là Bearer Token như hình bên dưới.Sử dụng Postman cho test API Sau khi gọi request này thì bên Headers sẽ gửi lên key là Authorization với value là token mình set ứng lúc nãy Sử dụng Postman cho test API Vậy lỡ có nhiều request cần token gửi lên thì sao. Vậy thì mình set token ở folder cha của nó rồi các request con kế thừa là được nha. Như hình dưới mình Folder cha có Type là Bear Token và set token cho nó luôn Sử dụng Postman cho test API Ở request con mình chỉ cần chọn Authorization là `Inherit auth from parent` là okie rồi Sử dụng Postman cho test API Hy vọng bài viết này sẽ giúp ae hiểu và sử dụng được công cụ này hiệu quà nhé. Bài viết sau mình sẽ giới thiệu viết script tự động hoá Postman nha. Ví dự như khi login xong thì mình có được accessToken và refreshToken và nó sẽ tự động lưu vào các biến môi trường của mình rồi mình đem đi gán cho các request cần truyền token lên header chẳng hạn nha hehe. Baiiiiii 😝

Tối ưu kích thước file build cho production

Tối ưu kích thước file build cho production
Hi ae, bài viết này xem tìm xem thử cái nào chiếm dung lượng nhiều trong project của mình và optimized nó nhé. Nếu mình chỉ build thông thường thì khó mà phát hiện ra cái gì chiếm nhiều dung lượng, mình dùng vite nên ở đây mình giới thiệu công cụ [Rollup Plugin Visualizer](http://npmjs.com/package/rollup-plugin-visualizer), thằng Vite được build dựa trên thằng Rollup nên dùng nó để phân tích file build nhé, nếu anh ae dùng webpack thì có package [webpack-bundle-analyzer](https://www.npmjs.com/package/webpack-bundle-analyzer) tương tự nhé. Khi mình chạy build nó sẽ cho xuất ra cho mình 1 file chỉ số stats.html cùng cấp với package.json của mình luôn. Ae có thể mở lên và theo dõi chỉ số nhé và check thử cái nào cần tối ưu được thì mình tối ưu cho nhẹ nha. Dùng cái nào thì import cái đó thôi thay vì import cả thư viện vào -> Tree-shaking Tối ưu kích thước file build cho production Sau khi tối ưu thì ae có thể tự check kích thước file build của mình nhé đương nhiên là nhỏ hơn rồi 😝, và load lại file stats tận hưởng thành quả nha 🥰 Tối ưu kích thước file build cho production Hy vọng bài viết này sẽ giúp ae phân tích file build và có thể tối ưu nó lại nhé với giao diện theo dõi trực quan okie luôn

Lazyload component với react lazy

Lazyload component với react lazy
Nghĩ lễ 2/9 sâu quá ghé blog chém gió xíu xíu chớ ae quên mình mất 😆 Đôi lúc ae code nhiều nhưng quên mất lúc build để deploy lên production thì không biết ra sao hè. Ae mở package.json và xem thử lệnh build như thế nào nhé Lazyload component với react lazy dev: để ae dev quen quá rồi :v build: chạy vite build preview: chạy file build của chúng ta. Ví dụ sau khi build ra được file js, html, css thì preview nó sẽ chạy cái những file này lên cho chúng ta Sau khi build nó sẽ nằm trong thư mục dist của chúng ta, gzip trên hình là nó 1 file nén lại từ file build ra. Và khi deploy lên server là nó sẽ deploy thằng dist này lên chứ mình không deploy cái src nha. Mục src để mình code thoiii. Để chạy bản production lên thì chạy yarn preview. Mọi người sẽ thấy toàn bộ app mình sẽ dồn toàn bộ javascript thành 1 file nặng gần 200 kiB sau khi đã được nén. Sau khi chạy yarn preview thì ae chọn tab network và chọn tab js, nó sẽ chạy mỗi cái file js sau khi build ra Trường hợp mình có trăm page, trăm component khi load lần đầu bắt người dùng tải toàn bộ về thì hơi phí mất time hơn 🤪. Điểm thuận lợi thì cũng có là nó tải toàn về nên chuyển route nó nhanh vãi vì nó tải toàn bộ về lần đầu rồi. Ở đây mình sẽ dùng kỹ thuật lazy load dùng đến đâu tải đến đó nhưng chuyển route thì hơi chậm 1 tí xíu nhưng chắc mình cũng không nhận ra lắm :)), do nó cần down js từ server về nữa. Dùng lazy thì cần 1 component <Suspense> để bao bọc nó nữa nhé, nó 1 fallbackUI, ví khi vào trang chưa load xong thì show tạm ra gì đấy chẳng hạn, không truyền cũng không sao, ra màn hình trắng thoi 😇 Lazyload component với react lazy Ví dụ khi mình dùng lazy load cho page Login thì khi vào trang login nó mới tải js trang này về chứ ban đầu nó không tải toàn bộ nữa. Và khi mình build lại thì không còn 1 file js nữa mà sẽ ra nhiều file js khác kích thước cũng giảm hơn so với ban đầu mình không dùng :v Khi mình dùng lazy load thì mình cũng cải thiện được cái Lighthouse nữa nha, công cụ của chrome để test performance. Không phải lúc nào cũng ra 1 kết quả nên mình tính tương đối sai số mỗi lúc chạy nhé ae, 1 phần do mạng mẽo đồ nữa nghen. Ở đây có những chỉ số của trang web mình ae có thể dựa vào đây để test và cải thiện những chỉ số theo hướng dẫn của nó nhé Lazyload component với react lazy Hy vọng bài viết này giúp ae cải thiện được chút performance project của mình nhé. Thank you for watchinggggg 😜

Tạo Modal với React Portal

Tạo Modal với React Portal
Say hi những ngừi ae của toiiiii. Bài viết này là khai bút con Mạc Bục đã mua cách đây 2 tuần của toiiii kaka. Máy chạy nhanh quá làm mình cũng quên luôn viết bài trên blog của mình hehe. À blog được tài trợ bởi server của ngừi anh thân thương [Thành Trung](https://thanhtrungit.net/). Ai mua VPS hay hosting thì có thể ghé [Dnclound.vn](https://dncloud.vn/) bao rẻ-khoẻ luôn nha ahihi. Thôi văn vở quá rồi kéo xuống thoiiiii 😂 Api này rất là hữu ích trong việc ae tạo modal, popup đó là `Create Portal`. Giúp mình tạo ra những component nằm trong bất kỳ vị trí nào trên page của chúng ta. Vậy tại vì sao nên sử dụng nó hè 🤙 React app của chúng ta được render trong element có id root chẳng hạn, thì ở đây sẽ render cả cái app chúng ra luôn. Trong 1 số trường hợp chúng ta muốn sử dụng Modal của mình nằm ngoài component nào đấy hoặc nằm ngoài id root luôn thì chúng ta sử dụng react portal nhé 🤙 Giả sử mình có 1 sidebar bên trái, content bên phải và trong content có 1 modal confirm nhé Trường hợp xảy ra là z-index của sidebar: 20, z-index của content:10 Bây giờ cho dù z-index của modal confirm của mình tăng lên bao nhiêu đi nữa thì cũng không có tác dụng đâu vì thằng cha của nó là content nhỏ hơn moà. Trong những trường hợp này mình có thể đưa thằng modal ra ngoài cùng cấp với sidebar hoặc tốt hơn ra ngoài root luôn Cách dụng thì ae sẽ import createPortal vào nhé, `có 2 tham số đầu tiên là jxs, tham số thứ 2 là element` chúng ta muốn chèn vào. Ví dụ muốn chèn vào body thì đơn giản chỉ cần document.body là okie rồi nè. Trong trường hợp ae muốn chèn vào element nào thì get element nó ra và dùng thoi ``` const root = document.getElementById('root') as HTMLElement export default function Confirm({ visible, ok, cancel }: ConfirmProps) { const handleOk = () => { ok() } const handleCancel = () => { cancel() } return createPortal(

Are you sure?

, root ) } ``` Nợ demo không bảo giờ trả nha ae 🤪. Có thì thắc mắc thì cứ ping mình giải thích nhé hihi. Chúc ae new day zui zẻ nhé 🤪

useCallback trong react

useCallback trong react
Hi 500 ae. Bài này mình giới thiệu về 1 hook là `useCallback` cũng như sử dụng nó ra sao nhé. Lướt thuiiiii Chúng ta thường dùng `useCallback` khi mình không muốn function của chúng ta được khởi tạo lại mỗi lần component chúng ta re-render ``` const memoizedCallback = useCallback(() => { doSomething(a, b) }, [a, b]) ``` Cách dùng thì tham số đầu tiên là 1 callback thực hiện việc gì đấy tham số thứ 2 là dependence. Mỗi lần dependence thay đổi thì function được chạy lại. Đơn giản vậy thuii Mình có để demo phía dưới thì mình có 1 function handleClickTitle nó nhận vào value. Function là 1 object nên khi component re-render thì handleClickTitle sẽ tạo tham chiếu mới nên sẽ làm component re-render lại thôi. Trường hợp này mình dùng useCallback như demo dưới bạn có thể vọc để chạy nhé 😅

React.memo và useMemo trong React

React.memo và useMemo trong React
Say hi 5 chăm ae, bài này sẽ là bài đầu tiên trong chuỗi React Hook nâng chình xíu nhé. Bỏ qua các hook basic như useState, useEffect, useContext…Hơi nhiều lời rồi, lướt thoiiiii Chắc ae đã biết thì component sẽ re-render state hoặc props được cập nhật, compoent cha re-render khiến component con cũng re-render theo. Vậy để không muốn component con bị re-render mỗi khi component cha re-render thì chúng ta dùng `React.memo` nhé ### **React.memo()** React.memo() là 1 HOC (Higher-order component), chứ không phải hook React.memo() dùng cho functional component Chỉ render lại component nếu props thay đổi, còn không thì render lại kết quả của props cũ => có sử dụng kỹ thuật Memozation Sử dụng shallow comparison ``` import "./styles.css"; import Title from "./components/Title"; import { useState } from "react"; export default function App() { const [count, setCount] = useState(0); const handleClick = () => { setCount((prev) => prev + 1); }; return ( Click to increase count Count: {count} ); } ``` Ae thấy component `<Title/>` chắc chắn sẽ bị re-render khi mình click button, component cha re-render kéo theo nó cũng bị re-render theo. Nếu như component `<Title/>` tính toán nhiều nặng thì về performent không tốt còn ít thì hông đáng là bao 😉. Thay vì mình export như bình thường mình sẽ export như bên dưới `React.memo(NameComponent)`. ``` import React from "react"; export default function Title() { console.log("title"); return This is Title; } --------------Convert to ----------> import React from "react"; function Title() { console.log("title"); return This is Title; } export default React.memo(Title); ``` `React.memo` chỉ check props thôi nha. Nếu như state trong component Title thay đổi thì nó vẫn re-render bình thường nha. Ngoài tham số là tên component thì sẽ nhận 1 function nữa nhé. Function này có 2 tham số, khi function đó return true thì props trước và sau giống nhau -> không làm component re-render. Ngược lại khác nhau thì render lại thuiiii. À ví dụ ae truyền 1props qua component con dạng không nguyên thủy như object đồ á thì nó vẫn khiến component con re-render bình thường nha. Vì mỗi cần component cha re-render thì nó sẽ thay đổi cái tham chiếu của object props mình truyền sang nên component con tưởng props thay đổi nó re-render lại. ``` interface TitleProps { address: { street: string; }; } function Title(props: TitleProps) { console.log(props.address); return This is Title; } function equal(prevProp: TitleProps, nextProps: TitleProps) { return prevProp.address.street === nextProps.address.street; } export default React.memo(Title, equal); ``` Các bạn để ý thì mỗi lần App chúng re-render thì nó sẽ tạo 1 instance address mới làm cho component React memo không còn hoạt động như mong muốn nữa, làm mình phải sử dụng thêm equal function hơi rườm rà. Thì để hạn chế address được khởi tại thì mình dùng useMemo. Nào mình dùng những state, props liên quan muốn control thì mình truyền vào dependence như là bên useEffect vậy khi nào nó có sự thay đổi thì sẽ làm cho address tạo 1 instance mới làm cho Title chúng ta re-render lại còn mặc định [] thì sẽ chạy lần đầu tiên hoiiiii Những vấn đề liên quan đến meno thì nó sẽ dùng ram của máy tính, càng dùng nhiều thì càng tốn nhiều ram, bù lại có được performance tốt hơn nên là ae cân nhắc khi dùng nha. Không phải gì cũng meno hết, vậy thì tốn ram nặng, những điện thoại yếu yếu tràn ram đơ cái máy tội lắm luôn :v ``` const address = useMemo(() => { return { street: K29 Nguyễn Như Đãi, Đà Nẵng" } }, []) ``` Hy vọng sẽ giúp các bạn có thể được cải thiện được performance trong dự án nha, tránh được việc re-render các component không cần thiết nhé

Custom hook trong react

Custom hook trong react
Hello 5 chăm ae, lại là Tú Pê Vê đây 😁. Bài viết này mình sẽ giới thiệu với các bạn về custom là gì và dùng như thế nào nhé. Custom hook là những hook riêng do chúng ta tạo, để chúng ta chia sẻ state, logic giữa các component với nhau. Mình để ví dụ ở đây anh em có thể vào xem thử nhé

Convert JSON loằn tà loằn ngoằn thành Typescript interface

Convert JSON loằn tà loằn ngoằn thành Typescript interface
Nhớ lúc trước ngồi xóa mớ value của key rồi chuyển thành type cho đúng value vừa xóa, vài dòng thì…i’m fine chứ 50 dòng thì uể thiệt 🤦‍♂️ Làm sao để biến cái đống JSON kia thành Typescript interface nhỉ, chẳng lẽ ngồi thay từng cái 🤔 Mình chia sẻ cho các bạn 1 cách nhanh hơn đó chính là dùng tool ở trang này: https://transform.tools/json-to-typescript các bạn chỉ cần dán cấu trúc JSON vào và việc còn lại để em nó lo. Sau đó các bạn sửa lại tên cho phù hợp trong dự án là được 👌 Hy vọng bài viết ngắn ngắn này sẽ support các bạn dài dài sau này nhé 😜

Phân biệt Web Storage và Cookie

06/07/2023
Phân biệt Web Storage và Cookie
Trong bài này cùng mình phân biệt web storage và cookie nhé. Gét gô **Web Storage & Cookie** Web storage có 2 loại đó là Local Storage và Session Storage Web storage lưu trữ được nhiều dữ liệu và dễ dùng hơn Cookie. Nhưng không có nghĩa họ bỏ không dùng Cookie nhé. Mỗi thằng có những ưu nhược khác nhau tùy case mình linh động nghen Cả 3 đều dùng chung mục đích lưu thông tin trên trình duyệt để tiện xử lý sau này Khác biệt lớn nhất giữa Local Storage, Session Storage và Cookie là thời gian lưu lại trên trình duyệt **Local Storage** Là Web Storage Lưu lại vĩnh viễn trên trình duyệt. Khi mình chủ động xóa thì nó mới mất thui Dung lượng lưu trữ khoản 5Mb – 10Mb tùy trình duyệt  Các trang khác không thể truy cập đến Local Storage nếu như khác domain ``` // Thêm item localStorage.setItem('name', 'John Doe') // Đọc item localStorage.getItem('name') // 'John Doe' // Xóa item localStorage.removeItem('name') // Xóa hết local storage localStorage.clear() ``` **Session Storage** Là Web Storage giống như Local Storage Lưu lại 1 phiên dùng web thôi, đóng tab là mất hết data Dung lượng lưu trữ khoản 5Mb – 10Mb tùy trình duyệt Các trang khác không thể truy cập đến Session Storage nếu như khác domain ``` // Thêm item sessionStorage.setItem('name', 'John Doe') // Đọc item sessionStorage.getItem('name') // 'John Doe' // Xóa item sessionStorage.removeItem('name') // Xóa hết Session Storage sessionStorage.clear() ``` **Cookie** Có trước 2 thằng Local Storage và Session Storage Không phải là web storage Thời gian lưu trữ data có giới hạn, khi hết hạn thì cookie tự động bị xóa.Hạn này mình có thể set cho nó Dung lượng lưu trữ chỉ khoảng 4KB => Nên lưu những data đơn giản, càng ít càng tốt, lưu quá nhiều thì mỗi lần mình truyền đi truyền lại thì nó tăng băng thông không tốt nghen Cookie sẽ tự động truyền từ server xuống client và truyền từ client lên server thông qua mỗi header request Server có thể cấu hình để các sub domain ví dụ `sub1.domain.com` có thể set cookie cho `sub2.domain.com`. Lưu ý là phải cùng domain cha là domain.com nghen Cookie thường được tạo trên server bằng PHP, Python, Java hoặc Node.Js để truyền xuống client thông qua header của mỗi request ``` setcookie( string $name, string $value = "", int $expires_or_options = 0, string $path = "", string $domain = "", bool $secure = false, bool $httponly = false ): bool ``` Cookie cũng có thể được tạo thông qua Javascript bằng cách dùng `document.cookie`. ``` document.cookie = 'yummy_cookie=choco' document.cookie = 'tasty_cookie=strawberry' console.log(document.cookie) // console.log(document.cookie) "yummy_cookie=choco; tasty_cookie=strawberry" ``` Mình lấy ra dùng thì cũng hơi bất tiện. Mình log document.cookie thì nó ra hết nên mình phải tách từng phần tử ra. Nên thường người ta sẽ dùng thư viện [js-cookie](https://www.npmjs.com/package/js-cookie) để thao tác trên Client dễ dàng hơn. Những Cookie mà tạo bằng javascript thì không có cờ `HttpOnly` nha * **Server Session** Đây là phiên trên server, không phải ở client Server sẽ tự động quyết định khi nào kết thúc phiên để đưa ra quyết định với client Dung lượng lưu trữ không giới hạn, tùy dung lượng server quyết định Phân biệt Web Storage và Cookie Giả sử người dùng sử dụng browser để login thông qua method post. Khi login okie thì server sẽ tạo ra 1 session id và nó sẽ return sesstion id vào trong cookie cùng với đó nó lưu sesstion id và db. Sesstion id khi giải mã thì có những thông tin username, createdate…Khi thằng browser thực hiện request gì đó và có đính kèm cái cookie có giá trị là sesstion id thì server sẽ check lại db có sesstion id chưa và còn hạn thì nó sẽ xác thực okie response result thui nè Hy vọng bài viết này giúp các hiểu và phân biệt được web storage và cookie nha 🤞

Các loại function hay dùng trong React

Các loại function hay dùng trong React
Trong bài viết này mình sẽ ôn lại concept function hay dùng trong React nhé I/ Đầu tiên hay dùng nhất là Callback function. Nó chỉ là function truyền vào function khác như là 1 tham số thôi nên họ gọi là Callback function ``` const nums = [1,2,3,4,5] const callBack = (item, index) => { console.log(`STT: ${index} là ${item}`) } nums.forEach(callBack) ``` Như mình demo ở trên thì biến callBack đóng vai trò như là 1 tham số trong hàm forEach và nó là 1 function nên nó được gọi là Callback function II/ Thứ 2 sẽ ngày đầu tuần 😁. Zui thôi chớ thứ là là Currying function . Nó là 1 function return về 1 function ``` // Ví dụ 1 function findNumber(num) { return function () { return num } } console.log(findNumber(10)()) // Ví dụ 2 const findNumber = (num) => { return (func) => { const result = [] for (let i = 0; i number % 2 === 0) ``` `findNumber` gọi là currying function vì nó return một function mới. Vậy nên chúng ta phải `()` 2 lần thì nó mới chạy hết code trong nó được. Chúng ta gọi findNumber(10) thì nó mới chỉ return về 1 function chưa chạy code bên trong function đó. Mình phải chạy nó thêm 1 lần nữa thì nó mới chạy function trong. Mà function bên trong là function điều kiện nên mình sẽ dùng (number => number % 2 === 0) sẽ trả về những kết là số chẵn. Hoặc mình có thể gọi bằng cách sau ``` // TH1 const newFunc = findNumber(10) const value2 = newFunc((value) => value ) // TH2 const newFunc = findNumber(10) const value2 = newFunc((value) => value % 2 === 0) console.log(value2) ``` newFunc sẽ return về 1 function rồi thì mình có thể sử dụng cái newFunc để xử lý tiếp hehe Chúc bạn new day zui zẻ keke 😘

Async Await trong Javascript

04/21/2023
Async Await trong Javascript
Nếu như phiên bản có Promise giải quyết được được phần nào callback hell, nhưng vẫn chưa max ping thì đến ES7 chúng ta có thể xử lý bất động bộ 1 cách dễ nhìn và dễ đọc hơn với async/await **Á à:** Async/Await không thay thế promise nha mà nó kết hợp với promise để cho ra cú pháp dễ nhìn hơn. Vì thế để học async/await bạn phải nắm được promise trước đã nghenn **Async function:** Luôn luôn return về 1 promise nha ``` async function handle() { return 1; } handle().then((value) => { console.log(value); }); ``` **Await:** Chỉ hoạt động bên trong async function, không thể await bên trong một function thường. Không phải cái gì cũng await, await chỉ nên dùng cho promise thôi nghenn ``` const getApi = () => { return new Promise((resolve, reject) => { setTimeout(() => { resolve("Hello"); }, 3000); }); }; const handle = async () => { const value = await getApi(); return value; }; // Bình thường như này handle(); là okie rồi. Muốn lấy kết quả từ function async về thì .then() nữa nghenn handle().then((value) => { console.log(value); }); ``` **Xử lý lỗi với async/await** ``` const getApi = () => { return new Promise((resolve, reject) => { setTimeout(() => { reject("Loi roi"); }, 3000); }); }; const getUser = async () => { try { const value = await getApi(); console.log(value); } catch (error) { console.log(error); return null; } }; getUser().then((value) => { console.log(value); }); ``` **Gọi tuần tự với async/await** ``` const getBooks = () => { return new Promise((resolve, reject) => { setTimeout(() => { resolve(["book1", "book2", "book3"]); }, 3000); }); }; const getUser = () => { return new Promise((resolve, reject) => { setTimeout(() => { resolve(["user1", "user2", "user3"]); }, 3000); }); }; const getAPI = async () => { const books = await getBooks(); const users = await getUser(); return { books, users }; }; getAPI().then((value) => { console.log(value); }); ``` **Tối ưu performance với `Promise.all()** Ở đoạn code trên thay vì gọi lấy getBooks() xong rồi đến getUser() thì ra có thể cho function này chạy "cùng lúc" ``` const getAPI = async () => { const [books, users] = await Promise.all([getBooks(), getUser()]); return { books, users }; }; getAPI().then((value) => { console.log(value); }); ```

Mutation trong React Query

02/11/2023
Mutation trong React Query
Lại là TúPêVê cùng sê ri React Query đây. Bài này giúp ae hiểu Mutation trong React Query là gì, dùng nó ra sao nhé. Lướt xuống thôi 😆 mutate là 1 async function nha ae, nó xử lý bất động bộ nhưng nó không return promise đâu nghen

Tìm hiểu cơ chế caching của React Query như thế nào nghen

Tìm hiểu cơ chế caching của React Query như thế nào nghen
Lại là TúPêVê đây 😜. Bài này mình cùng tìm hiểu một số khái niệm quan trọng cũng như cơ thế caching của React Query như thế nào nhé 💋 Một số khái niệm ae cần lưu ý nhé **staleTime** (default 0 ms): Thời gian data được cho là đã cũ. Khi get data xong thì sau một thời gian mình quy định thì data nó sẽ tự cũ. Mặc định 0 là khi get xong là nó cũ ròi á Ae có cài react dev tool thì chỗ `stale` là nó hiển thị data đã cũ (stale) và thêm cái là active nữa thôi (để cho mình biết đang gọi query key nào á kiểu vậy `subcribe`) mấy cái dưới cũng là cũ nhưng inactive á nghen **cacheTime** (default 5*60*1000 ms = 5 phút) : Thời gian data sẽ bị xóa ra khỏi bộ nhớ đệm. Data có thể cũ (stale) nhưng nó chưa bị xóa ra khỏi bộ nhớ đệm vì mình set staleTime < cacheTime. Thường thì người ta sẽ set **staleTime < cacheTime** . Ví dụ lúc phân trang mình ở trang 1 mình call api có page = 1, trang 2 mình call api có page = 2 thì khi sang trang 1 và 2 lại thì nó thấy data 2 page này còn lưu ở bộ nhớ đệm nên sẽ gọi data lưu ở cached ra và fetch ngầm ở dưới nếu có data mới khác data cache thì nó tự update lại data cached cho mình luôn 😍 **inactive:** Là khi data đó không còn component nào subcribe cả ``` const result = useQuery({ queryKey: ['todos'], queryFn: fetchTodoList }) // result là 1 object chứa 1 vài state rất quan trọng như status, fetchStatus... ``` **Những state về khoảnh khắc của data** isLoading hoặc status === ‘loading’: Query chưa có data isError hoặc status === ‘error’: Query xảy ra lỗi isSuccess hoặc status === ‘success’: Query thành công và data đã có sẵn **Những state về data** error: Nếu isError === true hoặc hoặc status === ‘error’ thì error sẽ xuất hiện data: Nếu isSuccess === true hoặc status === ‘success’ thì data sẽ xuất hiện **Đặc biệt là fetchStatus** isFetching hoặc fetchStatus === ‘fetching’: Đang fetching API isPaused hoặc fetchStatus === ‘paused’: Query muốn fetch API nhưng bị tạm dừng vì 1 số lý do nào đó fetchStatus === ‘idle’: Query không làm gì cả, chạy xong rồi đang rảnh =)) **Nói chung đọc tới đây ae cũng rối cmnr kaka. Tóm lại như này cho khỏe** status cho thông tin data có hay không fetchStatus cho thông tin về queryFn có đang chạy hay không Ví dụ thực tế ri cho ae dễ hình dung nghen, không hình dung được thì ib hỏi mình 😁 kaka Click trang 1 call api thì loading = true do chưa có call xong rồi thì loading = false, trang 2,3..n cũng vậy Khi quay về trang 1 hoặc những trang trước đó lại thì loading sẽ là false luôn vì nó đã có data trước đó rồi, `nhưng nó vẫn call api ngầm ở dưới á nếu có thay đổi thì nó sẽ cập nhật lại data mới thoi` => (isFetching = true lúc call api, khi call xong thì tất nhiên isFetching về false rồi) **Cơ chế caching data** Một data mà đã stale (cũ) thì khi mà gọi lại query của data đó, nó sẽ fetch lại api. Nếu không stale thì không fetch lại api. Vì mặc định là staleTime là 0 ms call xong nó cũ rồi. Hoặc setiing staleTime lên 60 * 1000 để 1 phút sau nó mới cũ thì click lại trong 1 phút thì nó không call api Một data mà đã bị xóa khỏi bộ nhớ (tức là quá thời gian cacheTime) thì khi gọi lại query của data đó, nó sẽ fetch lại api (Dĩ nhiên roài). Nếu còn chưa bị xóa khỏi bộ nhớ nhưng đã stale thì nó sẽ trả về data cached và detch api ngầm, sau khi fetch xong nó sẽ update lại data cached và trả về data mới cho bạn **Ví dụ siêu dễ hiểu cho ae về vòng đời caching của React Query** ``` Mặc định mình dùng cacheTime là 5 phút và staleTime là 0 nha function A() { const result = useQuery({ queryKey: ['todos'], queryFn: fetchTodos }) } function B() { const result = useQuery({ queryKey: ['todos'], queryFn: fetchTodos }) } function C() { const result = useQuery({ queryKey: ['todos'], queryFn: fetchTodos }) } ``` `A` component được mount Vì không có query nào với `['todos']` trước đó, nó sẽ fetch data Khi fetch xong, data sẽ được cache dưới key là `['todos']` hook đánh dấu data là `stale` (cũ) vì sau `0`s Bây giờ thì `B` component được mount ở một nơi nào đó Vì cache data `['todos']` đã có trước đó, data từ cache sẽ trả về ngay lập tức cho component `B` Vì cache data `['todos']` được cho là đã `stale` nên nó sẽ fetch api tại component `B` Không quan trọng function `fetchTodos` ở `A` và `B` có giống nhau hay không, việc fetch api tại `B` sẽ cập nhật tất cả các state query liên quan của `B` và `A` vì 2 component cùng key => cùng subcribe đến một data Khi fetch thành công, cache data `['todos']` sẽ được cập nhật, cả 2 comonent `A` và `B` cũng được cập nhật data mới Bây giờ thì `A` và `B` unmount, không còn sử dụng nữa, không còn subcribe đến cache data `['todos']` nữa nên data `['todos']` bị cho là `inactive` Vì `inactive` nên `cacheTime` sẽ bắt đầu đếm ngược 5 phút Trước khi `cacheTime` hết thì ông `C` comopnent được mount. cache data `['todos']` được trả về ngay lập tức cho `C` và `fetchTodos` sẽ chạy ngầm. Khi nó hoàn thành thì sẽ cập nhật lại cache với data mới. Cuối cùng thì `C` unmount Không còn ai subcribe đến cache data `['todos']` trong 5 phút tiếp theo nữa và cache data `['todos']` bị xóa hoàn toàn

Cùng tìm hiểu React Query là gì nghen

Cùng tìm hiểu React Query là gì nghen
Hello mấy ae bài viết là bài đầu tiên trong chuỗi [React Query](https://tanstack.com/query/latest/docs/react/overview) cùng TúPêVê nghen. Gét Gô thuiiii TanStack Query là cái tên gọi mới hay có thể gọi React Query là thư viện giúp quản lý các state bất đồng bộ như data từ api **Nó có ưu điểm gì** Quản lý cache data và cập nhật cực kỳ đơn giản Không dùng global state, reducer để quản lý, không khó hiểu như redux Có khả năng tương thích và mở rộng với mọi use-case gặp trong thực tế **Vậy nó dùng gì để gọi api** Tanstack Query không đảm nhận việc gọi API, việc gọi API sẽ thực hiện thông qua các thư viện bạn dùng như axios, fetch API. Còn Tanstack Query chỉ đảm nhận việc quản lý data và trigger gọi api khi cần thiết thôi Như cách thông thường mình dùng useEffect để call api thì sao hè. Mình vd đoạn code mẫu dưới nhé ``` const [students, setStudents] = useState([]) const [isLoading, setIsLoading] = useState(false) useEffect(() => { setIsLoading(true) getStudents(page, limit) .then((res) => { setStudents(res.data) }) .finally(() => { setIsLoading(false) }) }, []) ``` Với cách này khá dài dòng chúng ta phải set đi set lại state rất là mệt. Còn với react query thì tương đối gọn hơn với code demo mẫu ở dưới ``` const { data, isLoading} = useQuery({ queryKey: ['students', page], queryFn: () => getStudents(page, LIMIT) }) //page đặt trong queryKey kiểu như devdependency trong useEffect vậy khi page thay đổi nó sẽ trigger chạy lại hàm getStudents cho chúng ta data mới ``` Thấy gọn quá hè, có được data, isLoading mà không cần phải cái useEffect dài dòng nữa =)) **Query Key là gì** : Nó là 1 cái key định danh cho cái query của mình và React Query nó sẽ quản lý việc query caching dựa trên Query keys của mình. Nó có thể là 1 mảng hoặc 1 số hoặc cái gì cũng được miễn sao để người khác nhìn vào biết được query của mình có nhiệm vụ gì **Query Functions:** Nó là 1 function return về promise, promise này có thể return về resolve hoặc error

Phòng chống tấn công XSS cho website

Phòng chống tấn công XSS cho website
Hello mí ae bài viết này mình sẽ share kỹ thuật phòng chống XSS nghen. Ví dụ ở những field mà server trả về cho mình về dạng HTML thì ae không thể render như kiểu JSX `product.description` được nó sẽ gặp tình trạng kiểu như bên dưới, đấy là cách mà JSX chống lại tấn công  XSS. Phòng chống tấn công XSS cho website Vậy làm sao để mình render được dạng HTML lên React component của mình. Cách đơn giản nhất là mình dùng `dangerouslySetInnerHTML` mình truyền cho nó 1 object như bên dưới là nó render được dạng HTML rồi hehe Phòng chống tấn công XSS cho website Cách render này lỡ như HTML của mình có chứa javascript thì website của mình cũng hơi nguy hiểm, nó có thể bị tấn công XSS vì thế thằng React mới có đoạn `dangerouslySetInnerHTML` kiểu như thông báo nhắc nhở cho mình những đoạn code trong này hơi nguy hiểm á. Mình demo test thử đoạn code bên dưới nghen Phòng chống tấn công XSS cho website Khi mình click thì nó vẫn chạy được js show alert lên bình thường. Ví dụ đoạn này được user submit lên thì web mình dễ bị tấn công, có thể lấy access token của mình…thì vấn đề này giải quyết bằng cách cài package [`dompurify`](https://www.npmjs.com/package/dompurify) nó sẽ loại bỏ những đoạn code js đi tránh gây nguy hiểm cho trang web của mình. Phòng chống tấn công XSS cho website Và sau khi dùng mình có thể so sánh kết quả như bên dưới, ban đầu mình không dùng thư viện dompurify và sau là sử dụng Phòng chống tấn công XSS cho website Hy vọng bài viết này sẽ giúp ae hạn chế bị tấn công XSS tối thiểu nhé 😂

Trick xử lý loại bỏ được undefined của từng key trong Object

Trick xử lý loại bỏ được undefined của từng key trong Object
Hello ae nay mình share tip giúp ae loại bỏ giá trị undefined của key nhé. Ví dụ mình test demo 1 Object có 2 key optional của mình kiểu như bên dưới, thì khi hover vào chắc chắn sẽ nhận 2 type là string và undefined rồi Trick xử lý loại bỏ được undefined của từng key trong Object Ở đây mình sẽ tạo 1 function giúp loại bỏ giá trị undefined như bên dưới Trick xử lý loại bỏ được undefined của từng key trong Object – Cú pháp `-?` sẽ loại bỏ undefined key optional của mình – `NonNullable` là 1 util của Typescript giúp loại bỏ đi giá trị underfined của 1 type Khi sử dụng thì mình sẽ thấy 2 giá trị undefined của 2 key sẽ biến mất rồi hehe. Hy vọng ae sẽ áp dụng được nhiều case loại bỏ giá trị undefined không mong muốn nhé Trick xử lý loại bỏ được undefined của từng key trong Object

Cùng mình tìm hiểu cấu trúc thư mục theme trong wordpress nhé

01/20/2023
Cùng mình tìm hiểu cấu trúc thư mục theme trong wordpress nhé
Hello anh em lâu ngày quá. Hôm nay là 29 tết rồi, vừa dọn nhà xong tiện thể khai bút sê ri wordpress cho rộn ràng xíu hehe 😂 Mình mặc định là ae đã biết cài đặt wordpress à nếu chưa thì lên [đây](https://wordpress.org/download/) để tải về rồi tạo database rồi vô file config.php connect là được nghen Theme wp thì sẽ nằm trong wp-content/themes. Mặc định là sẽ có 3 thư mục tương ứng với 3 theme của wp tạo sẵn cho mình. Việc của mình là tạo theme của mình trong này hoặc ae nào có sẵn thì có thể vào admin up giao diện lên cũng được nha rồi vô giao diện chọn theme của mình nhé. Để lập trình theme wordpress thì đầu tiên ae phải nắm được cấu trúc thư mục theme trong wordpress là gì nhé Ngoài 2 file tất yếu phải có để chạy được theme wordpress là `style.css` để khai báo thông tin của theme chúng ta như tên theme, tác giả, version php… như bên dưới và file `index.php` đại diện cho trang chủ của mình thì có những file với những mục đích như sau **– File style.css** ``` /* Theme Name: Blog của Phạm Văn Tú Text Domain: phamvantu.com Version: 1.0 Requires at least: 4.7 Requires PHP: 5.2.4 Description: Theme wordpress by Tú Phạm Author: Phạm Văn Tú Author URI: https://v0.phamvantu.com Theme URI: https://v0.phamvantu.com */ ``` screenshot.png: Ảnh đại diện của theme functions.php: Dùng để viết các function dùng chung cho theme, đường nhiên là những file trong theme sẽ dùng được nha index.php: Hiển thị thông tin của trang chuyên mục category.php: Hiển thị thông tin của trang chuyên mục single.php: Hiển thị thông tin của trang chi tiết bài viết page.php: Hiển thị nội dung thông tin của trang tag.php: Hiển thị thông tin của trang chứa thẻ tag 404.php: Hiển thị nội dung của trang không tồn tại search.php: Hiển thị nội dung của trang kết quả tìm kiếm header.php: Chứa header của website dùng chung `get_header()` footer.php: Chứa footer của website dùng chung `get_footer()` sidebar.php: Chứa sidebar của website dùng chung `get_sidebar()` **Đôi lúc mình muốn tách những block riêng để dùng chung tùy nơi mong muốn thì sao** Thường mình sẽ tạo 1 folder template-part thì tạo file trong này rồi có thể gọi ra chỗ mình cần bằng cách `get_template_part('ten-thu-muc/ten-file')` Ví dụ trang mình có blog bên Huynh đệ bên sidebar thì thay vì mình copy sang trang chuyên mục, chi tiết bài viết thì mình có tạo 1 file box-huynh-de.php trong folder template-part để mình cần dùng thì block thì `get_template_part('template-part /box-huynh-de')` là okie rồi Ngoài những file php dùng cho các trang thì mình cần nhưng file style, image, js cho trang mình nữa thì mình hay tạo 1 thư mục public ví dụ như dưới public — css: chứa những file style của mình — images: chứa những file hình ảnh — js: chứa những file js — libs: chứa những thư viện mình down về như font, slider, animation… **Những phần nói trên là những file cơ bản cần dùng cho 1 trang nhưng chưa đủ 🤦‍♂️** . Ae xem 1 chút phần dưới để custom những page mình cần nha Ví dụ trang web mình có 2 trang liên hệ với giới thiệu nhưng 2 trang lại có 2 giao diện khác nhau thì sao hè vì mình chỉ có 1 file là page.php để hiển thị trang chớ mấy nên nó đang nhận file page.php là trang chính thì cách giải quyết là mình sẽ tạo với tên file là page-ten-slug.php Ví dụ với trang liên hệ thì sẽ có file tương ứng `page-lien-he.php` và trang giới thiệu `page-gioi-thieu.php` Nhưng ví dụ trang mình có 5 trang giao diện như liên hệ 5 trang giao diện như giới thiệu chẳng lẽ mình tạo 1 page rồi copy qua hà =)). Rứa thì hơi cồng kềnh nên mình sẽ tạo ra 1 template page rồi vào admin mình sẽ chọn trang đó thuộc template nào thôi. Mình sẽ tạo 1 folder là template-page trong này mình sẽ tạo ra những file giao diện mình mong muốn và khai báo tên template cho nó `Template Name: Template1` Tương tự chọn giao diện cho page thì post hoặc post type nào đó mình có thể chọn giao diện tương ứng bằng cách thêm 1 dòng dưới nữa Template Post Type: name_post_type ```

Setup dự án React Typescript

Setup dự án React Typescript
Hello 5 chăm ae 🤣. Bài viết này mình viết ra để lâu lâu tạo dự án thì vào copy cho nhanh á mà hehe. Một phần có gì ae tham khảo cách setup 1 dự án React Typescript như thế nào nhé 1️⃣ Đầu tiên đương nhiên mình phải create react app rồi `yarn create react-app name_project --template typescript` 2️⃣ Tiếp theo mình cài Prettier để format code và Eslint để quản lý tiêu chuẩn code cũng như giúp các member trong team thống nhất quy chuẩn lúc dev luôn.  `yarn add -D prettier eslint-plugin-prettier eslint-config-prettier`. À đừng quên setup editor vscode của mình Default Formatter => Chọn Prettier và Format On Save => true để tiện lúc code nhé 3️⃣ Thêm scripts vào package.json để check và sửa lỗi của eslint và prettier ``` { "lint": "eslint --ext js,jsx,ts,tsx src/", "lint:fix": "eslint --fix --ext js,jsx,ts,tsx src/", "prettier": "prettier --check \"src/ ** /(*.jsx|*.js|*.tsx|*ts|*.css|*.scss)\"", "prettier:fix": "prettier --write \"src/ ** /(*.jsx|*.js|*.tsx|*ts|*.css|*.scss)\"" } ``` Lúc này bạn chỉ cần chạy – `yarn lint` để kiểm tra lỗi eslint – `yarn lint:fix` để fix lỗi liên quan eslint (đôi lúc có những lỗi ae phải tự fix bằng tay nha) – `yarn prettier` để kiểm tra lỗi prettier format – `yarn prettier:fix` để tự fix lỗi prettier format 4️⃣ Tạo file `.prettierrc` để chia sẻ setting prettier giữa các editor. Các bạn có thể tạo ở trang [prettier này](https://prettier.io/playground/) cũng được nhé ``` { "arrowParens": "always", "semi": false, "trailingComma": "none", "tabWidth": 2, "endOfLine": "auto", "useTabs": false, "singleQuote": true, "printWidth": 80, "jsxSingleQuote": true } ``` 5️⃣ Tạo file `.eslintrc` để setting eslint ``` { "extends": ["react-app", "prettier"], "plugins": ["react", "prettier"], "rules": { "prettier/prettier": [ "warn", { "arrowParens": "always", "semi": false, "trailingComma": "none", "tabWidth": 2, "endOfLine": "auto", "useTabs": false, "singleQuote": true, "printWidth": 80, "jsxSingleQuote": true } ] } } ``` 6️⃣ Tạo file `.editorconfig` để chia sẻ một số setting giữa các editor với nhau cho đồng bộ ``` [*] indent_style = space indent_size = 2 ``` 7️⃣ À hiện tại Tailwindcss cũng khá trend và dự án hiện tại trên công ty mình cũng dùng nữa nên mình viết sẵn lệnh cài luôn đỡ mất công qua doc 😁 ``` yarn add -D tailwindcss postcss autoprefixer - Tiếp theo mình chạy npx tailwindcss init để tạo ra file tailwind config và edit content trong file lại thành: ["./src/ ** /*.{js, jsx, ts,tsx}"] có thể thêm hoặc xóa các option cho phù hợp dự án ae nhé - Và đừng quên import tailwind vào file css của mình nhé @tailwind base; @tailwind components; @tailwind utilities; - Nếu ae muốn sort các class của tailwindcss cho dễ nhìn thì yarn add -D prettier-plugin-tailwindcss ```

Bắt trend tạo trái tim đang hot rần rần hiện nay nào 😝

11/09/2022
Bắt trend tạo trái tim đang hot rần rần hiện nay nào 😝
Vào việc luôn, bài này mình share đoạn code tạo trái tim đập thả thính siêu hot ae tham khảo nhé. Chỉ cần tạo 1 file có đuôi là .html và paste đoạn code phía dưới save và chạy lên là oke rồi. À ae `có thể đổi tên ở dòng 338 bằng tên mình thích nhé` hoặc xóa đi nếu không muốn hiện tên hehe. Còn chần chừ gì nữa copy paste gửi cờ rớt thuiiii 😘 ``` phamvantu.com html, body { height: 100%; padding: 0; margin: 0; background: #000; display: flex; justify-content: center; align-items: center; } .box { width: 100%; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); display: flex; flex-direction: column; } canvas { position: absolute; width: 100%; height: 100%; } #pinkboard { position: relative; margin: auto; height: 500px; width: 500px; animation: animate 1.3s infinite; } #pinkboard:before, #pinkboard:after { content: ''; position: absolute; background: #FF5CA4; width: 100px; height: 160px; border-top-left-radius: 50px; border-top-right-radius: 50px; } #pinkboard:before { left: 100px; transform: rotate(-45deg); transform-origin: 0 100%; box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22); } #pinkboard:after { left: 0; transform: rotate(45deg); transform-origin: 100% 100%; } @keyframes animate { 0% { transform: scale(1); } 30% { transform: scale(.8); } 60% { transform: scale(1.2); } 100% { transform: scale(1); } } /* * Settings */ var settings = { particles: { length: 2000, // maximum amount of particles duration: 2, // particle duration in sec velocity: 100, // particle velocity in pixels/sec effect: -1.3, // play with this for a nice effect size: 13, // particle size in pixels }, }; /* * RequestAnimationFrame polyfill by Erik Möller */ (function () { var b = 0; var c = ["ms", "moz", "webkit", "o"]; for (var a = 0;a = duration && firstActive != firstFree) { firstActive++; if (firstActive == particles.length) firstActive = 0; } }; ParticlePool.prototype.draw = function (context, image) { // draw active particles if (firstActive Anh Thư ```

Thêm thay đổi vào commit cuối cùng với amend

10/29/2022
Thêm thay đổi vào commit cuối cùng với amend
Đôi lúc ae đang code gì đó nghĩ là xong rồi và commit push lên chuẩn bị tạo Pr cho mọi người review thì chợt nhận ra thiếu gì đấy cmnr. Thay vì vô viết rồi commit lại thì đã có **git amend** Sau khi ae thay đổi những gì đã thiếu rồi thì ae `git add .`để lưu lại những thay đổi. Sau đó dùng `git commit --amend` và nó sẽ hiện ra cửa sổ để mình sửa đổi message commit lúc nãy. Sau đó mình`push lên lại thôi nhưng phải -f` để đè lên commit cũ nhé, vì nó làm thay đổi mã hash commit đó rồi. Hy vọng sẽ giúp được ae thêm thay đổi commit dễ dàng hơn thay vì commit lên hoài như lúc xưa mình nhé kaka

Gộp commit với squash

10/28/2022
Gộp commit với squash
Đôi khi trong 1 feature có nhiều commit quá cũng không clearn lắm. Vd mình làm feature A thì code html có 1 commit, implement có 1 commit, update abc có 1 commit nữa không tiện quản lí sau này lắm, làm commit history không clean lắm `git rebase -i HEAD~3` (Head là con trỏ, trỏ đến vị trí của nó, 3 là tính từ vị trí Head => Gộp 3 commit từ vị trí head) Lúc này nó sẽ xuất hiện 1 file để bạn edit. Thứ tự 3 commit gần đây hơi ngược so với khi dùng git log. Và mình chỉ được gộp những commit phía sau vào commit phía trước (Gộp vô commit đầu tiên luôn cho dễ nhớ). Sửa pick thành s (hoặc squash cũng được). Sau khi xong thì nó xuất hiện thêm 1 file nữa để mình edit commit message. Và bây giờ chỉ cần `git push -f` là oke vì mình đã xóa 2 commit trước đó nên phải -f đè lên nghen ae.

Undo trong git

10/28/2022
Undo trong git
Hello ae lại là mình với những bài về git đây 😜. Trong bài viết này mình sẽ undo lại những thay đổi về trạng thái ban đầu ae cùng tham khảo nhé ### **Hoàn tác những file ở local changes về trạng thái ban đầu:** `git checkout name_file_change.ext` Hoặc `git restore name_file_change.ext` Hoặc khi change Vscode bên thanh bar trái cũng có xuất hiện những file change mình muốn undo file nào thì chỉ cần chọn vào mũi tên back rồi Discard Changes nó là oke ### Undo những file ở khu vực stage changes, khu vực mà sau khi mình add. lên git reset `name_file_change.ext` Hoặc git restore -S `name_file_change.ext` Hoặc khi add rồi bên thanh bar trái cũng có xuất hiện những file Staged Changes mình muốn quay lại thì chỉ cần chọn dấu – là oke ### Undo những file ở khu vực commited trong quá khứ Lấy mã commit đó, có thể lấy bằng cách click source control bên thanh bar trái, phía dưới có mục file history list ra những commit ở file này. Hoặc git log –oneline `git restore --source=mã_commit name_file_change.ext` Hoặc có thể click chuột phải tại file history rồi chọn Restore(Checkout) ### Undo commit với git reset git reset mã_commit => Đưa thay đổi về khu vực Changes git reset –sort mã_commit => Đưa thay đổi về Staged Changes git reset –hard mã_commit => Mất luôn thay đổi. Ít dùng do khá nguy hiểm vì nó xóa luôn commit sau nó cmnr =)) git reset –merger mã_commit => Giống –hard nhưng an toàn hơn, chỉ làm mất những thay đổi cần thiết. Còn những thứ mình đang code vẫn giữ nguyên Có thể undo commit gần nhất bằng source controls trong Vscode Hoặc nhanh hơn thì git log –oneline rồi muốn reset commit nào thì Ctrl+click mã hash đó rồi chọn Reset name_branch to commit rồi chọn option những bên trên **Và sau khi reset muốn push lên phải git push -f nghen. Vì nó sẽ đè lên các commit của origin**

Branch trong git

10/25/2022
Branch trong git
Branch nó giúp mình tạo ra những nhánh làm việc riêng biệt mà không ảnh hưởng lẫn nhau, dễ dàng quản lí code hơn. ### **Tạo 1 nhánh mới** Nó sẽ tạo 1 nhánh mới dựa trên nhánh hiện tại `git branch new_branch_name` Hoặc tạo 1 nhánh mới và chuyển sang nhánh mới luôn `git checkout -b new_branch_name` hoặc `git switch -c new_branch_name` (Cái mới ở git verson 2.23) ### List tất cả nhánh Hiển thị tất cả nhánh trên local `git branch` Hiển thị tất cả nhánh trên remote `git branch -r` Hiển thị tất cả nhánh trên local & remote `git branch -a` Đôi khi sẽ không hiển thị nhánh ở trên remote thì ae gõ `git fetch` trước để nó cập nhật lại repo của mình nghen ### Chuyển nhánh Chuyển qua lại giữa 2 nhánh ở local `git checkout name_branch` hoặc `git switch name_branch` ### Đổi tên nhánh Nếu tên nhánh hiện tại bị sai, sửa lại bằng cách `git branch -m new_branch_name` Trường ở nhánh này muốn đổi tên nhánh khác `git branch -m old_branch_name` `new_branch_name` Mình chỉ đổi được ở local thôi, nếu nhánh đó đã xuất hiện trên remote rồi thì khi mình push sẽ tạo ra nhánh mới trên repo ### Xóa nhánh Xóa nhánh ở local `git branch -D local_branch_name` Xóa nhánh ở remote `git branch origin --delete remote_branch_name` hoặc `git push origin :remote_branch_name` ### Push một branch Để push branch từ local lên `git push origin local_branch_name` hoặc `git push origin -u local_branch_name` nhưng cách này thì lần sau chỉ cần `git push` thôi thay vì origin bla bla kia nữa (‘-u’ là viết tắt của ‘–set-upstream’. Nó cho git biết rằng hãy tự kết nối nhánh ‘local feature’ với ‘origin feature’ Câu lệnh giúp các ae không cần gõ chính xác tên local branch luôn `git push -u origin HEAD` (Head là nó tham chiếu đến đầu danh sách branch hiện tại) Xem những local branch đã kết nối với remote branch thì `cat .git/config` ### Cập nhập branch đã xóa Khi ai đó xóa một branch trên remote nhưng khi mình gõ `git branch -r` vẫn show ra origin branch đó bình thường, thì để đồng bộ thì `git fetch -p`

README là gì và viết README như nào?

10/25/2022
README là gì và viết README như nào?
Trong bài viết này mình cùng tìm hiểu về file readme là gì nhé. Nó là 1 file dùng để giới thiếu dự án, cấu trúc cũng tài liệu cho dự án. Tạo file README.md (tên này là tiêu chuẩn để cho github, gitlab.. nhận diện được đó là file mô tả cho dự chúng ta) do sử dụng cú pháp Markdown để viết nên file có đuôi là .md á nghen ae Ae có thể lên trang [markdownguide](https://www.markdownguide.org/basic-syntax/) hoặc [document trên github](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax) của nó để xem cho đầy đủ cụ thể nhé. Mình có ví dụ những trường hợp thường dùng để viết mardown như các thẻ tiêu đề, thẻ văn bản, in đậm, in nghiêng, danh sách, chèn code….ae tạo file copy chạy thử nhé ``` # Đây là h1 ## Đây là h2 ### Đây là h3 Đây là một thẻ p bình thường Đây là danh sách ul, li - Đây là li 1 - Đây là li 2 [Đây là thẻ a](fb.com) ![Đây là mô tả cho hình ảnh](https://anhdepbonphuong.com/wp-content/uploads/2016/12/hinh-nen-dep-cho-may-tinh-nature-wallpapers-nature-wallpaper-latest-beautiful-wallpapers-800x480.jpg) **In đậm** *In nghiêng* `console.log('Chèn code ngon lành luôn')` ```js const a = 100; ``` ```html Hello Readme ``` ``` git status ```

Bỏ qua file với .gitignore

10/23/2022
Bỏ qua file với .gitignore
Đôi lúc ae không muốn git theo dõi file thay đổi của chúng ta chỉ cần tạo file `.gitignore` Khi ae làm việc với nodejs thì sinh ra thư mục node_modules khá nặng, không cần thiết phải lên git làm gì vì khá tốn thời gian pull push code và cả tài nguyên lưu trữ git nữa Để comment trên gitignore thì bắt đầu # vd: `# Comment``` Để ignore file thì chỉ cần ghi tên file là được `app.js` Để ignore cả thư mục thì chỉ cần ghi tên thư mục là được `node_modules`  nhưng nên thêm dấu / để phân biệt với file `node_modules/` Để ignore tất cả các thứ bên trong thư mục folder: `folder/ ** ` Muốn thêm file a.txt trong node_modules được theo dõi trong git thì thêm !: `!node_modules/a.txt` Để ignore tất cả các file có đuôi là `.exe` ở thư mục folder dù cho có nằm ở sub-folder đi chăng nữa: `folder/ **/** .exe` Để ignore tất cả các file có đuôi là `.exe`: `*.exe` Để ignore tất cả các file có tên bắt đầu là log: `log*`````

Git pull và giải quyết conflict code

10/22/2022
Git pull và giải quyết conflict code
Trường hợp code trên remote repo có những thay đổi và cập nhật, anh em có thể cập nhật những thay đổi này trên local repo của bạn cho giống như trên remote repo bằng câu lệnh vd như `git pull orgin name_branch` Đôi lúc trong team ai đó sửa code trên remote rồi nhưng mình cũng cập nhật code dưới local ở cùng 1 nơi. Thì lúc này git sẽ không cho phép mình push code lên mà mình phải pull code từ remote về xem chọn đoạn code trên remote hoặc dưới local hoặc cả hai hoặc kết hợi 2 cái lại… Thường thì trước khi push code lên ae pull code mới nhất trên remote về git pull Nếu có confict thì giải quyết nó nên chọn bỏ đoạn nào. Nếu đoạn code đó ae trong team code thì có thể thảo luận để okie hơn Add file đó lại hoặc git add . cũng được Commit những file change rồi push lên là done ròi :v

Trick dùng nhiều tài khoản github trên cùng một máy

10/22/2022
Trick dùng nhiều tài khoản github trên cùng một máy
Hello ae có bài này chắc sẽ ngắn thôi nhưng có thể giúp ae control được nhiều tài khoản github trong cùng một máy dễ dàng hơn qua bài viết này nhé. Đi thoi… Tại thư mục (~/.ssh/) nơi sinh ra id_rsa của các bạn ấy, mình tạo thêm 1 file config (Không có đuôi gì cả nha) để git nó biết được mình đang dùng tài khoản nào để thao tác pull push code. Ae mở file config lên bằng vscode hoặc cái gì nào đó rồi mình sửa theo bên dưới nhé ``` #Default Github Host github.com HostName github.com User git IdentityFile ~/.ssh/id_rsa_kozocom #Github personal Host github-phamtu613.com HostName github.com User git IdentityFile ~/.ssh/id_rsa_personal ``` Ở đây mình dùng 1 account ở công ty và 1 account cá nhân. À lúc tạo ssh key anh em có thể rename lại như mình cho tường minh nhé. Mình lấy mặc định là tài khoản account cty do mình làm việc chủ yếu ở cty mà hehe. Tài khoản thứ 2 là tài khoản custom cá nhân của mình. Khi mình Khi mình thực hiện những lệnh như clone, remote…thì ở tài khoản default đầu tiên thì mình vẫn giữ nguyên link git@github.com nhưng nếu mình thực hiện ở tài khoản thứ 2 thì thay vì `git@github.com` mình sẽ chuyển thành `git@github-phamtu613.com` nhé.

Git log là gì?

10/16/2022
Git log là gì?
Câu lệnh `git log` dùng để xem các commit gần đây của mình như thế nào. Mỗi commit sẽ có mã riêng biệt cho từng commit. Thường nó sẽ dài khiến mình khó đọc thì lệnh `git log --oneline` hiển thị ngắn gọn dễ đọc hơn. Nó sẽ lấy 7 ký tự đầu tiên và tên của commit đó Và những comnmit này có là do mình commit á nghen. Không phải commit nào được push mới hiển thị ở đây. Cứ commit là log sẽ ra hết :v

Git push là gì?

10/16/2022
Git push là gì?
Để đẩy code từ local lên trên remote thì thường dùng lệnh `git push origin name_branch` Ví dụ mình muốn đẩy code lên nhánh main: `git push origin main` Đừng trên trước khi push code phải add để thêm file thay đổi vào Staging, và commit nó nữa nhé Có thể ae thấy bạn bè hoặc đồng nghiệp chỉ cần git push thôi thay vì origin tên nhánh này nọ. Bởi vì nhánh mặc định của git thì nó tự hiểu có origin phía sau rồi nên không cần viết thêm gì nữa

SSH key trong github

10/13/2022
SSH key trong github
– Khi push thì mình phải đảm bảo đã có 1 repo trên server (github) rồi – Local repo của mình phải kết nối với remote repo đó **Để kết nối với remote repo thường sẽ có 2 cách** Clone remote repo về local, lúc này dưới local đã có local repo và được kết nối sẵn với remote repo Dùng câu lệnh git remote để tạo mối liên kết giữa local repo và remote repo (cách này thường thì sẽ có code dưới local gòi nha ae) **Clone thì thường sẽ có 2 cách** Clone bằng SSH (nên dùng cái này vì tiện và bảo mật) nhưng hơi phức tạp lúc setting ban đầu (tạo key, add key) Clone bằng HTTPS Để tạo SSH key thì bạn có thể tham khảo ở [đây](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent) hoặc xem hướng dẫn của mình dưới nhé Đầu tiên ae bật terminal lên gõ dòng lệnh sau: ssh-keygen -t ed25519 -C “email_bạn_dùng_ở_account_github” Nó sẽ thông báo tạo ra 1 public key và 1 pirvate key ở ổ `/C/User/...` thường là vậy. Nếu bạn muốn đổi đường dẫn này thì có thể copy đoạn `/C/User/.../id_rsa_tupham` hoặc bạn có thể để nguyên rồi enter cũng không sao Rồi các bước sau như nhập password bạn cũng ko cần nhập cứ enter cho đến khi nó thông báo oke Để xem public key nhanh chóng thì ở bước 3 có thông báo your public key… C/User/… thì mình copy bỏ lên trình duyệt luôn rồi sửa thành C:/User… là hiển thị rồi đỡ tìm hehe. Thấy khỏe hơn nhiều chưa ae. Hoặc nhanh hơn thì tại terminal đang gõ nhập lệnh `cat` rồi copy đường dẫn đó vô luôn nha ae Sau khi tạo thành công thì nó sẽ sinh ra cho bạn 2 file là private key và public key theo đường dẫn mà bạn nhập tên file. File chứa public key sẽ có đuôi .pub phía sau. Add public key lên github nhanh thông qua [đường dẫn này](https://github.com/settings/ssh/new) Check xem kết nối github thành công chưa: ssh -T git@github.com Hiện như này là add thành công gòi nhé ae. Nếu chưa được thì xem mình gắn ssh key vô github chính xác chưa nhé vì có thể ae copy thiếu gì đó hehe SSH key trong github

Combo Git status, Git add, Git commit 🧐

10/12/2022
Combo Git status, Git add, Git commit  🧐
### Git status Cho mình biết đang ở nhánh nào (On branch…) Trạng thái branch của mình so với trên server github như thế nào, có thể sai thì code đã được update trên server lúc mình đang code. Muốn chính xác thì phải git fetch để tải code mới nhất về Trạng thái các file, file nào đang được git theo dõi không ### Quan trọng: Các khu vực làm việc với git theo thứ tự như sau Khu vực làm việc: Là nơi mình đang code, `ở local` Khu vực staging: Sau khi dùng `git add` thì file sẽ được đưa lên khu vực này, `vẫn ở local` Khu vực commited: Khi khi dùng `git commit` thì file từ staging sẽ được đẩy lên khu vực này, `cũng vẫn ở local` Khu vực remote hoặc gọi là origin: Sau khi dùng `git push` thì file từ staggin sẽ được đưa `lên server` ### Git add Câu lệnh này sẽ thêm 1 hoặc nhiều file thay đổi vào khu vực **Staging** Thêm 1 file: `git add name_file_1` Thêm 2 file: `git add name_file_2` Thêm tất cả file: `git add .` ### Git reset Đôi khi mình lỡ add nó lên khu vực Staging rồi nhưng muốn back lại 1 hoặc nhiều file về khu vực code Khôi phục 1 file từ Staging về khu vực code: `git reset name_file_1` Khôi phục nhiều file: `git reset .` ### Git commit Câu lệnh này sẽ thêm những file từ khu vực Staging lên khu vực commit kèm theo title Vd: git `commit -m "implement feature notify talk"` Hoặc có thể thêm mô tả bổ nghĩa cho title thì: `git commit -m "implement feature notify talk" -m "description more"` Hy vọng các bạn có thể nắm, hiểu được 4 khu vực làm việc để những câu lệnh git mình gõ xuống thêm % tự tin hơn kkk

Git init và git config khi bắt đầu dự án

10/12/2022
Git init và git config khi bắt đầu dự án
### Git init Chạy git init để tạo 1 repository (nơi chứa source code) trên máy tính. Sau khi chạy xong nó sẽ sinh ra 1 mục .git (có thể bị ẩn tùy máy), và source code chúng ta phải nằm ngang cấp với mục .git nhé **Có 2 loại repository** 1 là ở local, trên máy tính 2 là ở server ví dụ như github, gitlab ### git config Để biết đứa nào đẩy code lên **Có 2 loại config** Local: Dành riêng cho dự án Để xem config ở local: git config –local –list Global: Cho toàn máy tính chúng ta luôn Để xem config ở global: git config –global –list Bây giờ config để biết đứa nào push code lên nè: git config –global user.name “TuPV” Thêm config email nữa là oki: git config –global user.email “tutu@gmail.com” Nói nhỏ: Với terminal sử dụng Git bash thì khi dùng tiếng Việt đôi lúc sẽ dễ bị lỗi. Nên chuyển Unikey sang tiếng Anh nhé. Ví dụ mình gõ chữ tú rồi mình xóa đi 1 ký tự thì đôi khi nó hiển thị còn chữ tu nhưng vẫn báo lỗi á nghen. Hẹn gặp lại ae vào những bài tiếp theo trọng tâm hấp dẫn nhé 🥳

Git là gì? Cài đặt git trên máy tính

10/12/2022
Git là gì? Cài đặt git trên máy tính
Hello ae. Bài này sẽ là bài đầu tiên trong chuỗi sê ri git của mình nhé. Đảm bảo đủ dùng bao gọn, bao dễ hiểu. Vì lúc trước mình sợ git lắm kaka, vì sợ mất code này nọ vài lần nên dùng rén rén. Nên hy vọng bài hày sẽ giúp phần nào ae rén như mình lúc xưa có thể tự tin bun bút tẹc ga. Đi thôi 😁 Lúc trước đi học chưa biết git thì ae mỗi đứa code 1 phần rồi gửi file với nhau đôi khi ráp vào thiếu hoặc lặp code thì rất là bất tiện. Chứ có GIT như bây giờ thì quá tiện rồi, biết ai là người code dòng này, code lúc nào và đồng bộ source code với nhau luôn Github là gì? Hiểu nôm na đó là 1 hệ thống chưa dự án, source code chúng ta. Dùng cá nhân thì oke free tẹc ga, còn nếu dùng team lớn thì trả phí nghen Bây giờ mình cài [git](https://git-scm.com/) nha (là 1 hệ thống quản lý phiên bản, theo dõi source code chúng ta). Sau khi cài đặt xong thì mình click chuột phải là nó sẽ hiện dòng `git bash here` hoặc bạn bật cmd lên gõ `git --version` là nó hiển thị phiên bản bạn đang dùng, vậy là okie rồi Bài sau mình sẽ nói về git config cũng như tạo 1 thư mục được quản lý bỏi git như thế nào nhé.

Quản lý Nodejs thông qua NVM

10/10/2022
Quản lý Nodejs thông qua NVM
Hello 500 ae, hôm nay mình sẽ giới thiệu sơ qua NVM giúp ae quản lý version node dễ dàng hơn nhé. Gét gô 🧐 Trước kia chưa biết đến NVM mình hay download trên [này](https://nodejs.org/en/) nè rồi cài dùng. Nhưng đôi khi gặp trường hợp cài dự án khác thì cần bản node mới hơn, thì mình phải gỡ đi cài lại bản mới. Đến khi quay lại dự án cũ thì bản mới không tương thích nên phải gỡ bản hiện tại và cài lại bản cũ. Từ đó mình tìm thấy NVM giải quyết switch qua lại các version 1 cách nhanh chóng hehe. Mình dùng windown nên mình lên [đây](https://github.com/coreybutler/nvm-windows) cài đặt nó, ae dùng ubuntu hoặc mac thì có thể lên [đây](https://github.com/nvm-sh/nvm) nghen. Cài đặt xong bạn có thể check version nvm `nvm -v`  hoặc version node `node -v` Để kiểm tra máy bạn đang dùng node version nào cũng như danh sách version trong máy bạn có thì => `nvm list` Để cài mới 1 phiên bản node thì `nvm install name-version` Vd: `nvm install 16.17.1` Và để sử dụng version nào thì `nvm use name-version` Vd: `nvm use 16.17.1` Hy vọng với vài dòng đơn giản này có thể giúp ae bớt khổ trong việc chuyển đổi qua lại giữa các version node hehe. Để rõ hơn các bạn có thể xem trên document mình có gắn link ở trên nhé. Bye 500 ae nghen 🤗

Destructuring, Rest parameter, Spread Syntax trong Javascript

10/08/2022
Destructuring, Rest parameter, Spread Syntax trong Javascript
Bài viết này mình sẽ tóm gọn về Destructuring, Rest parameter, Spread Syntax trong Javascript nhé. Mình thấy thực sự cần thiết và dùng rất nhiều trong dự án. Hy vọng với vài tóm tắt bên dưới sẽ giúp ae đỡ nhầm lẫn hơn cũng như biết được tên gọi của nó nhé ### Destructuring với Object ``` const user = { name: 'Tu Pham', age: 24, } // Thay vì viết dài dòng như thế này // const name = user.name // const age = user.age // Có thể dùng Destructuring làm code ngắn gọn hơn const { name: userName, age} = user // có thể đổi tên khác bằng cách : newName console.log(userName) // Tu Pham console.log(age) // 24 ``` ### Destructuring với Array ``` const res = [1, 2, 3, 4] const [a, b, c] = res console.log(a, b, c) // 1 2 3 ``` ### Spread Syntax ``` const user = { name: 'Tu Pham', age: 24, } const cloneUser = {...user} console.log(cloneUser) // { name: 'Tu Pham', age: 24, } Cái này có thể gọi là shallow copy (copy nông). Vì nó chỉ copy giá trị của thôi. So sánh bằng thì thực ra nó không bằng đâu nghen. Sẽ có bài nói về tham trị tham chiếu sau để rõ hơn nghen ``` ### Rest parameter ``` const handle = (a, b, ...c) => { return c } const value = handle(1, 2, 3, 4, 5, 6, 7, 8] console.log(value) // [3, 4, 5, 6, 7, 8] // Những tham số còn lại gộp thành 1 mảng ```

Structural types trong Typescript

10/03/2022
Structural types trong Typescript
Bài này thì mình sẽ tìm hiểu 2 cái type phức tạp hơn 1 chút nhưng cũng simple thôi đó là Object và Array ``` const obj: {} = {} const user: { firstName: string; lastName: string; isStudent: boolean; school: (string | number)[]; // mảng có thể có số hoặc chữ. Có bài viết riêng về union types nghen score: number[]; } = { firstName: "Pham", lastName: "Van Tu", isStudent: false, school: ["Hoa Tho", "Dang Thai Mai", "Phan Thanh Tai", "Dai Hoc Su Pham"], score: [8, 9, 10] }; ```

Primitives types trong Typescript

10/02/2022
Primitives types trong Typescript
Tiếp nối bài giới thiệu Typescript thì hôm nay chúng ta đến với Primitives types nhé. Type assignment: const variable: dataTypes = value Đại loại là mình truyền giá trị cho 1 biên nào đó const age:number = 23 const name:string = ‘Tu Pham’ const isStudent:boolean = false ``` // Js export function total(a, b) { return a + b } // Ts export function total(a: number, b: number, c?: number) { return a + b } // c?: parameter này không bắt buộc (optional) ``` Bình thường ở Js mình có thể không khai báo type cho tham số nên có thể truyền bất cứ type nào vào, ngược lại ts chặt chẽ hơn bắt buộc phải khai báo kiểu data truyền vào. Có thể khai báo tham số không bắt buộc bằng cách thêm dấu ? trước type của nó là mình có thể truyền hoặc không rồi nè hehe.

Giới thiệu Typescript

10/02/2022
Giới thiệu Typescript
Hôm nay mình ae cùng tìm hiểu về Typescript nhé. Đây là bài đầu tiên cũng như mở hàng cho sê ri 🤪 Typescript sắp tới của mình. Hy vọng sẽ giúp cho ae hiểu cũng như nắm được phần nào đó thằng Ts hơi khó chịu này nhé hehe…..đi thôi 😉 **Định nghĩa** : Ngắn gọn nó là 1 ngôn ngữ lập trình, được phát triển bởi microsoft dựa trên javascript. Khi code thì nó sử dụng những compile như webpack để build ra và convert sang javascript lại, và nó sẽ có những type giúp code chặc chẽ, clean hơn, nó thường sử dụng phát triển cho những ứng dụng lớn. Bên cạnh đó thì code Ts dài, mất thời gian hơn, phải suy nghĩ nó là type gì đồi nữa :)) Bài sau mình cùng tìm hiểu về Primitives types trong Typescript nhé

Anh em đã biết những thuộc tính CSS này chưa hè?

09/23/2022
Anh em đã biết những thuộc tính CSS này chưa hè?
Sau khi nghĩ dưỡng 2/9 hơn nữa tháng nằm qua 3 cái bệnh viện thì giờ mình quay lại đây. Hy vọng sắp tới sẽ chuyên cần hơn trong việc chém gió này keke. Thôi vào việc luôn get go 😁 `margin-inline:` Nó sẽ tương ứng với việc các bạn viết margin-left và margin-right Ví dụ luôn cho dễ đi vào lòng người nè: Bình thường mình muốn cho 1 block ra giữa mình có thể dùng `margin-left:auto` và `margin-right: auto` còn sau khi các bạn đọc đến đây rồi thì => `margin-inline: auto` thấy hịn hơn chưa 😁 `margin-block:` Tương tự nhưng khác chiều thôi nó sẽ tương ứng với top và bottom Ví dụ luôn:  Thay vì các bạn viết `margin-top: 20px` và `margin-right: 20px` => `margin-block: 20px` cũng hịn hịn hơn xíu gòi đó 😁 Thì có margin thì cũng sẽ có padding thôi chứ chạy đi đâu nữa 😝 => `padding-inline & padding-block` `aspect-ratio:` là 1 thuộc tính giúp chúng ta hiển thị hình ảnh theo tỉ lệ (1:1, 16:9, 4:3). ``` .aspect { aspect-ratio: 1/1; // aspect-ratio: 16/9; // aspect-ratio: 4/3; } .aspect img { width: 100%; height: 100%; object-fix: cover; } ``` Đa số trình duyệt đều hỗ trợ rồi tầm 80% trừ những trình duyệt cũ quá hoi (< safafi 14.8). Bạn có thể check trên trang caniuse.com nghen. `inset` thuộc tính này thường giúp mình viết thay cho trường hợp top: 0, right: 0, bottom: 0, left: 0 để phủ 1 lớp absolute full thằng cha relative luôn hoặc top: 0, left: 0, width: 100%, height: 100% cũng có tác dụng tương tự thì mình có thể viết gọn thành `inset: 0` nó là viết tắt của `inset: top right bottom left` tương tự cách viết tắt của padding và margin thôi hehe Hy vọng anh em đọc xong bài này có thể giúp anh em biết được vài thuộc tính mới trong css, áp dụng luôn vào dự án đang làm của mình cho quen tay nhé. Mình sẽ update bài này nếu có thêm cái mới nghen 🥰

Flexbox trong css

07/28/2022
Flexbox trong css
### display Để sử dụng flex trong css thì đơn giản chúng ta chỉ cần khai báo display: flex hoặc display: inline-flex Về chức năng thì nó cũng như nhau, nhưng flex thì sẽ full 100% phần tử cha chứa nó còn inline-flex thì độ trộng phần tử bao nhiêu thì nó chiếm bấy nhiêu thôi ### flex-direction: row | row-reverse | column | column-reverse; row: Giá trị mặc định sẽ là row theo chiều ngang trái sang phải row-reverse: Các phần tử vẫn nằm theo chiều ngang nhưng hiển thị ngược lại từ phải qua trái column: Các phần tử nằm theo chiều dọc từ trên xuống dưới column-reverse: Các phần tử nằm theo chiều dọc được sắp xếp đảo ngược từ dưới lên trên ### align-items: stretch | flex-start | flex-end | center | baseline; stretch: Giá trị mặc định sẽ là stretch làm cho các cột tự giãn ra cao bằng nhau flex-start: Canh theo phần trên **đầu** thôi, còn nội dung ngắn dài tự thay đổi flex-end: Canh theo phần trên **dưới** thôi, còn nội dung ngắn dài tự thay đổi center: Canh giữa theo trục dọc của các phần tử baseline: Nó sẽ canh theo nét chữ nằm theo 1 hàng ngang ### align-self: auto | flex-start | flex-end | center | baseline | stretch; Nó cũng tương tự như align-item nhưng khác ở chỗ nó sẽ set riêng cho từng phần tử ### justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly; flex-start: Giá trị mặc định các phần tử sẽ nằm phía bên trái flex-end: Các phần tử sẽ nằm phía bên phải center: Các phần tử sẽ nằm ở giữa space-between: Nó sẽ tạo các khoảng trống giữa các phần tử bằng nhau space-around: Nó sẽ tạo các khoảng trống giữa các phần tử bằng nhau và các phần tử cũng có khoảng trắng nữa ( = 1/2 khoảng trắng ở giữa) space-evenly: Tạo ra các khoảng trống đều bằng nhau

Giới thiệu về React Hook Form API

Giới thiệu về React Hook Form API
Hello ae bài viết này mình sẽ sơ lược về thư viện React Hook Form API và những api mình hay dùng của thằng này nhé! Link thư viện: [React Hook Form](https://react-hook-form.com/v6/api) Mình thường sử dụng các hook chính để làm việc chủ yếu là hook useForm, Controller, ErrorMessage. Mình dùng bản v6 nhé ### Hook useForm – Nó giúp mình tạo ra 1 Object form instance. Nó cung cấp đầy đủ tất cả các phương thức giúp mình lấy được giá trị, trạng thái. set value…Bạn có thể xem code demo của doc bên dưới ``` const { register } = useForm({ mode: 'onSubmit', // có thể là onBlur, onChange, onTouched reValidateMode: 'onChange', defaultValues: {}, // gán những giá trị mặc định khởi tạo của form mình resolver: undefined, // Để mình truyền vào cho nó 1 cái validation resolver. Thường mình dùng yup nghen context: undefined, criteriaMode: "firstError", shouldFocusError: true, shouldUnregister: true, }) ``` – Đầu tiên cái useForm sẽ nhận vào 1 Object như trên ### Controller – Nó giúp mình tự động bind những sự kiện vào ui control của mình ### ErrorMessage – Mỗi lần cần show lỗi thì nó giúp mình show err ra. Bài này nói sơ qua như vậy thôi nha. Tập tiếp theo ở đây nhé hehe

Tìm hiểu về ASYNC AWAIT

06/29/2022
Tìm hiểu về ASYNC AWAIT
Khi ta có một function là test, khi function test thực thi, bằng cách console.log (ở dưới) đoạn text được in ra theo thứ tự, Tìm hiểu về ASYNC AWAIT Tìm hiểu về ASYNC AWAIT nhưng khi ta setTimeout cho nó thì có sự thay đổi đoạn text sẽ in ra số 2 và 3 trước rồi sau đó mới in ra số 1 **Promise** sinh ra để xử lý các thao tác bất đồng bộ, trước khi có promise thì chúng ta thường xử dụng callback, mà callback thì dễ bị trường hợp callback hell (nó sẽ bị chọt sâu vào, rồi rắm, khó nhìn, khó hiểu) Tìm hiểu về ASYNC AWAIT **Promise** sinh ra ở phiên bản ES6 để giải quyết (khắc phục) các trường hợp thường mắc phải ở callback Cách tạo ra một promise thì ta sẽ tạo một từ khoá new với promise trong constructor chúng ta sẽ có executor trong executor function chúng ta có 2 tham số (resolve và reject): **Resolve** khi thao tác xử lý logic thành công (success) **Reject** khi thao tác xử lý bị thất bại (failed)  và khi sử dụng Promise thì đối tượng promise được tạo ra, chúng ta sử dụng 3 hàm (phương thức) **then** / **catch** / **finally, then** và **catch** đều nhận những callback function, **then** nó được thực thi khi promise được resolve, **catch** nó được thực thi khi promise được reject, **finally** khi kết thúc thực thi promise của resolve và reject Author: Lincoln (Linh Nguyen Van)

Routing trong React only post 😁

Routing trong React only post 😁
Bài viết này mình sẽ nói về routing trong React nghen. Nhưng mà ở version 5 thôi nhé, version mới mình chưa update hehe Package: [react-router-dom](https://www.npmjs.com/package/react-router-dom)` **npm i --save react-router-dom@^5** ` ### Các component trong react-router-dom Router: Component bao bọc tất cả các component khác của routing, mình sử dụng là **BrowerRouter** còn các loại khác các bạn có thể tìm hiểu sau nhé. Và tất cả các component của reacr-router-dom đều phải nằm bên trong Router nhé Route: Render component khi match với patch Switch: Chỉ render **route đầu tiên** match path Redirect: Redirect từ path này sang path khác Link: Đi tới path tương ứng NavLink: Giống như Link như có thêm activeClassName, thường làm cho menu để style cho item đang active ### **Sự khác biệt Route & Switch** Route:Chỉ cần match với path thì render lên component đó lên Switch: Nó sẽ chạy từ trên xuống dưới, check từng Route, cái nào match với path hiện tại thì render component đó và dừng tại đó luôn. Ngược lại không dùng Switch thì nó sẽ render tất cả component được match luôn Switch bọc các Route lại ### **Route matching** Mặc định exact = false, lúc đó Route sẽ match khi URL bắt đầu tới path Khi exact = true, lúc đó Route sẽ match khi URL = path ### Redirect: Mình muốn chuyển từ path này sang path khách thì mình dùng Redirect nghen Dùng bên trong Switch Redirect từ path nào đến path nào. Có thể sử dụng thêm exact ``` // Chỉ cần bắt đầu /home thì sẽ tự động chuyển sang / // Bắt buộc url là /home thì sẽ tự động chuyển sang / // Cũng có thể chuyển mà vẫn giữ tham số url được luôn nha ``` Các hook trong react-router-dom useHistory: Trả về **history** instance, dùng để navigate. Thường dùng để di chuyển qua trang khác thay vì dùng Link hoặc NavLink useLocation: Trả về **location** object của URL hiện tại. Thường xử lý với URL params useParrams: Trả về **path params** object của URL hiện tại. Khi muốn xử lý path params useRouteMatch: Trả về **match** object của URL hiện tại. Khi làm nested routing ### Phân biệt Path params & URL params **Path params** Ví dụ: Route có path là: /todos/:todoId User vào đường dẫn: todos/123 -> Path params là {todoId: ‘123’} **URL params** User vào đường dẫn: /todos?page=1&size=10 URL params là phần sau dấu chấm hỏi

Cách so sánh 2 mảng cơ bản trong javascript

06/09/2022
Cách so sánh 2 mảng cơ bản trong javascript
Bài viết này mình sẽ  tìm hiểu cách so sánh 2 mảng cơ bản trong javascript bằng kiểu dữ liệu Json nha. JSON là viết tắt của cụm từ Javascript Object Notation thì đây 1 kiểu dữ liệu tuân theo 1 quy tắc nhất định. Mình thấy ngôn ngữ nào cũng sử dụng nó cả hehe. Mình ví dụ sau này muốn lưu data nào đó vào database thì không ai mà lưu 1 mảng `const arr = [1, 2]` như thế này cả mà người ta sẽ chuyển đổi sang 1 kiểu dữ liệu Json xong rồi mới thêm vào database chứ hông là nó hông hiểu :d ### Cú pháp: **JSON.stringify(value):** Chuyển giá trị sang dưới dạng JSON string **JSON.`parse`(value):** Chuyển đổi giá trị JSON sang kiểu ban đầu của nó Lúc trước mình cũng thắc mắc sao không dùng hàm toString để chuyển sang string rồi lưu luôn cho khỏe :v. Cách so sánh 2 mảng cơ bản trong javascript Nếu dùng `JSON.stringify` thì nó sẽ lưu dưới dạng Json string. Vậy mình muốn lấy ra lại giá trị ban đầu [1,2,3] thì mình dùng JSON.parse(value) nha `JSON.parse([1,2,3]) -> [1,2,3]` ``` const arr1 = [1, 2, 3]; const arr2 = [1, 2, 3]; console.log(arr1 == arr2); // false console.log(JSON.stringify(arr1) === JSON.stringify(arr2))// true ``` Nếu như so sánh bình thường thì sẽ ra kết quả là false, liên quan đến by Reference trong Js hiểu nôm na như có sẽ lưu địa chỉ của giá trị chứ không giá trị của nó nên nếu so sánh thì nó so sánh địa chỉ đó thôi hehe. Còn so sánh theo chuỗi Json String thì okie rồi nè hehe.

Styling trong React

Styling trong React
Nay mình cùng tìm hiểu các cách khác nhau để style trong React nghen. ### I. Inline styles – Thêm vào thuộc tính style của tag html, và viết các thuộc tính theo dạng camelCase nha. Ví dụ backgroundColor, textAlign… ```

``` – Cách này ít dùng, chỉ dùng khi cần thay đổi styles theo props, hoặc giá trị động từ api trả về chẳng hạn ### II. Css – Cách này tạo 1 file css bên ngoài và import vào dùng những class, id… đã định nghĩa sẵn bên file css này là okie rồi ``` /* styles.css */ .text-center { text-align: center; } /* component.js */ import './styles.css'; ``` ### III. Scss & Bem – Cũng như cách trên  nhưng tạo file scss và có thể viết sass trông gắn gọn, sạch sẽ hơn ahihi ``` /* styles.scss */ .menu { display: flex; &-item { position: relative; } &-link { color: "blue"; } } /* component.js */ import './styles.scss'; ``` ### IV. Css Module – Đối với cách này thì sẽ tạo ra 1 unique class bằng cách thêm các chuỗi vào tên class nên sẽ ko gặp vấn đề về trùng class giữa các dev với nhau ``` /* styles.module.css */ .title{ color: red; } /* component.js */ import './styles.module.css'; Title is here ``` ### V. Styled Component – Cách này viết css trong js luôn. Nó sẽ tự tạo ra class unique cho mình nên cũng sẽ không gặp vấn đề trùng class cách css module ``` /* component.js */ const TitleStyles= styled.h1` text-align: center; color: ${props => props.color || "red"} ```

Life cycles trong React

Life cycles trong React
Life cycles là 1 phần khá quan trong trong React, nó giúp mình hiểu hơn về cách hoạt động của 1 component ra sao. Bài viết này mình sẽ nói về life cycles trong React nghen. Đầu tiên thì các component life cycle chỉ có trong Class Component thôi nha. **Với component trong ReactJs, life cycle gồm 3 giai đoạn:** Mounting – Được tạo ra Updating – Qua nhiều cập nhật, thay đổi Unmounting – Bị hủy bỏ Hình mô tả life cycles trong ReactJs bạn có thể đoán từng giai đoạn có những hàm nào luôn hehe Life cycles trong React ### I. contructor() – Thường sẽ dùng để khai báo property hoặc state của component ``` class App extends PureComponent{ constructor(props) { super(props); this.DEFAULT_COLOR = "Green"; this.state = { postList: [], } } } ``` ### II. componentDidMount() – Thường để tạo data cho component như get API, update state… – Ví dụ như này cho dễ hiểu nè. Contructor chạy đầu tiên định nghĩa sẵn state postList Component sẽ render đầu tiên, lúc này chưa có data gì đâu nghen ComponentDidMount sẽ call api gì đó xong sẽ setState data được trả về từ API cho postList mới Khi setState thì component sẽ re-render lại 1 lần nữa thì sẽ có data mới từ api show ra nè ### III. componentWillUnmount() – Chạy 1 lần sẽ được gọi khi component của mình được hủy bỏ đi, vd như không render nó nữa hoặc chuyển trang – Thường sẽ gọi nó để clear timeout hoặc interval nếu có dùng – Rest dữ liệu trên redux nếu cần thiết ### IV. componentDidUpdate() – Thường ít dùng – Chỉ dùng nếu muốn handle update component khi click nút back trên url có query params – Cần thận setState trrong này vì có thể sẽ gây ra vòng lặp vô hạn á, vì setState thay đổi sẽ re-render và gọi componentDidUpdate rồi setState thay đổi xong re-render tiếp….hehe Hy vọng bài viết bài sẽ giúp các bạn hiểu hơn về life cycle trong React nha

Chia component như thế nào cho hiệu quả trong React

Chia component như thế nào cho hiệu quả trong React
Có nhiều phương pháp chia component nên số loại component sẽ khác nhau. Ở bài viết này mình chia React theo 2 loại component **– Container: Smart component** Quản lý, xử lý xử liệu (Có thể get api lấy data, hoặc data tĩnh, cung cấp dữ liệu và có dữ liệu để render) Không quan tâm render UI như thế nào Chỉ quan tâm render cái gì Có thể chứa container con và các components **– Component: Dumb component** Thằng cho cái gì render cái đó Không cần biết dữ liệu đến từ đâu Thường chỉ có props, không có state Tái sử dụng, với props khác nhau thì sẽ render khác nhau Mình ví dụ 1 block cơ bản dưới đây nha Chia component như thế nào cho hiệu quả trong React ### **Container** **HomePage:** Thường tổng thể 1 trang là 1 container Props: N/A State: featuredPostList Render: Header Banner FeaturedPostList: state featuredPostList ### **Components** Header: render header Banner: render banner FeaturedPostList Props: featuredPostList State: N/A Render: a list of post

Context trong React

Context trong React
Hi mọi người hôm nay mình sẽ nói về 1 useContext() hook trong React nha. Context cung cấp phương pháp để chia sẻ những giá trị giữ các component với nhau Mình có cây component sau: App(status: false) -> Header -> Menu -> User -> Profile Mình muốn truyền 1 dât từ App sang component Profile sẽ gặp vấn đề Props Drilling (truyền props thông qua nhiều component) `Context` sẽ giúp mình truyền từ component cha xuống thằng component cháu, chắc luôn mà không cần thông qua các component trung gian nữa hehe **3 bước đơn để tạo context** ``` import {createContext} from "react"; //B1. Tạo context export const StatusContext = createContext(); // export để component con cháu sẽ có thể dùng được // StatusContext trả về 1 Object có Provider và Consumer //B2. Dùng provider cho component cha nhận được dữ liệu để component con có thể sử dụng được // Thằng Provider sẽ bọc component cha ``` Với Provider sẽ có prop là value. Value nhận dữ liệu gì thì toàn bộ các childrent trong Provider đều có thể nhận được value đó Ở component con `Component-Child` ``` import {useContext} from "react"; import {StatusContext} from "nơi export context"; // Để nhận được dữ liệu từ component cha thì có hook useContext() React viết sẵn để nhận data rồi hehe const value = useContext(StatusContext); // value sẽ là giá trị mà ở Provider component cha truyền vào ``` Và tới đây ở component con có data từ component cha truyền qua rồi thì thoải mái dùng thôi, không cần quan tâm từ component cha qua mình có bao nhiêu trung gian nữa hehe.

useState trong React

useState trong React
Tiếp nối bài viết về hook `useEffect()`thì hôm nay mình sẽ nói về hook `useState()` nha useState() cũng là 1 hook cơ bản trong React, nó giúp mình sử dụng được state trong functional component Nó cũng là 1 cái hàm thôi, đầu vào là 1 initialState có thể là giá trị hoặc cũng có thể là 1 function. Và đầu ra là 1 mảng có 2 phần tử tương ứng cho state và setState **Cú pháp:** const [state, setState] = useState(initialState); ### Lưu ý khi dùng useState() chỗ này nghen ``` const [person, setPerson] = useState({ name: "Tu", address: "Da Nang" }); setPerson({ name: "Tu Pham" }); ``` – Mình ví dụ có 1 state person và khi mình setPerson như trên thì giá trị sẽ chỉ còn lại là { name: “Tu Pham” } và nó sẽ replace giá trị trước đó Nên trường hợp này mình nên clone nó ra rồi mới setState thuộc tính mình cần như hình dưới nghen ``` const [person, setPerson] = useState({ name: "Tu", address: "Da Nang" }); setPerson({ ...person, name: "Tu Pham" }); ``` – Inital state chỉ chạy 1 lần đầu tiên các lần render sau coi như vô nghĩa nên nếu giá trị ban đầu inital state xử lý phức tạp thì có thể xử lý như cách dưới đây để chỉ chạy đúng 1 lần đầu thôi nghen :D. ``` const [person, setPerson] = useState(() => { const initPerson = getPerson(); return initPerson }); ``` – Mình sẽ dùng inital state dạng callback function thay vì nó là 1 giá trị. Và useState() sẽ đảm bảo rằng giá trị khởi tạo trong này chỉ chạy đúng 1 lần mà thôi, những lần render sau không render nữa hehe. – Những giá trị khởi tạo state như chuỗi hoặc số thì có thể ghi thẳng trực tiếp còn lại những xử lý tính toán phức tạp thì nên cho vào callback function để tối ưu hơn nha

useEffect trong React

useEffect trong React
Hi mọi người bài này mình sẽ nói về hook useEffect() nha useEffect() là 1 hook trong React hook hỗ trợ cho functional component. Thường được dùng xử lý các vấn đề liên quan đến side-effects. Side effects có thể hiểu nôm na là những thứ mà nó tác động, chạy phía bên ngoài component của mình như Gọi API lấy dữ liệu trên server Tương tác với DOM Subscriptions SetTimeout, setInterVal Chia làm 2 loại effects: Effect không cần clean up: gọi API, tương tác DOM Effect cần clean up: subscriptions, setTimeout, setInterVal **useEffect()** – Gồm 2 phần: side effect và clean up (option) – Được chạy sau mỗi lần render – Được thực thi ít nhất sau 1 lần render đầu tiên – Những lần sau, chỉ được thực thi nếu có có dependencies thay đổi – Effect cleanup sẽ được chạy trước khi run effect lần tiếp theo hoặc unmount Cơ bản useEffect cũng là 1 cái hàm thôi nhận vào 2 tham số callback và dependencies: `useEffect(callback, dependency)` – Mình ví dụ 1 code mẫu ở đây nha ``` // Được chạy sau mỗi lần render useEffect(() => { // Code side-effect ở đây... return () => { // Code clean up ở đây // Sẽ chạy trước khi lần render tiếp theo hoặc unmount } }, []) ``` ### Dùng với dependency thì mình sẽ ví dụ 3 trường hợp ### – Trường hợp 1: Không khai báo dependency ``` useEffect(() => { // Luôn luôn chạy sau mỗi lần render return () => { // Code clean up ở đây // Sẽ chạy trước khi lần render tiếp theo hoặc unmount } }) ``` ### – Trường hợp 2: dependency là empty ``` useEffect(() => { // Chạy đúng 1 lần sau lần render đầu tiên return () => { // Code clean up ở đây // Cũng chạy đúng 1 lần unmount } }, []) ``` ### – Trường hợp 3: dependency có dữ liệu tham số đầu vào ``` useEffect(() => { // Chạy sau lần render đầu tiên // Nhưng lần sau có chạy hay không thì nó sẽ phụ thuộc vào dependency return () => { // Sẽ chạy trước khi lần render tiếp theo hoặc unmount } }, [dependency]) ```

Tìm hiểu Javascript Modules

05/16/2022
Tìm hiểu Javascript Modules
Chào các bạn! Hôm nay mình sẽ tìm hiểu về Module trong javascript là gì nhé. Module có thể hiểu như nó là 1 bộ phận, 1 phần nào đó tập hợp rất là nhiều function, logic trong đó và khi chúng ta muốn sử dụng nó thì chỉ cần gọi nó ra mà thôi **Tại sao chúng ta cần sử dụng nó** Có tính bảo trì vì nó đóng thành 1 gói chia nhỏ nó ra rồi Namespacing, vì trong javascript chúng ta khai báo 1 biến nào đó global thì tất cả mọi nơi đều sử dụng được thì nó xảy 1 cái vấn đề là giả sử function đó mình đặt cái tên trùng với 1 function ở đâu đó thì nó sẽ bị lỗi Có thể tái sử dụng. Có thể đem các module đã viết kế thừa sang dùng những dự án khác Xem ví dụ dưới đây sẽ giúp bạn hiểu hơn những gì nói nhé Tìm hiểu Javascript Modules – Nếu như mình export default thì mình sẽ import theo cách như trên là import name_function from “url file” – Trường hợp mình muốn export nhiều thì mình dùng export name như ví dụ dưới đây Tìm hiểu Javascript Modules Trường hợp mình muốn đổi tên Đổi tên đối với `expoort default` thì mình import tên gì cũng được không thành vấn đề Đổi tên đối với `export name` ví dụ thay vì export myName thì sẽ thành myNameAs như này `export { myName as myNameAs }` và import thì phải là {myNameAs} thì sẽ là okie

Lấy phần tử cuối trong mảng theo cách của bạn

05/09/2022
Lấy phần tử cuối trong mảng theo cách của bạn
Mình ví dụ 1 mảng đơn giản dưới đây và những cách mà lấy phần tử cuối trong mảng bạn có thể tham khảo áp dụng nhé **const arr** = [‘a’, ‘b’, ‘c’, ‘d’]; **Cách 1:** Có thể dùng method pop để xóa phần tử cuối cùng trong mảng thu được phần tử cuối cùng. Hoặc theo cách dưới đây thì destructuring ra là sẽ được kết quả tương tự `const last = [...arr].pop()` **Cách 2:** Cách này có vẻ dễ hiểu hơn khi lấy độ dài của mảng -1 sẽ ra index phần tử cuối cùng `const last = arr[arr.length - 1]` **Cách 3:** Method reverse sẽ đảo ngược vị trí thứ tự các phần tử trong mảng và ta lấy phần tử đầu tiên là okie `arr.reverse()[0]` **Cách 4:** Method slice sẽ tạo ra 1 mảng mới sẽ 2 tham số (vị trí bắt đầu, vị trí kết thúc). Nếu chỉ truyền 1 tham số thì sẽ tạo ra mảng mới từ mảng cũ từ bắt đầu từ vị trí index truyền vào, vị trí end tự hiểu là đến hết mảng. Và truyền 1 tham số và số đó âm thì sẽ tính ngược lại từ phải sang trái. `arr.slice(-1)[0]` **Cách 5:** at là method mới của array, -1 nghĩa là lấy phần tử cuối cùng trong array. Nếu truyền vào 0 là lấy phần tử đầu tiên. `arr.at(-1)`

Bộ phím tắt vscode thần thánh giúp bạn ảo diệu hơn khi dev

05/06/2022
Bộ phím tắt vscode thần thánh giúp bạn ảo diệu hơn khi dev
Thử thách 6 ngày 6 đêm thành thạo các phím tắt trên Visual studio code để dev ảo diệu hơn…Get Gô ?. ▷==PHÍM TẮT CHỈNH SỬA VĂN BẢN==◁ 1. Ctrl + Shift + K: Xóa dòng 2. Ctrl + Enter: Chèn dòng bên dưới 3. Ctrl + Shift + Enter: Chèn dòng trên 4. Ctrl + ⇓: cuộn xuống (đừng động đến chuột mà cuộn nội dung lên xuống bằng phím nhé) 5. Ctrl + ⇑: cuộn lên (đừng động đến chuột mà cuộn nội dung lên xuống bằng phím nhé) 6. Ctrl + Shift + Alt + ⇓: Thêm con trỏ chuột xuống dưới ngay con trỏ hiện tại 7. Ctrl + Shift + Alt + ⇑: Thêm con trỏ chuột lên trên ngay con trỏ hiện tại mẹo: Giữ Alt + con trỏ chuột kích trái vào từng vị trí 8. Shift + Alt + ⇓: Copy nội dung dòng hiện tại xuống dưới 9. Shift + Alt + ⇑: Copy nội dung dòng hiện tại lên trên 10. Ctrl + D: Chọn văn bản giống văn bản bôi đen hiện tại 11. Ctrl + U: Hoàn tác thao tác phần tử chọn cuối cùng 12. Ctrl + Shift + L: Chọn tất cả đoạn văn bản giống hiện tại ( không phân biệt hoa thường ) 13. Ctrl + ]: Đẩy dòng sang phải 14. Ctrl + [: Đẩy dòng sang trái 15. Home: Đi đến đầu dòng 16. End: Đi đến cuối dòng 17. Ctrl + end: Đi đến cuối file 18. Ctrl + home: Chuyển đến đầu file 19. Ctrl + F: Tìm kiến nội dung 20. Ctrl + H: Thay thế nội dung 21. F3: Tìm tiếp theo ▷==PHÍM TẮT KHÁC==◁ 22. Ctrl + z: Quay lại thao tác nội dung trước đó 23. Ctrl + y: Lặp lại thao tác tiếp theo 24. Ctrl + [cách]: Gợi ý khi code các ngôn ngữ 25. Ctrl + w: Đóng tab hiện tại 26. Ctrl + [cộng,trừ]: To nhỏ font chữ khi code ▷==PHÍM HAY SỬ DỤNG==◁ 1. Ctrl + [cách]: Gợi ý khi code các ngôn ngữ 2. Ctrl + /: Comment code 3. Ctrl + z: Quay lại thao tác nội dung trước đó 4. Ctrl + Y: Lặp lại thao tác tiếp theo 5. Shift + Alt + ⇓: Copy nội dung dòng hiện tại xuống dưới 6. Shift + Alt + ⇑: Copy nội dung dòng hiện tại lên trên 7. Ctrl + ]: Đẩy dòng sang phải 8. Ctrl + [: Đẩy dòng sang trái 9. Ctrl + D: Chọn văn bản giống văn bản bôi đen hiện tại 10. Ctrl + Shift + L: Chọn tất cả đoạn văn bản giống hiện tại ( không phân biệt hoa thường ) 11. Ctrl + F: tìm kiến nội dung 12. Ctrl + w: Đóng tab hiện tại 13. Ctrl + [cộng,trừ]: To nhỏ font chữ khi code Hy vọng bài viết này sẽ giúp các bạn thao tác trên vscode xịn hơn, cầm chuột ít hơn ? khi dev là good chóp rồi hehe

Những cách làm center khối thường dùng nhất

05/03/2022
Những cách làm center khối thường dùng nhất
Hôm nay mình sẽ giới thiệu cho các bạn những cách căn giữa khối thường dùng nhất hiện nay, tùy trường hợp các bạn tham khảo áp dụng nhé. Mình có đoạn html nhỏ mô tả vấn đề để căn giữa 1 phần tử khối bên trong như sau Những cách làm center khối thường dùng nhất Bây giờ để cho khối có class là box-wrapper căn giữa màn hình thì chỉ cần cho nó có thuộc tính `margin: 0 auto` thì nó sẽ tự chia độ rộng 2 bên còn trống ra đều nhau và thế là căn giữa rồi á :v Những cách làm center khối thường dùng nhất Bây giờ mình muốn khối có class box căn giữa khối bao quanh nó thì mình cũng có thể dùng `margin: 0 auto` tiếp luôn hehe, nhưng phải đảm bảo là width nó phải nhỏ hơn thằng cha chứa nó nha. Rồi vấn đề chính là mình muốn khối có class box-center canh giữa khối cha có class box thì sao… à thì cũng dùng `margin: 0 auto` luôn :))). Kết quả hiện tại nè Những cách làm center khối thường dùng nhất À khoan dừng lại khoảng chừng 2s :v, nãy giờ toàn `margin: 0 auto` á =)). Để canh giữa nội dung ra giữa thì cho `text-align: center` ở khối có class box-center thôi là okie. Nếu trường hợp khối box-center kia là các tag inline hoặc là inline-block thì muốn cho ra giữa thì cho khối cha nó có class box thuộc tính `text-align: center` là được nha. Bây giờ mình muốn canh giữa chiều ngang lẫn chiều chiều luôn thì mình sẽ dùng position nhé Mình sẽ cho khối ngoài có class là box sẽ cố định bằng thuộc tính `position: relative` và khối con bên trong box-center chạy theo khối cha bằng thuộc tính position: absolute theo như đoạn code bên dưới nhé. Những cách làm center khối thường dùng nhất Mình sẽ set cho left: 50% có nghĩa là nó sẽ đẩy xuống 50% chiều cao của khối cha chứa nó và left: 50% thì nó sẽ tịnh tiến sang phải 50% so với chiều rộng của khối cha. Tiếp theo mình sẽ dịch ngược lên trên và sang trái 1 nữa chiều rộng và chiều cao của chính nó với thuộc tính transform như hình trên là xong rồi nè Và cách còn lại này đơn giản hơn nữa khi chỉ cần style cho khối chứa ngoài nó là khối trong tự di chuyển theo cả chiều ngang lẫn dọc với flexbox, align-item và justify-content mặc định sẽ căn theo chiều dọc và chiều ngang của phần tử cha Những cách làm center khối thường dùng nhất – Cách cuối dùng này có lẽ sẽ ngắn gọn nhất luôn cho các ae đây hehe `display:grid; place-items: center` Và đây là kết quả minh họa từ nãy giờ các bạn có thể test thực tế nha. See the Pen [ Untitled](https://codepen.io/phm-vn-t/pen/KKyQxJL) by Phạm Văn Tú ([@phm-vn-t](https://codepen.io/phm-vn-t)) on [CodePen](https://codepen.io). Vẫn còn 1 vài cách nữa nhưng mình nghĩ trên đây đủ để mình style hầu hết các trường hợp các bạn gặp rồi nè. Hy vọng sẽ giúp ích được cho các bạn nhé

Hướng dẫn tùy biến scrollbar trong css

05/03/2022
Hướng dẫn tùy biến scrollbar trong css
Trong bài viết này mình sẽ hướng dẫn cho mọi người cách tùy biến scrollbar nhé. À nó chỉ có chạy ngon trên chrome, safari kể cả edge và coccoc luôn còn firefox thì không hỗ trợ nha. Đầu tiên là thẻ chúng ta muốn dùng để áp dụng, như hình dưới mình set cho thẻ body nhé. Thứ hai là ta set cho độ rộng của thanh scrollbar là bao nhiêu, ở đây ta mình đang áp dụng cho body nên selector mình sẽ là `body::-webkit-scrol` nếu các bạn muốn áp dụng cho những thẻ khác thì chỉ cần thay thẻ body bằng thẻ tương ứng là được nhé. Hướng dẫn tùy biến scrollbar trong css Để set style cho thanh bar nền ở dưới thì mình dùng `body::-webkit-scrollbar-track` Hướng dẫn tùy biến scrollbar trong css Và cuối cùng để style cái mà chúng ta kéo lên xuống thì dùng `body::-webkit-scrollbar-thumb` là xong rồi nè. Hướng dẫn tùy biến scrollbar trong css Chúng ta có thể set thêm border-radius cho thanh scroll cũng như màu nền gradient cho bắt mắt trông xịn hơn hehe. Và đây là kết quả nè See the Pen [ Untitled](https://codepen.io/phm-vn-t/pen/oNoppbY) by Phạm Văn Tú ([@phm-vn-t](https://codepen.io/phm-vn-t)) on [CodePen](https://codepen.io). Hy vọng qua bài viết này sẽ giúp cho các bạn phần nào đó hiểu và áp dụng được cách style tùy biến scrollbar nhé.

Xử lý hình nền phức tạp với clip-path

05/03/2022
Xử lý hình nền phức tạp với clip-path
Hôm nay mình sẽ giới thiệu cho các bạn thuộc tính clip path nhé. Nó sẽ giúp chúng ta trong việc cắt hình ảnh phức tạp. Ví dụ như hình ảnh dưới đây, thay vì mình dùng hình thì mình sẽ sử dụng clip-path nhé. Xử lý hình nền phức tạp với clip-path Các số trên hình mô tả tọa độ các điểm tương ứng. Nó sẽ hoạt động theo trục tọa độ và các điểm nối lại với nhau tạo ra hình mà mình cần, mình tưởng tượng trục x là chiều ngang, trục y là chiều dọc thì các bạn think xíu là ra ngay tọa độ trên thôi nè. Thuộc tính này khó ở cách hiểu chút thôi, còn lại mình bê nguyên các tọa độ đó vào trong hàm polygon như hình dưới là xong rồi. Xử lý hình nền phức tạp với clip-path Bạn có thể test trên kết quả mình đã làm ví dụ dưới để hiểu hơn về cách hoạt động của clip-path nhé See the Pen [ Untitled](https://codepen.io/phm-vn-t/pen/vYWREbe) by Phạm Văn Tú ([@phm-vn-t](https://codepen.io/phm-vn-t)) on [CodePen](https://codepen.io). Đến đây mình nghĩ các bạn cũng hiểu được phần nào về cách hoạt động của clip-path rồi, sau này mình dùng những trang có sẵn như [clippy](https://bennettfeely.com/clippy/) thì ta hiểu cách hoạt động cũng như những thông số bên trong hàm polygon rồi thì mình dễ dàng tùy biến theo ý của mình gòi :v. Hy vọng qua bài viết này sẽ giúp ae trong việc làm những hình phức tạp trong design dễ dàng hơn thay vì dùng hình trong design nha hehe

Vẽ vời chút với box-shadow

05/03/2022
Vẽ vời chút với box-shadow
Hôm nay mình sẽ chia sẻ cho các bạn 1 chút về thuộc tính box-shadow nâng cao nha. Để dễ hình dung thì mình nhắc lại thuộc tính này tí nhé nó sẽ có 4 các giá trị như sau `box-shadow: x y scale blur color`. Tương ứng giá trị x sẽ là trục ngang, khi các bạn muốn tạo bóng về phía bên phải thì các bạn cho số dương, tương tự như giá trị y sẽ tạo bóng về phía dưới nếu cho giá trị dương ngược lại sẽ đổ bóng lên trên, scale mặc định sẽ bằng với khối chúng ta đang set luôn, blur là độ mờ của bóng, còn color thì không nói các bạn cũng hiểu là màu của bóng rồi hen. Ví dụ mình có 1 hình như dưới đây, có thể các bạn sẽ nghĩ tạo các thẻ div rồi chia layout…để được như vậy, ở đây mình dùng box-shadow để các bạn hiểu sâu hơn về thuộc tính này nhé Vẽ vời chút với box-shadow Còn đây là đoạn code shadow để cho ra được như hình trên nè Vẽ vời chút với box-shadow Thực ra nhìn cái box-shadow dài thế thôi chứ tóm lại cũng chỉ là các giá trị quen thuộc cả, nhưng ở đây nó kết hợp lại thôi. Các bạn chỉ cần hiểu 1 cái box đầu tiên là sẽ hình dung ra liền hehe. Mình muốn mỗi box sẽ cách nhau 10px nên box đầu tiên mình sẽ set cho nó `110px 0 0 0 yellow` sẽ dời sang trục x 1 khoảng 110px và có màu vàng các thuộc tính mờ hay scale mình để mặc định nhé Box thứ 2 sẽ cách ra 220px có nghĩa là sẽ cách cục box chính cộng thêm box shadow mình vừa mới tạo và 20px cho 2 khoảng cách nữa đó hehe, hơi khó hiểu tí nhưng mà tí các bạn copy code chạy sửa lại thông số là hiểu ngay thôi Đến đây chắc các bạn cũng đã nắm được cách dùng nhiều thuộc tính box-shadow chung với nhau cũng như cách nó hoạt động rồi hen, cop code ở dưới demo cho nó đỡ dài dòng =)) See the Pen [ box-shadow](https://codepen.io/phm-vn-t/pen/LYOJgVv) by Phạm Văn Tú ([@phm-vn-t](https://codepen.io/phm-vn-t)) on [CodePen](https://codepen.io).

Sự khác nhau giữa 3 thuộc tính opacity: 0, display:none, visibility:hidden

05/03/2022
Sự khác nhau giữa 3 thuộc tính opacity: 0, display:none, visibility:hidden
Trong bài viết này mình sẽ giúp các bạn phân biệt 3 thuộc tính opacity: 0, display:none, visibility:hidden để dùng đúng cũng như đỡ gặp bug nhé 😀 Đầu tiên mình đi qua thuộc tính `opacity` trước nha. Nó sẽ chạy từ 0 đến 1, giá trị 1 là bình thường còn 0 là không thấy gì cả nhưng nó vẫn ở đó và chiếm diện tích và có thể nhấn vào được bình thường nha, bạn có thể thử hover vào thấy hình con trỏ chuột ngay Tiếp theo `visibility:hidden` thì nó vẫn chiếm diện tích nhưng không thể nhấn vào được nên hover vào không có con trỏ gì nữa hết Cuối cùng là `display:none` thì nó biến mất hoàn toàn khỏi trang luôn, không chiếm diện tích cũng như không thể nhấn vô được nữa Thường 2 thuộc tính opacity và visibility sẽ đi chung với nhau để làm hiệu ứng với kết hợp với thuộc tính `transition` mượt hơn kiểu nhấn vào hiện ra như menu chẳng hạn. Còn display không hỗ trợ với transition nên đôi khi muốn hiển thị nhanh gọn thì có thể dùng `display:none` với `display: block` luôn Hy vọng với sự so sánh ngắn gọn này sẽ giúp cho các bạn hiểu nên dùng thuộc tính nào để ẩn hiện với transition mượt mà hơn mà không phải hỏi vì sao lại Giật Giật nữa nhé hehe

Lặp các phần tử dễ dàng với array.fill()

05/03/2022
Lặp các phần tử dễ dàng với array.fill()
Đôi khi các bạn muốn tạo nhiều phần tử giống nhau, có thể các bạn tạo 1 mảng rồi lặp hoặc là copy ra hoặc…thì `array.fill()` sẽ giúp bạn tiện hơn nhé Lặp các phần tử dễ dàng với array.fill() Mình muốn tạo 9 phần tử thì mình cho `Array(9)` các bạn muốn lặp bao nhiêu phẩn từ bên trong thì thay số tương ứng nhé. Hàm fill sẽ thay đổi giá trị tất cả các phần tử của một mảng thành một giá trị mình truyền vào, nếu không truyền gì thì mặc định các phần tử trong mảng là `undefined`nhé. Và cuối cùng mình dùng map hoặc các hàm lặp tương ứng nhé để lặp các phần tử mình muốn lặp chẳng hạn như mình có có các component giống nhau chẳng hạn thì việc dùng như này sẽ giúp code của bạn clean hơn. Hy vọng qua bài viết này sẽ giúp ích cho các bạn trong lúc làm việc thực tế nhé 😀
hero