+4

Điểm nhấn của AngularJS-P2

Hi cả nhà, Trong bài viết trước, mình đã có một số giới thiệu một số điểm nhấn trong AnggularJS, hôm nay mình xin tiếp tục với loạt bài đăng cùng chủ đề ni. Mình không lằng nhằng nữa nhé, đi thẳng vô vấn đề luôn, mời mọi người chén 😄 😄

4. Directives

HTMl là một ngôn ngữ lập trình ngon, đang tuyệt đối phổ biến với Web Development, nhưng nó lại có những nhược điểm lớn là buộc người lập trình phải tuân thủ theo cú pháp của nó. Ví dụ như các element hay chi chi đó thì người lập trình bắt buộc phải tuân thủ đúng theo của pháp của hắn như <button></button>,.

... phải đúng với từng mục đích cụ thể. Nhưng trong Angular, vấn đề này được giải quyết thông qua một kỹ thuật rất hay gọi là Directives. Có nghĩa là Directives cho phép anh em chũng ta mở rộng ngôn ngữ HTLM, chỉ cho HTML các cấu trúc mới của DOM. Nhìn vào các thí dụ trên chúng ta thấy rằng có nhiều attribute không thuộc HTML trước đây như là “ng-model”, “ng-repeat”, “ng-controller”. Đó chính là các Directive có sẵn và AngularJS hỗ trợ cho người lập trình tạo ra các Directives tương tự như thế. Bốn loại trong cấu trúc DOM mà người lập trình can thiệp vào đó là: E = element , A = attribute, C = class, M = comment. Mỗi cách định nghĩa trên tương ứng với cách gọi trong HTML như là <save-Order></save-Order>
,
, <!-- directive: save Order -->. Ví dụ dưới đây tạo ra một Directive button: Ví dụ 5: Directive hiển thị giỏ hàng Directives.JS

// Directive cartItems: hiển thị giỏ hàng
directive('cartItems', function () {
    return {
        replace: true, restrict: 'EA',
        templateUrl: 'SelectedCart.html'
    };});

Cách gọi Directive trên View

<body ng-controller="OrderController">
   <div id="main">
      <div><cart_Items></cart_Items></div>
   </div>
</body>

SelectedCart.html

<div><img src="..\\Images/cart.png" alt="Items: "/>                 
 <span>( {{selectedItems.length}} )</span></div>

Trong file Directives.JS, định nghĩa một directive mới “cartItems” với từ khóa “restrict: 'EA'” nên nó vừa là Element vừa là Attribute. “templateUrl” chỉ đến file HTML template là nội dung của Directive. Mục đích của directive này là hiển thị hình giỏ xe hàng và số lượng hàng hóa đang được chọn nên nội dung của template 'SelectedCart.html' là các syntax hiển thị hình ảnh và số lượng item được chọn. View chỉ gọi tên directive này

<cart_Items></cart_Items>
để hiển thị giỏ hàng. Directive rất hay bởi vì ngoài cách viết code theo kiểu khai báo làm cho mã code rất dễ đọc, nó còn cho phép người thiết kế có thể thiết kế các trang web mà không cần phải biết code và quan trọng là các directive này hoàn toàn độc lập nên có thể sử dụng lại cho dự án khác hay chia sẽ cho cộng đồng. Khi xây dựng Directive cần chú ý là không nên sử dụng tiếp đầu ngữ là “ng-” đặt tên cho custom Directive mới gì nó sẽ gây nhầm lẫn với các Directive của AngularJS và cách đặt tên phải theo chuẩn camel-cased. Thí dụ Directive “cartItems”, trong HTML, chúng ta phải thêm ký tự “-“ vào thành “cart_Items”.

5. HTML Template

Trong thí dụ 5, AngularJS sử dụng một html template 'SelectedCart.html' để hiển thị nôi dung trên View. Html template giúp cho người lập trình giải quyết những yêu cầu về UI “động” rất nhanh như trên cùng một tập dữ liệu, nếu là nhà quản lý, thì dữ liệu sẽ hiển thị đầy đủ nhưng nếu nhân viên thì dữ liệu hiển thị sẽ ít hơn. Hay cũng trên 1 tập dữ liệu, nếu mặt hàng là TV thì phải hiển thị cột “Mô tả” là một file video, nhưng các hàng khác chỉ hiển thị là text. Cách đơn giản nhất có lẽ là sử dụng 3 Directive “ng-repeat”, “ng-switch on” và “ng-switch-when” có cấu trúc như là vòng lập “for … switch .. case” để gọi đúng template ứng với giá tri của Model.

Ví dụ 6 - dynamic template:

<div ng-repeat="item in items">
    <div ng-switch on="item.name">
         <div ng-switch-when="TV" >
             <div template_Video div>
         </div>
         <div ng-switch-when="Laptop">
             <div template_Text</div>
</div></div></div>

6. Dependency Injection (DI)

Đây có lẽ là kỹ thuật hay nhất của AngularJS. DI là một design pattern, có thể hiểu đơn giản cách làm giảm sự phụ thuộc giữa các object khi xây ứng dụng. Nếu thiết kế một object A phụ thuộc vào nhiều object khác thì dẫn tới object A sẽ khó được quản lý cũng như khó Unit test. Thường mỗi dòng lệnh có thể phụ thuộc vào một object hay một library. Giả sử Object A sử dụng Object B thì Object B có thể khai báo là global, hay sử dụng “new” trong Object A để tạo new instance của Object B. Như thế, giữ Object A và Object B luôn luôn có sự liên kết lẫn nhau. Cách thứ 3 là gắn (inject) Object B tới Object A ở khi cần thiết ở run time. Đó là cách mà AngularJS hướng tới để giải quyết vấn đề giảm sự phụ thuộc giữa các Object. Xem thí dụ đơn giản dưới đây để hiểu về AngularJS.

Ví dụ 7 -custom DI:

Service.JS

module.service('OrderService', function () {
    var Orders = [{
        id: 0,'name': 'TV','price': 1000,        
        'quantity': '1', image: "\\Images\\tv.jpg"
    }];
    //save new order
    this.save = function (order) {}
    }});

Controller

var module = angular.module('Online', []);
module.controller('OrderController', function ($scope, OrderService) {
    // Save Order
    $scope.saveOrder = function () {
        OrderService.save($scope.newOrder);
    }})

File “OrderService” bao gồm các hàm business logic “save”, “delete”... Controller “OrderController” sử dụng “OrderService” nhưng không có bất cứ biến toàn cục hay từ khóa “new” ở “OrderController” . Khi UI gọi hàm "SaveOrder” của “OrderController”, AngularJS sẽ tự động gắn “OrderService” vào “OrderController”. Do AngularJS quản lý theo tên, nên gì một lý do nào đó, controller không sử dụng “OrderService” mà chuyển sang một service khác, thì người lập trình chỉ đổi tên mà thôi. Giả sử ứng dụng đang trên Production bị lỗi một hàm nào đó, người lập trình viết một service mới cho mục đích tìm lỗi. Khi tìm lỗi hoàn tất, chúng ta trả đúng lại tên cũ. Ưu điểm của DI là khi thiết kế, người lập trình chia nhỏ các business logic từ phức tạp thành nhiều phần đơn giản. Càng chia nhỏ, code càng dể quản lý và sẽ giúp cho việc thự hiện Unit test trở nên thuận lợi hơn rất nhiều.

7. Unit Test

Unit test JavaScript là công việc vô cùng phức tạp và mất nhiều thời gian. Nếu các hàm JavaScript phụ thuộc lẫn nhau càng nhiều thì việc Unit test càng khó. AngularJS xây dựng trên ý tưởng DI và làm giảm sự phụ thuộc giữa các component, tách riêng logic và view cho nên thực hiện unit test rất thuận lợi. Tất cả ví dụ trên về filter, directives, controller, DI là những file riêng biệt cho nên người lập trình dễ dàng viết các Unit test cho từng loại như là NUnit của .Net. Hiện nay Jasmine là một công cụ rất hay để thực hiện unit test JavaScript. Sử dụng Jasmine rất đơn giản, chỉ cần download jasmine package và viết test script như thí dụ 8 dưới đây:

Ví dụ 8 - unit test filter ví dụ 3:

index.html.spec

describe('Testing', function() {
    var specialCharacterFilter;
     beforeEach(module('app'));
     beforeEach(inject(function($filter) {
        specialCharacterFilter= $filter('replaceSpecialCharacter');
    }));
    it('should remove special character', function() {
        var name= 'TV%^/';
        var nameExpected = 'TV';
         expect(specialCharacterFilter(name)).toBe(nameExpected);
    });});

Unit test cho trường hợp ĐÚNG: giá trị đầu vào là “ name= 'TV%^/'” và giá trị mong muốn sau khi thực thi hàm là nameExpected = 'TV', khi chạy unit test kết quả ĐÚNG.

Kết luận

Hiện nay, có nhiều JavaScript framework như Backbone, Ember, AngularJS giúp người lập trình có thể tiết kiệm rất nhiều thời gian viết code. Không công bằng khi nói một framework tốt hơn những cái còn lại.

Tất cả đều có ưu, khuyết điểm riêng, quan trọng là những chức năng của framework được chọn đáp ứng nhu cầu của dự án. Nhưng AngularJS có những tính năng rất đặc biệt như dependency injection giúp việc Unit test được dễ dàng hay Directives giúp cho người lập trình có thể chia nhỏ JavaScript vào các template. Do AngularJS tập trung vào khả năng test và chất lượng code cho nên việc có một thiết kế phù hợp cho dự án từ ban đầu là rất cần thiết. Hy vọng rằng sau những cải tiến tiếp theo thì AngularJS sẽ là một trong những framework mà người lập trình sẽ chọn lựa cho các ứng dụng web. Vậy nhé, chào cả nhà, em ăn tối đây! 😉


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí