JavaScript là một cách tuyệt vời để tạo ứng dụng trên hầu hết mọi nền tảng. TypeScript là một cách để làm cho JavaScript trở nên tốt hơn. Nó giúp đảm bảo rằng mã bạn viết là chính xác và nó bổ sung một số tính năng bổ sung mà JavaScript chưa có.
Trang trí là gì?
Trang trí là một mẫu trong lập trình cho phép bạn bọc thứ gì đó để thay đổi hành vi của nó. Nó không phải là một điều mới – nhiều ngôn ngữ lập trình như Python, Java và C# có nó. JavaScript đã đề xuất tính năng này, nhưng tính năng trang trí của TypeScript thì khác vì đây là ngôn ngữ được nhập mạnh, vì vậy bạn có thể truy cập thông tin bổ sung để thực hiện những nội dung thú vị như xác nhận kiểu thời gian chạy và nội xạ phụ thuộc.
Các loại trang trí
Trình trang trí giống như các nhãn đặc biệt mà bạn có thể đặt trên các lớp và các phần của chúng, chẳng hạn như các phương thức và thuộc tính. Dưới đây là một số ví dụ về những gì họ trông giống như.
Trang trí lớp học
Khi bạn thêm một tính năng đặc biệt vào một lớp, điều đầu tiên bạn nhận được là hàm tạo của lớp.
1 2 3 4 5 6 7 | <span class="token keyword">const</span> <span class="token function-variable function">classDecorator</span> <span class="token operator">=</span> <span class="token punctuation">(</span> target <span class="token operator">:</span> <span class="token builtin">Function</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">// do something with your class</span> <span class="token punctuation">}</span> <span class="token decorator"><span class="token at operator">@</span> <span class="token function">classDecorator</span></span> <span class="token keyword">class</span> <span class="token class-name">Rocket</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> |
Nếu bạn muốn thay đổi điều gì đó về lớp, bạn có thể tạo một lớp mới dựa trên lớp cũ, rồi thay đổi những phần bạn muốn cho khác đi.
1 2 3 4 5 6 7 8 9 | <span class="token keyword">const</span> <span class="token function-variable function">addFuelToRocket</span> <span class="token operator">=</span> <span class="token punctuation">(</span> target <span class="token operator">:</span> <span class="token builtin">Function</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">class</span> <span class="token class-name"><span class="token keyword">extends</span></span> target <span class="token punctuation">{</span> fuel <span class="token operator">=</span> <span class="token number">100</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token decorator"><span class="token at operator">@</span> <span class="token function">addFuelToRocket</span></span> <span class="token keyword">class</span> <span class="token class-name">Rocket</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> |
Lớp Rocket
của bạn hiện có thuộc tính fuel
bắt đầu bằng giá trị 100.
1 2 3 | <span class="token keyword">const</span> rocket <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Rocket</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token builtin">console</span> <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> rocket <span class="token punctuation">)</span> <span class="token punctuation">.</span> fuel <span class="token punctuation">)</span> <span class="token comment">// 100</span> |
phương pháp trang trí
Khi bạn sử dụng một trình trang trí, bạn có thể đính kèm nó vào một phương thức của lớp. Điều này có nghĩa là khi bạn sử dụng phương thức này, bạn sẽ nhận được ba phần thông tin: target
, propertyKey
và descriptor
.
1 2 3 4 5 6 7 8 9 10 11 | <span class="token keyword">const</span> <span class="token function-variable function">myDecorator</span> <span class="token operator">=</span> <span class="token punctuation">(</span> target <span class="token operator">:</span> Object <span class="token punctuation">,</span> propertyKey <span class="token operator">:</span> <span class="token builtin">string</span> <span class="token punctuation">,</span> descriptor <span class="token operator">:</span> PropertyDescriptor <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">// do something with your method</span> <span class="token punctuation">}</span> <span class="token keyword">class</span> <span class="token class-name">Rocket</span> <span class="token punctuation">{</span> <span class="token decorator"><span class="token at operator">@</span> <span class="token function">myDecorator</span></span> <span class="token function">launch</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token builtin">console</span> <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">"Launching rocket in 3... 2... 1... 🚀"</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Lớp Rocket
có một cách đặc biệt để thay đổi cách hoạt động của một phương thức. Bạn có thể đặt tên cho nó và một số hướng dẫn về cách thức hoạt động của nó. Điều này có thể giúp bạn làm cho phương thức làm được nhiều việc hơn bình thường.
trang trí tài sản
Trình trang trí phương thức và trình trang trí tham số giống nhau ở chỗ cả hai đều cung cấp cho bạn hai thứ: target
và propertyKey
. Sự khác biệt duy nhất là trình trang trí tham số không cung cấp cho bạn bộ mô tả thuộc tính.
1 2 3 4 | <span class="token keyword">const</span> <span class="token function-variable function">propertyDecorator</span> <span class="token operator">=</span> <span class="token punctuation">(</span> <span class="token parameter">target <span class="token operator">:</span> Object <span class="token punctuation">,</span> propertyKey <span class="token operator">:</span> string</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">// do something with your property</span> <span class="token punctuation">}</span> |
Nếu bạn muốn tìm hiểu thêm về trình trang trí trong TypeScript, bạn có thể tra cứu nó trong tài liệu TypeScript .
Các trường hợp sử dụng cho trình trang trí TypeScript
Bây giờ chúng ta đã biết decorator là gì và cách sử dụng chúng, hãy xem cách chúng có thể giúp chúng ta thực hiện một số tác vụ nhất định.
Tính toán thời gian thực hiện
Nếu bạn muốn biết ứng dụng của mình đang chạy nhanh như thế nào, bạn có thể tạo một thứ gọi là trình trang trí để đo thời gian cần thiết để một chức năng chạy và sau đó hiển thị cho bạn thời gian trên màn hình.
1 2 3 4 5 6 7 | <span class="token keyword">class</span> <span class="token class-name">Rocket</span> <span class="token punctuation">{</span> <span class="token decorator"><span class="token at operator">@</span> <span class="token function">measure</span></span> <span class="token function">launch</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token builtin">console</span> <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">"Launching in 3... 2... 1... 🚀"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Lớp Rocket
có một cách đặc biệt để khởi động nó. Để biết mất bao lâu để khởi động Rocket, bạn có thể sử dụng công cụ trang trí measure
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <span class="token keyword">import</span> <span class="token punctuation">{</span> performance <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"perf_hooks"</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function">measure</span> <span class="token operator">=</span> <span class="token punctuation">(</span> target <span class="token operator">:</span> Object <span class="token punctuation">,</span> propertyKey <span class="token operator">:</span> <span class="token builtin">string</span> <span class="token punctuation">,</span> descriptor <span class="token operator">:</span> PropertyDescriptor <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> originalMethod <span class="token operator">=</span> descriptor <span class="token punctuation">.</span> value <span class="token punctuation">;</span> descriptor <span class="token punctuation">.</span> <span class="token function-variable function">value</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token operator">...</span> args <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">const</span> start <span class="token operator">=</span> performance <span class="token punctuation">.</span> <span class="token function">now</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> result <span class="token operator">=</span> <span class="token function">originalMethod</span> <span class="token punctuation">.</span> <span class="token function">apply</span> <span class="token punctuation">(</span> <span class="token keyword">this</span> <span class="token punctuation">,</span> args <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> finish <span class="token operator">=</span> performance <span class="token punctuation">.</span> <span class="token function">now</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token builtin">console</span> <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token template-string"><span class="token template-punctuation string">`</span> <span class="token string">Execution time: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span> finish <span class="token operator">-</span> start <span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> milliseconds</span> <span class="token template-punctuation string">`</span></span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">return</span> result <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> <span class="token keyword">return</span> descriptor <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> |
Chúng ta sẽ sử dụng một thứ gọi là Performance Hooks API từ thư viện tiêu chuẩn Node.js để đo thời gian cần thiết để khởi chạy Rocket
. Chúng tôi sẽ tạo một Rocket
mới và sau đó gọi phương thức launch
. Công cụ trang trí measure
sẽ thay thế phương thức khởi chạy ban đầu bằng một phương thức mới sẽ đo thời gian cần thiết để khởi chạy Tên lửa và sau đó ghi lại thời gian vào bảng điều khiển.
1 2 3 | <span class="token keyword">const</span> rocket <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Rocket</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> rocket <span class="token punctuation">.</span> <span class="token function">launch</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
Bạn sẽ nhận được kết quả như sau.
1 2 3 | Launching <span class="token keyword">in</span> <span class="token number">3.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token number">2.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token number">1.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> 🚀 Execution time <span class="token operator">:</span> <span class="token number">1.0407989993691444</span> milliseconds |
nhà máy trang trí
Nhà máy trang trí là một cách để làm cho đồ trang trí của bạn làm những việc khác nhau trong các tình huống khác nhau. Nó giống như một nhà máy sản xuất đồ trang trí, nhưng bạn có thể hướng dẫn nó để đồ trang trí làm những việc khác nhau. Ví dụ: bạn có thể yêu cầu nhà máy trang trí theo một cách nhất định hoặc làm điều gì đó đặc biệt.
1 2 3 4 | <span class="token keyword">const</span> <span class="token function-variable function">changeValue</span> <span class="token operator">=</span> <span class="token punctuation">(</span> value <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">(</span> target <span class="token operator">:</span> Object <span class="token punctuation">,</span> propertyKey <span class="token operator">:</span> <span class="token builtin">string</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> Object <span class="token punctuation">.</span> <span class="token function">defineProperty</span> <span class="token punctuation">(</span> target <span class="token punctuation">,</span> propertyKey <span class="token punctuation">,</span> <span class="token punctuation">{</span> value <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> |
Hàm changeValue
tạo ra một thứ đặc biệt được gọi là trình trang trí. Trình trang trí này thay đổi giá trị của thứ gì đó dựa trên những gì bạn yêu cầu nó thực hiện từ nhà máy của bạn.
1 2 3 4 5 6 7 8 | <span class="token keyword">class</span> <span class="token class-name">Rocket</span> <span class="token punctuation">{</span> <span class="token decorator"><span class="token at operator">@</span> <span class="token function">changeValue</span></span> <span class="token punctuation">(</span> <span class="token number">100</span> <span class="token punctuation">)</span> fuel <span class="token operator">=</span> <span class="token number">50</span> <span class="token punctuation">}</span> <span class="token keyword">const</span> rocket <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Rocket</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token builtin">console</span> <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> rocket <span class="token punctuation">.</span> fuel <span class="token punctuation">)</span> <span class="token comment">// 100</span> |
Nếu bạn kết nối nhà máy trang trí với nhiên liệu, lượng nhiên liệu sẽ là 100.
Bảo vệ lỗi tự động
Hãy sử dụng những gì chúng ta đã học để tìm ra cách giải quyết vấn đề trong thế giới thực.
1 2 3 4 5 6 7 8 | <span class="token keyword">class</span> <span class="token class-name">Rocket</span> <span class="token punctuation">{</span> fuel <span class="token operator">=</span> <span class="token number">50</span> <span class="token punctuation">;</span> <span class="token function">launchToMars</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token builtin">console</span> <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">"Launching to Mars in 3... 2... 1... 🚀"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Nếu bạn có một loại tàu vũ trụ đặc biệt tên là Rocket, nó cần có đủ nhiên liệu để đến sao Hỏa. Chúng ta có thể tạo ra một thứ đặc biệt gọi là thiết bị trang trí để đảm bảo Tên lửa có đủ nhiên liệu trước khi nó cất cánh.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <span class="token keyword">const</span> <span class="token function-variable function">minimumFuel</span> <span class="token operator">=</span> <span class="token punctuation">(</span> fuel <span class="token operator">:</span> <span class="token builtin">number</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">(</span> target <span class="token operator">:</span> Object <span class="token punctuation">,</span> propertyKey <span class="token operator">:</span> <span class="token builtin">string</span> <span class="token punctuation">,</span> descriptor <span class="token operator">:</span> PropertyDescriptor <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> originalMethod <span class="token operator">=</span> descriptor <span class="token punctuation">.</span> value <span class="token punctuation">;</span> descriptor <span class="token punctuation">.</span> <span class="token function-variable function">value</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span> <span class="token operator">...</span> args <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> fuel <span class="token operator">></span> fuel <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">originalMethod</span> <span class="token punctuation">.</span> <span class="token function">apply</span> <span class="token punctuation">(</span> <span class="token keyword">this</span> <span class="token punctuation">,</span> args <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token builtin">console</span> <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">"Not enough fuel!"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> <span class="token keyword">return</span> descriptor <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> |
minimumFuel
giống như một công cụ đặc biệt giúp bạn kiểm tra lượng fuel
cần thiết để phóng tên lửa. Bạn có thể sử dụng nó để đảm bảo tên lửa có đủ nhiên liệu trước khi cất cánh.
1 2 3 4 5 6 7 8 9 | <span class="token keyword">class</span> <span class="token class-name">Rocket</span> <span class="token punctuation">{</span> fuel <span class="token operator">=</span> <span class="token number">50</span> <span class="token punctuation">;</span> <span class="token decorator"><span class="token at operator">@</span> <span class="token function">minimumFuel</span></span> <span class="token punctuation">(</span> <span class="token number">100</span> <span class="token punctuation">)</span> <span class="token function">launchToMars</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token builtin">console</span> <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">"Launching to Mars in 3... 2... 1... 🚀"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Nếu bạn cố gắng phóng tên lửa lên sao Hỏa, nó sẽ không hoạt động vì nó không có đủ nhiên liệu.
1 2 3 4 5 | <span class="token keyword">const</span> rocket <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Rocket</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> rocket <span class="token punctuation">.</span> <span class="token function">launchToMars</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> Not enough fuel <span class="token operator">!</span> |
Điều này có nghĩa là bạn có thể sử dụng cùng một đoạn mã để tạo một phương thức mới nhưng chỉ cần thay đổi số mà bạn đang kiểm tra. Vì vậy, nếu bạn muốn thực hiện một phương pháp mới để phóng tên lửa lên mặt trăng, bạn có thể sử dụng cùng một mã nhưng chỉ cần thay đổi số bạn đang kiểm tra từ 25 sang một số khác.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <span class="token keyword">class</span> <span class="token class-name">Rocket</span> <span class="token punctuation">{</span> fuel <span class="token operator">=</span> <span class="token number">50</span> <span class="token punctuation">;</span> <span class="token decorator"><span class="token at operator">@</span> <span class="token function">minimumFuel</span></span> <span class="token punctuation">(</span> <span class="token number">100</span> <span class="token punctuation">)</span> <span class="token function">launchToMars</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token builtin">console</span> <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">"Launching to Mars in 3... 2... 1... 🚀"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token decorator"><span class="token at operator">@</span> <span class="token function">minimumFuel</span></span> <span class="token punctuation">(</span> <span class="token number">25</span> <span class="token punctuation">)</span> <span class="token function">launchToMoon</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token builtin">console</span> <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token string">"Launching to Moon in 3... 2... 1... 🚀"</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Bây giờ, tên lửa này có thể được phóng lên mặt trăng.
1 2 3 4 5 | <span class="token keyword">const</span> rocket <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Rocket</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> rocket <span class="token punctuation">.</span> <span class="token function">launchToMoon</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> Launching to Moon <span class="token keyword">in</span> <span class="token number">3.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token number">2.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> <span class="token number">1.</span> <span class="token punctuation">.</span> <span class="token punctuation">.</span> 🚀 |
Loại trang trí này có thể giúp bạn quyết định xem ai đó có được phép xem thông tin đặc biệt hay không. Nó có thể giúp bạn đảm bảo rằng chỉ những người phù hợp mới có thể nhìn thấy nó.
Phần kết luận
Đôi khi bạn không cần phải tự trang trí. Hiện đã có các thư viện và khung như TypeORM và Angular có tất cả các trang trí mà bạn cần. Nhưng bạn vẫn nên hiểu những gì đang xảy ra đằng sau hậu trường. Nó thậm chí có thể cung cấp cho bạn những ý tưởng để tạo khung TypeScript của riêng bạn.
Và cuối cùng
Như mọi khi, tôi hy vọng bạn thích bài viết này và học được điều gì đó mới. Xin cảm ơn và hẹn gặp lại các bạn trong những bài viết tiếp theo!
Nếu các bạn thích bài viết này thì hãy cho mình 1 like và subscribe để ủng hộ mình nhé. Cảm ơn. 😊