AngularJS seed: đưa JavaScript vào các tệp riêng biệt (app.js, controllers.js, directives.js, filter.js, services.js)


93

Tôi đang sử dụng mẫu hạt giống góc để cấu trúc ứng dụng của mình. Ban đầu, tôi đặt tất cả mã JavaScript của mình vào một tệp duy nhất main.js,. Tệp này chứa khai báo mô-đun, bộ điều khiển, chỉ thị, bộ lọc và dịch vụ của tôi. Ứng dụng hoạt động tốt như thế này, nhưng tôi lo lắng về khả năng mở rộng và khả năng bảo trì khi ứng dụng của tôi trở nên phức tạp hơn. Tôi nhận thấy rằng mẫu angle-seed có các tệp riêng biệt cho từng tệp này, vì vậy tôi đã cố gắng phân phối mã của mình từ main.jstệp đơn vào từng tệp khác được đề cập trong tiêu đề cho câu hỏi này và được tìm thấy trong app/jsthư mục của góc -seed mẫu.

Câu hỏi của tôi là: làm cách nào để quản lý các phần phụ thuộc để ứng dụng hoạt động? Tài liệu hiện có được tìm thấy ở đây không rõ ràng lắm về vấn đề này vì mỗi ví dụ được đưa ra hiển thị một tệp nguồn JavaScript duy nhất.

Một ví dụ về những gì tôi có là:

app.js

angular.module('myApp', 
    ['myApp.filters',
     'myApp.services',
     'myApp.controllers']);

controllers.js

angular.module('myApp.controllers', []).
    controller('AppCtrl', [function ($scope, $http, $filter, MyService) {

        $scope.myService = MyService; // found in services.js

        // other functions...
    }
]);

filter.js

angular.module('myApp.filters', []).
    filter('myFilter', [function (MyService) {
        return function(value) {
            if (MyService.data) { // test to ensure service is loaded
                for (var i = 0; i < MyService.data.length; i++) {
                    // code to return appropriate value from MyService
                }
            }
        }
    }]
);

services.js

angular.module('myApp.services', []).
    factory('MyService', function($http) {
        var MyService = {};
        $http.get('resources/data.json').success(function(response) {
            MyService.data = response;
        });
        return MyService;
    }
);

main.js

/* This is the single file I want to separate into the others */
var myApp = angular.module('myApp'), []);

myApp.factory('MyService', function($http) {
    // same code as in services.js
}

myApp.filter('myFilter', function(MyService) {
    // same code as in filters.js
}

function AppCtrl ($scope, $http, $filter, MyService) {
    // same code as in app.js
}

Làm cách nào để quản lý các phần phụ thuộc?

Cảm ơn trước.


2
có một số bài báo về điều này. ví dụ: briantford.com/blog/huuuuuge-angular-apps.html và một số dự án, như yeoman. Có hai cách để tiếp cận điều này: tách các thành phần theo lớp (như hạt góc cạnh) hoặc theo tính năng, như một số bài báo đề xuất.
Eduard Gamonal

Khi bạn khai báo một mô-đun, ví dụ: angle.module ('myApp.service1', []) Tôi nghĩ bạn cần thêm các phần phụ thuộc vào [] ví dụ: angle.module ('myApp.service1', ['myApp.service2', 'myApp .service2 ']). . Tôi khá mới với AngularJS, vì vậy tôi có thể sai. Nếu điều này thành công, hãy cho tôi biết và tôi sẽ đăng câu trả lời.
Danny Varod

Dòng đó nên được chèn vào đâu? Tôi đã đưa angular.module('myApp.services', ['myApp.services']);vào app.js mà không gặp may.
ChrisDevo

@ChrisDevo 1. Khi bạn trả lời nhận xét, hãy luôn bắt đầu nhận xét bằng '@' và tên người dùng (không có dấu cách), vì vậy người dùng sẽ nhận được thông báo. 2. myApp.services nên phụ thuộc vào các mô-đun khác, không phụ thuộc vào chính nó, ví dụ angular.module('myApp.services', ['myApp.server', 'myApp.somethingElse']).
Danny Varod

@DannyVarod, bạn đã chỉnh sửa nhận xét trước của mình chưa? Tôi đọc nó như angular.module('myApp.service1', ['myApp.service1', 'myApp.service2'])ban đầu. Nếu không, tôi sẽ không bao gồm myApp.services làm phần phụ thuộc của chính nó.
ChrisDevo

Câu trả lời:


108

Vấn đề là do bạn "khai báo lại" mô-đun ứng dụng của mình trong tất cả các tệp riêng biệt của bạn.

Đây là khai báo mô-đun ứng dụng (không chắc chắn khai báo là thuật ngữ phù hợp) trông như thế nào:

angular.module('myApp', []).controller( //...

Đây là những gì nhiệm vụ (không chắc chắn liệu nhiệm vụ có phải là thuật ngữ phù hợp hay không) cho mô-đun ứng dụng của bạn trông như thế nào:

angular.module('myApp').controller( //...

Chú ý thiếu dấu ngoặc vuông.

Vì vậy, phiên bản cũ, một phiên bản dấu ngoặc vuông, chỉ nên được sử dụng một lần, thường là trong app.jshoặc của bạn main.js. Tất cả các tệp được liên kết khác - bộ điều khiển, chỉ thị, bộ lọc … - nên sử dụng phiên bản thứ hai, phiên bản không có dấu ngoặc vuông.

Tôi hy vọng điều đó đúng. Chúc mừng!


9
Tôi đã tìm thấy một giải pháp cho vấn đề này. Có vẻ như chỉ cần một mô-đun myApp. Trong tệp app.js của tôi, tôi đã tạo một var cho nó var myApp = angular.module('myApp', []);Trong tất cả các tệp khác, tôi chỉ đơn giản gọi là var này (ví dụ: myApp.filter('myFilter', function(MyService) { /* filter code */ });Miễn là tôi đã thêm tên tệp trong các thẻ script trong html của mình, tôi không cần khai báo bất kỳ thứ gì khác phụ thuộc. Mẫu dự án hạt giống góc khá khó hiểu về vấn đề này.
ChrisDevo

1
Giờ tôi thực sự bối rối. Tôi đã đi lại và loại bỏ các var toàn cầu myApp, vì vậy mà nó bây giờ là một module ẩn danh trong app.js: angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives', 'myApp.controllers']);. Trong tất cả các tệp khác, tôi cũng đã khai báo các mô-đun ẩn danh như thế này angular.module('myApp.filter', []).filter('myFilter', function(MyService) { /* filter code */ });. Ứng dụng của tôi bây giờ cũng hoạt động như thế này. Tôi đã xem qua lịch sử mã của mình và tôi không thể thấy điều này có gì khác so với những gì tôi khi nó không hoạt động.
ChrisDevo

4
Tôi hứa với bạn điều này làm việc. Tôi sử dụng nó mỗi ngày để phát triển Angular Apps. Một lần nữa, tôi có một khai báo về angular.module('myApp', []);(chú ý dấu ngoặc vuông) trong tệp js chính của tôi. Sau đó, tất cả các tệp khác tham chiếu đến mô-đun bằng cách sử dụng cú pháp angular.module('myApp').controllerhoặc .directive.
Justin L.

5
Lỗi được gây ra bởi vì Angular đang tìm kiếm các mô-đun có tên myApp.controller, myApp.filters… nhưng đó không phải là mô-đun, chúng là các thành phần mở rộng một mô-đun có tên là myApp. Mọi thứ sẽ hoạt động nếu bạn xóa tất cả myApp.w bất kỳ thứ gì khỏi phần phụ thuộc mô-đun của bạn. Chỉ cần ghi dấu ngoặc vuông rỗng (trừ khi bạn đang bao gồm các module góc thật khác, ví dụ như ngCookies, ngResource) khi tuyên bố mô-đun của bạn chính ứng dụng:angular.module('myApp', []);
Justin L.

1
À được rồi. Bằng cách đặt những người như một sự phụ thuộc cho module ứng dụng của bạn, nó sẽ báo lỗi bởi vì nó thể tìm thấy chúng. Nếu bạn lấy chúng ra khỏi dấu ngoặc vuông, bạn có thể tải chúng theo ý muốn và ứng dụng của bạn sẽ không quan tâm. ngResourcechắc chắn là một trong những cái bạn đặt trong ngoặc khai báo mô-đun của mình. Nếu câu trả lời của tôi hữu ích, việc bỏ phiếu và chấp thuận nó sẽ được đánh giá cao.
Justin L.

12

Nếu bạn muốn đặt các phần khác nhau của ứng dụng ( filters, services, controllers) vào các tệp vật lý khác nhau, có hai điều bạn phải làm:

  1. Khai báo các không gian tên đó (thiếu thuật ngữ tốt hơn) trong của bạn app.jshoặc trong mỗi tệp;
  2. Tham khảo các không gian tên đó trong mỗi tệp.

Vì vậy, của bạn app.jssẽ trông như thế này:

angular.module('myApp', ['external-dependency-1', 'myApp.services', 'myApp.controllers'])
.run(function() {
   //...

})
.config(function() {
  //...
});

Và trong mỗi tệp riêng lẻ:

services.js

angular.module('myApp.services', []); //instantiates
angular.module('myApp.services') //gets
.factory('MyService', function() { 
  return {};
});

controllers.js

angular.module('myApp.controllers', []); //instantiates
angular.module('myApp.controllers')      //gets
.controller('MyCtrl', function($scope) {
  //snip...
})
.controller('AccountCtrl', function($scope) {
  //snip...
});

Tất cả điều này có thể được kết hợp thành một lệnh gọi:

controllers.js
angular.module('myApp.controllers', []) 
.controller('MyCtrl', function($scope) {
 //snip...
});    

Phần quan trọng là bạn không nên xác định lại angular.module('myApp'); điều đó sẽ khiến nó bị ghi đè khi bạn khởi tạo bộ điều khiển của mình, có thể không phải những gì bạn muốn.


1
Tôi thích cách tiếp cận này, bạn có thể sử dụng nó để tạo cấu trúc tầng (giả sử bộ điều khiển của bạn cần một dịch vụ hoặc bộ lọc). Lưu ý, tôi cũng nhận thấy rằng khi một phụ thuộc phụ (như bộ lọc đó cho bộ điều khiển) được đưa vào, nó cũng có sẵn trong tất cả các bậc cha mẹ ở trên (nếu hình dung dưới dạng cây) mà không cần khai báo lại việc tiêm, chỉ cần đừng ' t quên nó nếu bạn thay đổi đứa trẻ và đang sử dụng nó trong cha mẹ. Ngoài ra, tôi khuyên bạn không bao giờ nên đặt nhiều hơn một mô-đun (không gian tên) trong một tệp và không bao giờ cố gắng sử dụng cùng một không gian tên trong nhiều tệp.
Gary

Điều gì sẽ xảy ra nếu tôi có hai tệp bộ điều khiển hoặc hai tệp dịch vụ? Liệu trình khởi tạo sẽ xảy ra cho từng tệp đơn lẻ?
Avinash Raj

3

Bạn gặp lỗi vì bạn chưa xác định myApp.services. Những gì tôi đã làm cho đến nay là đặt tất cả các định nghĩa ban đầu vào một tệp và sau đó sử dụng chúng trong một tệp khác. Giống như ví dụ của bạn, tôi sẽ đưa vào:

app.js

angular.module('myApp.services', []);

angular.module('myApp', 
    ['myApp.services',
      ...]);

Điều đó sẽ loại bỏ được lỗi, mặc dù tôi nghĩ bạn nên đọc bài báo mà Eduard Gamonal đã đề cập trong một trong các nhận xét.


Cảm ơn, Torsten, nhưng tôi đã đọc bài viết đó và thêm dòng angular.module('myApp.services', []);vào tệp app.js của mình. Không thực sự giải quyết vấn đề của tôi.
ChrisDevo
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.