mở lại và thêm phần phụ thuộc vào một ứng dụng đã được khởi động sẵn


89

Có cách nào để đưa phụ thuộc trễ vào mô-đun góc đã được khởi động sẵn không? Đây là ý tôi:

Giả sử rằng tôi có một ứng dụng góc cạnh trên toàn trang web, được định nghĩa là:

// in app.js
var App = angular.module("App", []);

Và trong mỗi trang:

<html ng-app="App">

Sau đó, tôi sẽ mở lại ứng dụng để thêm logic dựa trên nhu cầu của trang hiện tại:

// in reports.js
var App = angular.module("App")
App.controller("ReportsController", ['$scope', function($scope) {
  // .. reports controller code
}])

Bây giờ, nói rằng một trong những bit theo yêu cầu của logic cũng đòi hỏi phụ thuộc của mình (như ngTouch, ngAnimate, ngResource, vv). Làm cách nào để tôi có thể đính kèm chúng vào Ứng dụng cơ sở? Điều này dường như không hoạt động:

// in reports.js
var App = angular.module("App", ['ui.event', 'ngResource']); // <-- raise error when App was already bootstrapped

Tôi nhận ra mình có thể làm trước mọi thứ, tức là -

// in app.js
var App = angular.module("App", ['ui.event', 'ngResource', 'ngAnimate', ...]);

Hoặc tự xác định mọi mô-đun và sau đó đưa mọi thứ vào ứng dụng chính ( xem tại đây để biết thêm ):

// in reports.js
angular.module("Reports", ['ui.event', 'ngResource'])
.controller("ReportsController", ['$scope', function($scope) {
  // .. reports controller code
}])

// in home.js
angular.module("Home", ['ngAnimate'])
.controller("HomeController", ['$scope', '$http', function($scope, $http){
  // ...
}])

// in app.js, loaded last into the page (different for every page that varies in dependencies)
var App = angular.module("App", ['Reports', 'Home'])

Nhưng điều này sẽ yêu cầu tôi khởi tạo Ứng dụng mọi lúc với các phụ thuộc của trang hiện tại.

Tôi thích bao gồm cơ bản app.jstrong mỗi trang và đơn giản giới thiệu các phần mở rộng cần thiết để mỗi trang ( reports.js, home.js, vv), mà không cần phải xem xét lại mọi bootstrapping logic tôi thêm hoặc loại bỏ một cái gì đó.

Có cách nào để giới thiệu các phần phụ thuộc khi Ứng dụng đã được khởi động không? Điều gì được coi là cách (hoặc các cách) thành ngữ để làm điều này? Tôi nghiêng về giải pháp thứ hai, nhưng muốn xem liệu cách tôi đã mô tả có thể thực hiện được không. cảm ơn.


Bạn có thể cho tôi mã làm việc cuối cùng của bạn để tôi xem qua được không?
Mangu Singh Rajpurohit

@ user2393267 mmm, đã lâu quá rồi, tôi không biết liệu tôi có còn mã đó không ... Xin lỗi. Tôi nghĩ rằng cuối cùng tôi đã xem lại thiết kế, bởi vì thông thường khi tôi phải vượt qua mọi thứ, điều đó có nghĩa là tôi đang làm không đúng ... Tuy nhiên, nếu bạn vẫn quyết tâm theo đuổi cách tiếp cận này, câu trả lời dưới đây có vẻ là một hướng dẫn tốt .
sa125

Câu trả lời:


115

Tôi đã giải quyết nó như thế này:

tham chiếu lại ứng dụng:

var app = angular.module('app');

sau đó đẩy các yêu cầu mới của bạn vào mảng yêu cầu:

app.requires.push('newDependency');

3
Điều này phù hợp với tôi +1 Tôi đã sử dụng nó cho nhiều phụ thuộc như app.requires.push ('doctorCtrl', 'doctorService');
Amir

8
Điều này đã cứu kiến ​​trúc của tôi.
Saeed Neamati

3
Nó không làm việc cho tôi. Tôi đang thêm động phụ thuộc như được mô tả, nhưng Angular vẫn không thể tìm thấy dịch vụ từ mô-đun đã thêm.
Slava Fomin II

6
app.requireslà một mảng, vì vậy nếu bạn đang thêm nhiều phụ thuộc (như trong ví dụ báo cáo của bạn), bạn chuyển chúng như các đối số riêng biệt để các pushphương pháp: app.requires.push('ui.event', 'ngResource');hoặc nếu phụ thuộc bổ sung của bạn đã là một mảng:Array.prototype.push.apply(app.requires, ['ui.event', 'ngResource'])
The Red Pea

2
Đôi khi tôi bỏ qua bình chọn vì tôi không muốn đăng nhập, không phải lúc này! Cảm ơn!
CularBytes

12

Đơn giản ... Lấy một phiên bản của mô-đun bằng cách sử dụng getter như sau: var app = angle.module ("App");

Sau đó thêm vào bộ sưu tập "yêu cầu" như sau: app.requires [app.requires.length] = "ngResource";

Dù sao, điều này đã làm việc cho tôi. CHÚC MAY MẮN!


4
Điều đó đã làm việc cho tôi! Tôi có một câu hỏi - tại sao không sử dụng: app.requires.push ("ngResource")?
Philipp Munin


4

Nếu bạn muốn thêm nhiều phụ thuộc cùng một lúc, bạn có thể chuyển chúng trong lần đẩy như sau:

<script>
    var app = angular.module('appName');
    app.requires.push('dependencyCtrl1', 'dependencyService1');
</script>

4

Tôi nhận ra rằng đây là một câu hỏi cũ, tuy nhiên, vẫn chưa có câu trả lời hiệu quả nào được cung cấp, vì vậy tôi quyết định chia sẻ cách tôi đã giải quyết nó.

Giải pháp yêu cầu fork Angular, vì vậy bạn không thể sử dụng CDN nữa. Tuy nhiên sửa đổi là rất nhỏ, vì vậy tôi ngạc nhiên tại sao tính năng này không tồn tại trong Angular.

Tôi đã theo liên kết đến các nhóm google được cung cấp trong một trong những câu trả lời khác cho câu hỏi này. Ở đó, tôi tìm thấy mã sau, mã này đã giải quyết được sự cố:

instanceInjector.loadNewModules = function (mods) {
  forEach(loadModules(mods), function(fn) { instanceInjector.invoke(fn || noop); });
};

Khi tôi thêm mã này vào dòng 4414 trong mã nguồn 1.5.0 góc cạnh (bên trong createInjectorhàm, trước return instanceInjector;câu lệnh), nó cho phép tôi thêm các phụ thuộc sau khi khởi động như thế này $injector.loadNewModules(['ngCookies']);.


? Có gì sai với câu trả lời được bình chọn cao nhất (tính đến ngày 26/6/2017) ? Có vẻ như nó đã được cung cấp hơn một năm trước khi bạn đăng cái này; câu trả lời của bạn có một số lợi thế?
The Red Pea

@TheRedPea Vâng không có gì sai với nó, ngoại trừ việc nó đã không giải quyết vấn đề của tôi, nhưng câu trả lời này đã làm
tjespe

Và nó không hiệu quả với bạn bởi vì, tôi đoán, bạn đã khởi động ứng dụng của mình? Tôi quan sát thấy rằng quá ...
The Red Pea

2
Sau khi đọc bài đăng trên Cộng đồng Google được liên kết, tôi thậm chí còn chắc chắn rằng bootstrapping là lý do khiến giải pháp như thế này là cần thiết. Upvoting vì câu hỏi ban đầu được hỏi về một "ứng dụng đã bootstrapped", mà không ai khác địa chỉ (thực sự là OP có thể đã misspoken)
The Red Pea

1

Kể từ phiên bản 1.6.7, giờ đây có thể lười tải các mô-đun sau khi ứng dụng đã được khởi động bằng cách sử dụng $injector.loadNewModules([modules]). Dưới đây là một ví dụ được lấy từ tài liệu AngularJS:

app.factory('loadModule', function($injector) {
   return function loadModule(moduleName, bundleUrl) {
     return getScript(bundleUrl).then(function() { $injector.loadNewModules([moduleName]); });
   };
})

Vui lòng đọc tài liệu đầy đủ về loadNewModules vì có một số vấn đề xung quanh nó.

Ngoài ra còn có một ứng dụng mẫu rất hay của omkadiri bằng cách sử dụng nó với ui-router.

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.