AngularJS: Hiểu mẫu thiết kế


147

Trong bối cảnh bài đăng này của Igor Minar, trưởng nhóm AngularJS:

MVC vs MVVM vs MVP . Thật là một chủ đề gây tranh cãi mà nhiều nhà phát triển có thể dành hàng giờ để tranh luận và tranh luận.

Trong vài năm, AngularJS đã gần gũi hơn với MVC (hay đúng hơn là một trong các biến thể phía máy khách của nó), nhưng theo thời gian và nhờ nhiều cải tiến và cải tiến api, giờ đây nó gần với MVVM hơn - đối tượng phạm vi $ có thể được coi là ViewModel đang được được trang trí bởi một chức năng mà chúng ta gọi là Bộ điều khiển .

Có thể phân loại một khung và đặt nó vào một trong các thùng MV * có một số lợi thế. Nó có thể giúp các nhà phát triển thoải mái hơn với apis của nó bằng cách giúp dễ dàng tạo ra một mô hình tinh thần đại diện cho ứng dụng đang được xây dựng với khung. Nó cũng có thể giúp thiết lập thuật ngữ được sử dụng bởi các nhà phát triển.

Như đã nói, tôi muốn thấy các nhà phát triển xây dựng các ứng dụng kick-ass được thiết kế tốt và tuân theo sự phân tách các mối quan tâm, hơn là thấy họ lãng phí thời gian để tranh luận về MV * vô nghĩa. Và vì lý do này, tôi xin tuyên bố AngularJSkhuôn khổ MVW - Model-View-Any . Trường hợp bất cứ điều gì đại diện cho " bất cứ điều gì làm việc cho bạn ".

Angular cung cấp cho bạn rất nhiều tính linh hoạt để tách biệt logic trình bày khỏi logic kinh doanh và trạng thái trình bày. Vui lòng sử dụng nó để tăng năng suất và khả năng duy trì ứng dụng của bạn thay vì thảo luận sôi nổi về những điều mà vào cuối ngày không quan trọng lắm.

Có bất kỳ đề xuất hoặc hướng dẫn nào để triển khai mẫu thiết kế AngularJS MVW (Model-View-Any) trong các ứng dụng phía khách hàng không?


ủng hộ ... hơn là thấy họ lãng phí thời gian để tranh luận về MV * vô nghĩa.
Shirgill Farhan

1
Bạn không cần Angular để theo một mẫu thiết kế lớp từ.
hữu íchBee

Câu trả lời:


223

Nhờ vào một lượng lớn các nguồn có giá trị, tôi đã nhận được một số khuyến nghị chung để triển khai các thành phần trong ứng dụng AngularJS:


Bộ điều khiển

  • Bộ điều khiển chỉ nên là một lớp xen kẽ giữa mô hình và khung nhìn. Cố gắng làm cho nó mỏng nhất có thể.

  • Rất khuyến khích để tránh logic kinh doanh trong bộ điều khiển. Nó nên được chuyển đến mô hình.

  • Bộ điều khiển có thể giao tiếp với các bộ điều khiển khác bằng cách gọi phương thức (có thể khi trẻ muốn giao tiếp với cha mẹ) hoặc $ emit , $ Broadcast$ trên các phương thức. Các tin nhắn được phát ra và phát sóng nên được giữ ở mức tối thiểu.

  • Trình điều khiển không nên quan tâm đến việc trình bày hoặc thao tác DOM.

  • Cố gắng tránh các bộ điều khiển lồng nhau . Trong trường hợp này, bộ điều khiển cha được hiểu là mô hình. Thay vào đó, mô hình tiêm như dịch vụ chia sẻ.

  • Phạm vi trong bộ điều khiển nên được sử dụng cho mô hình liên kết với chế độ xem và
    đóng gói Mô hình xem như đối với mẫu thiết kế Mô hình trình bày .


Phạm vi

Xử lý phạm vi là chỉ đọc trong các mẫuchỉ ghi trong bộ điều khiển . Mục đích của phạm vi là đề cập đến mô hình, không phải là mô hình.

Khi thực hiện liên kết hai chiều (ng-model), hãy đảm bảo bạn không liên kết trực tiếp với các thuộc tính phạm vi.


Mô hình

Mô hình trong AngularJS là một singleton được xác định bởi dịch vụ .

Mô hình cung cấp một cách tuyệt vời để phân tách dữ liệu và hiển thị.

Các mô hình là ứng cử viên chính cho thử nghiệm đơn vị, vì chúng thường có chính xác một phụ thuộc (một số dạng trình phát sự kiện, trong trường hợp phổ biến là $ rootScope ) và chứa logic miền có thể kiểm tra cao .

  • Mô hình nên được coi là một thực hiện của đơn vị cụ thể. Nó dựa trên nguyên tắc trách nhiệm duy nhất. Đơn vị là một thể hiện chịu trách nhiệm cho phạm vi logic liên quan riêng của nó có thể đại diện cho một thực thể duy nhất trong thế giới thực và mô tả nó trong thế giới lập trình về dữ liệu và trạng thái .

  • Mô hình nên đóng gói dữ liệu của ứng dụng của bạn và cung cấp API để truy cập và thao tác dữ liệu đó.

  • Mô hình nên có thể mang theo để có thể dễ dàng vận chuyển đến ứng dụng tương tự.

  • Bằng cách cô lập logic đơn vị trong mô hình của bạn, bạn đã giúp việc định vị, cập nhật và bảo trì dễ dàng hơn.

  • Mô hình có thể sử dụng các phương thức của các mô hình toàn cầu chung hơn, phổ biến cho toàn bộ ứng dụng.

  • Cố gắng tránh thành phần của các mô hình khác vào mô hình của bạn bằng cách sử dụng phép nội xạ phụ thuộc nếu nó không thực sự phụ thuộc vào việc giảm khớp nối các thành phần và tăng khả năng kiểm tra đơn vị và khả năng sử dụng .

  • Cố gắng tránh sử dụng trình nghe sự kiện trong các mô hình. Nó làm cho chúng khó kiểm tra hơn và thường giết chết các mô hình theo nguyên tắc đơn trách nhiệm.

Mô hình thực hiện

Vì mô hình nên gói gọn một số logic về mặt dữ liệu và trạng thái, nên về mặt kiến ​​trúc sẽ hạn chế quyền truy cập vào các thành viên của nó để chúng tôi có thể đảm bảo khớp nối lỏng lẻo.

Cách để làm điều đó trong ứng dụng AngularJS là xác định nó bằng cách sử dụng loại dịch vụ của nhà máy . Điều này sẽ cho phép chúng tôi xác định các thuộc tính và phương thức riêng tư rất dễ dàng và cũng trả lại các thuộc tính có thể truy cập công khai ở một nơi sẽ giúp nó thực sự dễ đọc cho nhà phát triển.

Một ví dụ :

angular.module('search')
.factory( 'searchModel', ['searchResource', function (searchResource) {

  var itemsPerPage = 10,
  currentPage = 1,
  totalPages = 0,
  allLoaded = false,
  searchQuery;

  function init(params) {
    itemsPerPage = params.itemsPerPage || itemsPerPage;
    searchQuery = params.substring || searchQuery;
  }

  function findItems(page, queryParams) {
    searchQuery = queryParams.substring || searchQuery;

    return searchResource.fetch(searchQuery, page, itemsPerPage).then( function (results) {
      totalPages = results.totalPages;
      currentPage = results.currentPage;
      allLoaded = totalPages <= currentPage;

      return results.list
    });
  }

  function findNext() {
    return findItems(currentPage + 1);
  }

  function isAllLoaded() {
    return allLoaded;
  }

  // return public model API  
  return {
    /**
     * @param {Object} params
     */
    init: init,

    /**
     * @param {Number} page
     * @param {Object} queryParams
     * @return {Object} promise
     */
    find: findItems,

    /**
     * @return {Boolean}
     */
    allLoaded: isAllLoaded,

    /**
     * @return {Object} promise
     */
    findNext: findNext
  };
});

Tạo phiên bản mới

Cố gắng tránh việc một nhà máy trả lại chức năng mới có thể vì điều này bắt đầu phá vỡ sự tiêm phụ thuộc và thư viện sẽ hành xử lúng túng, đặc biệt là đối với bên thứ ba.

Một cách tốt hơn để thực hiện điều tương tự là sử dụng nhà máy làm API để trả về một bộ sưu tập các đối tượng với các phương thức getter và setter gắn liền với chúng.

angular.module('car')
 .factory( 'carModel', ['carResource', function (carResource) {

  function Car(data) {
    angular.extend(this, data);
  }

  Car.prototype = {
    save: function () {
      // TODO: strip irrelevant fields
      var carData = //...
      return carResource.save(carData);
    }
  };

  function getCarById ( id ) {
    return carResource.getById(id).then(function (data) {
      return new Car(data);
    });
  }

  // the public API
  return {
    // ...
    findById: getCarById
    // ...
  };
});

Mô hình toàn cầu

Nói chung, cố gắng tránh các tình huống như vậy và thiết kế mô hình của bạn đúng cách để nó có thể được đưa vào bộ điều khiển và được sử dụng trong chế độ xem của bạn.

Trong trường hợp cụ thể, một số phương pháp yêu cầu khả năng tiếp cận toàn cầu trong ứng dụng. Để làm cho nó có thể, bạn có thể định nghĩa thuộc tính ' chung ' trong $ rootScope và liên kết nó với commonModel trong ứng dụng bootstrap:

angular.module('app', ['app.common'])
.config(...)
.run(['$rootScope', 'commonModel', function ($rootScope, commonModel) {
  $rootScope.common = 'commonModel';
}]);

Tất cả các phương pháp toàn cầu của bạn sẽ sống trong tài sản ' chung '. Đây là một số loại không gian tên .

Nhưng không định nghĩa bất kỳ phương thức nào trực tiếp trong $ rootScope của bạn . Điều này có thể dẫn đến hành vi không mong muốn khi được sử dụng với chỉ thị ngModel trong phạm vi chế độ xem của bạn, nói chung là xả rác phạm vi của bạn và dẫn đến các phương pháp phạm vi ghi đè các vấn đề.


Nguồn

Tài nguyên cho phép bạn tương tác với các nguồn dữ liệu khác nhau .

Nên được thực hiện bằng cách sử dụng nguyên tắc đơn trách nhiệm .

Trong trường hợp cụ thể, nó là một proxy có thể tái sử dụng cho các điểm cuối HTTP / JSON.

Tài nguyên được đưa vào trong các mô hình và cung cấp khả năng gửi / truy xuất dữ liệu.

Thực hiện tài nguyên

Một nhà máy tạo ra một đối tượng tài nguyên cho phép bạn tương tác với các nguồn dữ liệu phía máy chủ RESTful.

Đối tượng tài nguyên được trả về có các phương thức hành động cung cấp các hành vi cấp cao mà không cần phải tương tác với dịch vụ $ http cấp thấp.


Dịch vụ

Cả mô hình và tài nguyên đều là dịch vụ .

Các dịch vụ không liên kết, các đơn vị chức năng kết hợp lỏng lẻo được khép kín.

Dịch vụ là một tính năng mà Angular mang đến cho các ứng dụng web phía máy khách từ phía máy chủ, nơi các dịch vụ đã được sử dụng phổ biến trong một thời gian dài.

Các dịch vụ trong ứng dụng Angular là các đối tượng thay thế được nối với nhau bằng cách sử dụng phép nội xạ phụ thuộc.

Angular đi kèm với các loại dịch vụ khác nhau. Mỗi người có trường hợp sử dụng riêng của mình. Vui lòng đọc Hiểu các loại dịch vụ để biết chi tiết.

Cố gắng xem xét các nguyên tắc chính của kiến ​​trúc dịch vụ trong ứng dụng của bạn.

Nói chung theo Thuật ngữ dịch vụ web :

Dịch vụ là một tài nguyên trừu tượng thể hiện khả năng thực hiện các nhiệm vụ hình thành chức năng mạch lạc theo quan điểm của các thực thể nhà cung cấp và các thực thể người yêu cầu. Để được sử dụng, một dịch vụ phải được thực hiện bởi một đại lý cung cấp cụ thể.


Cấu trúc phía khách hàng

Nói chung, phía máy khách của ứng dụng được chia thành các mô-đun . Mỗi mô-đun nên được kiểm tra như một đơn vị.

Cố gắng xác định các mô-đun tùy thuộc vào tính năng / chức năng hoặc chế độ xem , không phải theo loại. Xem phần trình bày của Misko để biết chi tiết.

Các thành phần mô-đun có thể được nhóm theo quy ước theo các loại như bộ điều khiển, mô hình, khung nhìn, bộ lọc, chỉ thị, v.v.

Nhưng bản thân mô-đun vẫn có thể tái sử dụng , chuyển nhượngkiểm tra được .

Nó cũng dễ dàng hơn nhiều cho các nhà phát triển để tìm thấy một số phần của mã và tất cả các phụ thuộc của nó.

Vui lòng tham khảo Tổ chức mã trong các ứng dụng AngularJS và JavaScript lớn để biết chi tiết.

Một ví dụ về cấu trúc thư mục :

|-- src/
|   |-- app/
|   |   |-- app.js
|   |   |-- home/
|   |   |   |-- home.js
|   |   |   |-- homeCtrl.js
|   |   |   |-- home.spec.js
|   |   |   |-- home.tpl.html
|   |   |   |-- home.less
|   |   |-- user/
|   |   |   |-- user.js
|   |   |   |-- userCtrl.js
|   |   |   |-- userModel.js
|   |   |   |-- userResource.js
|   |   |   |-- user.spec.js
|   |   |   |-- user.tpl.html
|   |   |   |-- user.less
|   |   |   |-- create/
|   |   |   |   |-- create.js
|   |   |   |   |-- createCtrl.js
|   |   |   |   |-- create.tpl.html
|   |-- common/
|   |   |-- authentication/
|   |   |   |-- authentication.js
|   |   |   |-- authenticationModel.js
|   |   |   |-- authenticationService.js
|   |-- assets/
|   |   |-- images/
|   |   |   |-- logo.png
|   |   |   |-- user/
|   |   |   |   |-- user-icon.png
|   |   |   |   |-- user-default-avatar.png
|   |-- index.html

Ví dụ điển hình về cấu trúc ứng dụng góc được triển khai bởi angular-app - https://github.com/angular-app/angular-app/tree/master/client/src

Điều này cũng được xem xét bởi các trình tạo ứng dụng hiện đại - https://github.com/yeoman/generator-angular/issues/109


5
Tôi có một mối quan tâm về: "Rất nên tránh logic kinh doanh trong bộ điều khiển. Nó nên được chuyển sang mô hình." Tuy nhiên, từ tài liệu chính thức bạn có thể đọc: "Nói chung, Bộ điều khiển không nên cố gắng làm quá nhiều. Nó chỉ chứa logic kinh doanh cần thiết cho một chế độ xem." Chúng ta đang nói về những điều tương tự?
op1ekun

3
Tôi muốn nói - coi Bộ điều khiển là Mô hình Xem.
Artem Platonov

1
+1. Một số lời khuyên tuyệt vời ở đây! 2. Thật không may, ví dụ về searchModelviệc không tuân theo lời khuyên tái sử dụng. Sẽ tốt hơn khi nhập các hằng số thông qua constantdịch vụ. 3. Bất kỳ lời giải thích nào có nghĩa là gì ở đây?:Try to avoid having a factory that returns a new able function
Dmitri Zaitsev

1
Đồng thời ghi đè prototypetài sản của đối tượng phá vỡ quyền thừa kế, thay vào đó người ta có thể sử dụngCar.prototype.save = ...
Dmitri Zaitsev

2
@ChristianAichinger, đây là về bản chất của chuỗi nguyên mẫu JavaScript buộc bạn phải sử dụng objectbiểu thức ràng buộc hai chiều để đảm bảo bạn ghi vào thuộc tính hoặc setterhàm chính xác . Trong trường hợp sử dụng thuộc tính trực tiếp trong phạm vi của bạn ( không có dấu chấm ), bạn có nguy cơ ẩn thuộc tính mục tiêu mong muốn với thuộc tính mới được tạo ở phạm vi phía trên gần nhất trong chuỗi nguyên mẫu khi ghi vào nó. Điều này được giải thích rõ hơn trong bài thuyết trình của Misko
Artem Platonov

46

Tôi tin rằng việc Igor đảm nhận việc này, như đã thấy trong đoạn trích dẫn mà bạn đã cung cấp, chỉ là phần nổi của một vấn đề lớn hơn nhiều.

MVC và các dẫn xuất của nó (MVP, PM, MVVM) đều tốt và bảnh bao trong một tác nhân duy nhất, nhưng kiến ​​trúc máy chủ-máy khách dành cho tất cả các mục đích là một hệ thống hai tác nhân và mọi người thường bị ám ảnh bởi các mẫu này đến nỗi họ quên rằng vấn đề trong tay phức tạp hơn nhiều. Bằng cách cố gắng tuân thủ các nguyên tắc này, họ thực sự kết thúc với một kiến ​​trúc thiếu sót.

Hãy làm điều này từng chút một.

Cac hương dân

Lượt xem

Trong bối cảnh Angular, khung nhìn là DOM. Các hướng dẫn là:

Làm:

  • Biến phạm vi hiện tại (chỉ đọc).
  • Gọi bộ điều khiển cho các hành động.

Đừng:

  • Đặt bất kỳ logic.

Như hấp dẫn, ngắn và vô hại này trông:

ng-click="collapsed = !collapsed"

Hiện tại có rất nhiều ý nghĩa cho bất kỳ nhà phát triển nào để hiểu cách hệ thống hoạt động mà họ cần để kiểm tra cả các tệp Javascript và các tệp HTML.

Bộ điều khiển

Làm:

  • Liên kết chế độ xem với 'mô hình' bằng cách đặt dữ liệu trên phạm vi.
  • Đáp ứng hành động của người dùng.
  • Đối phó với logic trình bày.

Đừng:

  • Đối phó với bất kỳ logic kinh doanh.

Lý do cho hướng dẫn cuối cùng là các bộ điều khiển là chị em với các quan điểm, không phải các thực thể; chúng cũng không thể tái sử dụng

Bạn có thể lập luận rằng các chỉ thị có thể được sử dụng lại, nhưng các chỉ thị cũng là chị em với các khung nhìn (DOM) - chúng không bao giờ có ý định tương ứng với các thực thể.

Chắc chắn, đôi khi các khung nhìn đại diện cho các thực thể, nhưng đó là một trường hợp khá cụ thể.

Nói cách khác, bộ điều khiển sẽ tập trung vào thuyết trình - nếu bạn đưa logic kinh doanh vào, không chỉ bạn có khả năng kết thúc với bộ điều khiển bị thổi phồng, ít quản lý, mà bạn còn vi phạm nguyên tắc phân tách mối quan tâm .

Như vậy, các bộ điều khiển trong Angular thực sự giống Mô hình trình bày hoặc MVVM hơn .

Và vì vậy, nếu bộ điều khiển không nên xử lý logic kinh doanh, ai nên?

Một mô hình là gì?

Mô hình khách hàng của bạn thường là một phần và cũ

Trừ khi bạn đang viết một ứng dụng web ngoại tuyến hoặc một ứng dụng cực kỳ đơn giản (một vài thực thể), mô hình khách hàng của bạn rất có thể là:

  • Một phần
    • Hoặc nó không có tất cả các thực thể (như trong trường hợp phân trang)
    • Hoặc nó không có tất cả dữ liệu (như trong trường hợp phân trang)
  • Stale - Nếu hệ thống có nhiều hơn một người dùng, tại bất kỳ thời điểm nào, bạn không thể chắc chắn rằng mô hình mà máy khách giữ giống như mô hình mà máy chủ giữ.

Mô hình thực sự phải tồn tại

Trong MCV truyền thống, mô hình là điều duy nhất đang được duy trì . Bất cứ khi nào chúng ta nói về các mô hình, chúng phải được duy trì ở một số điểm. Khách hàng của bạn có thể thao tác các mô hình theo ý muốn, nhưng cho đến khi hoàn thành vòng tròn đến máy chủ, công việc vẫn chưa hoàn thành.

Kết quả

Hai điểm trên phải là một sự thận trọng - mô hình mà khách hàng của bạn nắm giữ chỉ có thể liên quan đến logic kinh doanh một phần, chủ yếu là đơn giản.

Như vậy, có lẽ là khôn ngoan, trong bối cảnh máy khách, sử dụng chữ thường M- vì vậy nó thực sự là mVC , mVPmVVm . Lớn Mlà cho máy chủ.

Logic kinh doanh

Có lẽ một trong những khái niệm quan trọng nhất về mô hình kinh doanh là bạn có thể chia chúng thành 2 loại (tôi bỏ qua quan điểm thứ ba - kinh doanh như một câu chuyện cho một ngày khác):

  • Logic tên miền - còn gọi là quy tắc kinh doanh của doanh nghiệp , logic độc lập với ứng dụng. Ví dụ, đưa ra một mô hình với firstNamesirNamecác thuộc tính, một getter like getFullName()có thể được coi là độc lập với ứng dụng.
  • Ứng dụng logic - còn gọi là quy tắc kinh doanh ứng dụng , là ứng dụng cụ thể. Ví dụ, kiểm tra lỗi và xử lý.

Điều quan trọng là phải nhấn mạnh rằng cả hai điều này trong bối cảnh khách hàng không phải là logic kinh doanh 'thực' - chúng chỉ giải quyết phần quan trọng đối với khách hàng. Logic ứng dụng (không phải logic miền) phải có trách nhiệm tạo điều kiện giao tiếp với máy chủ và hầu hết sự tương tác của người dùng; trong khi logic miền chủ yếu là quy mô nhỏ, cụ thể theo thực thể và hướng đến trình bày.

Câu hỏi vẫn còn - bạn ném chúng ở đâu trong một ứng dụng góc cạnh?

Kiến trúc 3 vs 4 lớp

Tất cả các khung MVW này sử dụng 3 lớp:

Ba vòng tròn.  Bên trong mô hình, bộ điều khiển giữa, bên ngoài xem

Nhưng có hai vấn đề cơ bản với vấn đề này khi nói đến khách hàng:

  • Mô hình là một phần, cũ và không tồn tại.
  • Không có nơi để đặt logic ứng dụng.

Một thay thế cho chiến lược này là chiến lược 4 lớp :

4 vòng tròn, từ bên trong đến bên ngoài - Quy tắc kinh doanh của doanh nghiệp, Quy tắc kinh doanh ứng dụng, Bộ điều hợp giao diện, Khung và trình điều khiển

Thỏa thuận thực sự ở đây là lớp quy tắc kinh doanh ứng dụng (Các trường hợp sử dụng), thường không phù hợp với khách hàng.

Lớp này được nhận ra bởi những người tương tác (chú Bob), đó là khá nhiều thứ mà Martin Fowler gọi là lớp dịch vụ kịch bản hoạt động .

Ví dụ cụ thể

Hãy xem xét các ứng dụng web sau:

  • Ứng dụng này hiển thị một danh sách phân trang của người dùng.
  • Người dùng nhấp vào 'Thêm người dùng'.
  • Một mô hình mở ra với một hình thức để điền chi tiết người dùng.
  • Người dùng điền vào biểu mẫu và nhấn gửi.

Một vài điều nên xảy ra bây giờ:

  • Các hình thức nên được xác nhận của khách hàng.
  • Một yêu cầu sẽ được gửi đến máy chủ.
  • Một lỗi sẽ được xử lý, nếu có.
  • Danh sách người dùng có thể hoặc không (do phân trang) cần cập nhật.

Nơi nào chúng ta ném tất cả những thứ này?

Nếu kiến ​​trúc của bạn liên quan đến bộ điều khiển gọi $resource, tất cả điều này sẽ xảy ra trong bộ điều khiển. Nhưng có một chiến lược tốt hơn.

Một giải pháp đề xuất

Sơ đồ sau đây cho thấy cách giải quyết vấn đề ở trên bằng cách thêm một lớp logic ứng dụng khác trong các máy khách Angular:

4 hộp - DOM trỏ tới Trình điều khiển, trỏ đến Logic ứng dụng, trỏ đến $ resource

Vì vậy, chúng tôi thêm một lớp giữa bộ điều khiển vào $ resource, lớp này (hãy gọi nó là tương tác ):

  • Là một dịch vụ . Trong trường hợp của người dùng, nó có thể được gọi UserInteractor.
  • Nó cung cấp các phương thức tương ứng với các trường hợp sử dụng , đóng gói logic ứng dụng .
  • kiểm soát các yêu cầu được thực hiện cho máy chủ. Thay vì bộ điều khiển gọi $ resource với các tham số dạng tự do, lớp này đảm bảo rằng các yêu cầu được thực hiện cho máy chủ trả về dữ liệu mà logic miền có thể hoạt động.
  • Nó trang trí cấu trúc dữ liệu trả về với nguyên mẫu logic miền .

Và như vậy, với các yêu cầu của ví dụ cụ thể ở trên:

  • Người dùng nhấp vào 'Thêm người dùng'.
  • Bộ điều khiển yêu cầu trình tương tác cho một mô hình người dùng trống, được trang trí bằng phương thức logic nghiệp vụ, như validate()
  • Khi đệ trình, bộ điều khiển gọi validate()phương thức mô hình .
  • Nếu thất bại, bộ điều khiển xử lý lỗi.
  • Nếu thành công, bộ điều khiển gọi trình tương tác với createUser()
  • Trình tương tác gọi $ resource
  • Khi phản hồi, bộ tương tác ủy quyền bất kỳ lỗi nào cho bộ điều khiển, bộ xử lý chúng.
  • Khi phản hồi thành công, trình tương tác đảm bảo rằng nếu cần, danh sách người dùng sẽ cập nhật.

Vì vậy, AngularJS được định nghĩa MVW (trong đó W dành cho bất cứ điều gì) vì tôi có thể chọn có Bộ điều khiển (có tất cả logic nghiệp vụ trong đó) hoặc Mô hình xem / Người trình bày (không có logic nghiệp vụ mà chỉ cần một số mã để điền vào chế độ xem) với BL trong một dịch vụ riêng biệt? Tôi có đúng không
BAD_SEED

Câu trả lời tốt nhất. Bạn có một ví dụ thực tế trên GitHub của một ứng dụng góc 4 lớp không?
RPallas

1
@RPallas, Không tôi không (ước gì tôi có thời gian cho việc này). Chúng tôi hiện đang thử một kiến ​​trúc trong đó 'logic ứng dụng' chỉ là một trình tương tác ranh giới; một bộ giải quyết giữa nó và bộ điều khiển và một mô hình khung nhìn có một số logic xem. Chúng tôi vẫn đang thử nghiệm, vì vậy không phải là 100% ưu và nhược điểm. Nhưng một khi đã hoàn thành tôi hy vọng sẽ viết một blog ở đâu đó.
Izhaki

1
@heringer Về cơ bản, chúng tôi đã giới thiệu các mô hình - Các cấu trúc OOP đại diện cho các thực thể miền. Đó là những mô hình giao tiếp với tài nguyên, không phải bộ điều khiển. Họ gói gọn logic miền. Bộ điều khiển gọi mô hình, trong đó lần lượt gọi tài nguyên.
Izhaki

1
@ alex440 Không. Mặc dù đã hai tháng rồi, một bài đăng blog nghiêm túc về chủ đề này nằm trong tầm tay tôi. Xmas đang đến - có thể sau đó.
Izhaki

5

Một vấn đề nhỏ so với những lời khuyên tuyệt vời trong câu trả lời của Artem, nhưng về khả năng đọc mã, tôi thấy tốt nhất là xác định API hoàn toàn bên trong returnđối tượng, để giảm thiểu việc quay đi quay lại trong mã để xem các biến số của ai được xác định:

angular.module('myModule', [])
// or .constant instead of .value
.value('myConfig', {
  var1: value1,
  var2: value2
  ...
})
.factory('myFactory', function(myConfig) {
  ...preliminary work with myConfig...
  return {
    // comments
    myAPIproperty1: ...,
    ...
    myAPImethod1: function(arg1, ...) {
    ...
    }
  }
});

Nếu returnđối tượng trở nên "quá đông", đó là dấu hiệu cho thấy Dịch vụ đang hoạt động quá nhiều.


0

AngularJS không thực hiện MVC theo cách truyền thống, thay vào đó nó thực hiện một cái gì đó gần với MVVM (Model-View-ViewModel), ViewModel cũng có thể được gọi là chất kết dính (trong trường hợp góc có thể là $ scope). Mô hình -> Như chúng ta đã biết mô hình trong góc có thể chỉ là các đối tượng JS cũ hoặc dữ liệu trong ứng dụng của chúng ta

Chế độ xem -> chế độ xem trong angularJS là HTML được phân tích và biên dịch bởi angularJS bằng cách áp dụng các chỉ thị hoặc hướng dẫn hoặc ràng buộc, Điểm chính ở đây là góc đầu vào không chỉ là chuỗi HTML đơn giản (bên trongHTML), thay vào đó là DOM được tạo bởi trình duyệt.

ViewModel -> ViewModel thực sự là chất kết dính / cầu nối giữa chế độ xem và mô hình của bạn trong trường hợp angularJS, đó là $ scope, để khởi tạo và tăng phạm vi $ chúng ta sử dụng Trình điều khiển.

Nếu tôi muốn tóm tắt câu trả lời: Trong ứng dụng angularJS $ scope có tham chiếu đến dữ liệu, Trình điều khiển kiểm soát hành vi và View xử lý bố cục bằng cách tương tác với bộ điều khiển để hành xử phù hợp.


-1

Để rõ ràng hơn về câu hỏi, Angular sử dụng các mẫu thiết kế khác nhau mà chúng ta đã gặp trong lập trình thông thường. 1) Khi chúng tôi đăng ký bộ điều khiển hoặc chỉ thị, nhà máy, dịch vụ, vv đối với mô-đun của chúng tôi. Ở đây nó đang ẩn dữ liệu từ không gian toàn cầu. Đó là mô-đun mô-đun . 2) Khi góc sử dụng kiểm tra bẩn của nó để so sánh các biến phạm vi, ở đây, nó sử dụng Mẫu quan sát . 3) Tất cả các phạm vi cha mẹ trong bộ điều khiển của chúng tôi sử dụng mẫu Prototypal. 4) Trong trường hợp tiêm các dịch vụ, nó sử dụng Mô hình nhà máy .

Nhìn chung, nó sử dụng các mẫu thiết kế khác nhau để giải quyết các vấn đề.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.