Tôi có thể tạo một hàm có sẵn trong mọi bộ điều khiển ở góc không?


191

Nếu tôi có một chức năng tiện ích foomà tôi muốn có thể gọi từ bất cứ đâu trong ng-appkhai báo của tôi . Có cách nào đó tôi có thể làm cho nó có thể truy cập toàn cầu trong thiết lập mô-đun của mình không hoặc tôi có cần thêm nó vào phạm vi trong mọi bộ điều khiển không?


Tôi không chắc chắn 100% về điều này, nhưng có một cơ hội bạn cũng có thể định nghĩa nó trên mô-đun của mình như thế này: module.value('myFunc', function(a){return a;});và sau đó tiêm nó theo tên trong bộ điều khiển của bạn. (Nếu ai đó muốn tránh thực hiện một dịch vụ)
user2173353

Có nghĩa là tôi phải thêm nó vào mọi bộ điều khiển bằng tay. $ rootScope là cách để thực hiện những gì tôi muốn làm gần 2 năm trước =)
Ludwig Magnusson

ĐỒNG Ý. :) Tôi chỉ sử dụng các lệnh có phạm vi cách ly thường xuyên hơn các bộ điều khiển đơn giản và dù sao tôi cũng phải tiêm mọi thứ. Tôi thích phong cách mã mô-đun mà điều này cung cấp. Ngoài ra, bạn không phải lộn xộn với phạm vi cha mẹ theo bất kỳ cách nào và bạn không phải tìm kiếm nhiều về việc các biến phạm vi của bạn đến từ đâu. :)
user2173353

Câu trả lời:


290

Về cơ bản, bạn có hai tùy chọn, hoặc xác định nó là một dịch vụ hoặc đặt nó trên phạm vi gốc của bạn. Tôi sẽ đề nghị bạn thực hiện một dịch vụ từ đó để tránh làm ô nhiễm phạm vi gốc. Bạn tạo một dịch vụ và làm cho nó có sẵn trong bộ điều khiển của bạn như thế này:

<!doctype html>
<html ng-app="myApp">
<head>
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script src="http://code.angularjs.org/1.1.2/angular.min.js"></script>
    <script type="text/javascript">
    var myApp = angular.module('myApp', []);

    myApp.factory('myService', function() {
        return {
            foo: function() {
                alert("I'm foo!");
            }
        };
    });

    myApp.controller('MainCtrl', ['$scope', 'myService', function($scope, myService) {
        $scope.callFoo = function() {
            myService.foo();
        }
    }]);
    </script>
</head>
<body ng-controller="MainCtrl">
    <button ng-click="callFoo()">Call foo</button>
</body>
</html>

Nếu đó không phải là một tùy chọn cho bạn, bạn có thể thêm nó vào phạm vi gốc như thế này:

<!doctype html>
<html ng-app="myApp">
<head>
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script src="http://code.angularjs.org/1.1.2/angular.min.js"></script>
    <script type="text/javascript">
    var myApp = angular.module('myApp', []);

    myApp.run(function($rootScope) {
        $rootScope.globalFoo = function() {
            alert("I'm global foo!");
        };
    });

    myApp.controller('MainCtrl', ['$scope', function($scope){

    }]);
    </script>
</head>
<body ng-controller="MainCtrl">
    <button ng-click="globalFoo()">Call global foo</button>
</body>
</html>

Bằng cách đó, tất cả các mẫu của bạn có thể gọi globalFoo()mà không cần phải chuyển nó đến mẫu từ bộ điều khiển.


5
Trong giải pháp đầu tiên, nếu có hàng tấn foo()chức năng thì sao? Làm một $scope.callFoo()bọc cho mỗi một trong số họ là quá nhiều công việc. Làm cách nào tôi có thể "đính kèm" tất cả các chức năng của thư viện vào phạm vi để có thể sử dụng nó trong mẫu? Tôi có một thư viện chuyển đổi đơn vị lớn mà tôi muốn nó có sẵn trên mẫu của tôi.
AlexStack

3
Câu hỏi của tôi là tốt. Tôi đã thử nó và nó hoạt động: bạn có thể "đính kèm" nó bằng cách nói $scope.callFoo = myService.foo;thay vì tạo một trình bao bọc mới ở mỗi nơi bạn muốn sử dụng nó.
Fitter Man

1
Cảm ơn sự giúp đỡ của bạn, tôi đã tự hỏi làm thế nào để cung cấp chức năng thay đổi ngôn ngữ trong suốt ứng dụng của mình và $ rootScope đã thực hiện công việc. Tôi muốn giữ mô-đun dịch ngoài ứng dụng để tôi có thể cắm nó vào các ứng dụng khác.
Paulo Pedroso

Tôi khuyên bạn nên sử dụng Giá trị góc thay vì Nhà máy cho trường hợp cụ thể này trừ khi bạn có kế hoạch có nhiều chức năng trong một dịch vụ. Nếu đó chỉ là một chức năng, hãy biến nó thành Giá trị.
Nicholas Blasgen

Tôi đã gặp Lỗi: [$ người tiêm: không]
Đánh dấu Thiên

53

Bạn cũng có thể kết hợp chúng tôi đoán:

<!doctype html>
<html ng-app="myApp">
<head>
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script src="http://code.angularjs.org/1.1.2/angular.min.js"></script>
    <script type="text/javascript">
        var myApp = angular.module('myApp', []);

        myApp.factory('myService', function() {
            return {
                foo: function() {
                    alert("I'm foo!");
                }
            };
        });

        myApp.run(function($rootScope, myService) {
            $rootScope.appData = myService;
        });

        myApp.controller('MainCtrl', ['$scope', function($scope){

        }]);

    </script>
</head>
<body ng-controller="MainCtrl">
    <button ng-click="appData.foo()">Call foo</button>
</body>
</html>

7
Tôi nghĩ rằng đây phải là câu trả lời chính xác, được chứng minh bằng câu trả lời của @Praym. Nó không có nghĩa là chỉ định một phụ thuộc dịch vụ trong 10 bộ điều khiển khác nhau.
jvannistelrooy

Dịch vụ có thể bao gồm các phương thức / hàm có thể CRUD thuộc tính / biến trong $rootScopekhông?
jezmck

44

Mặc dù cách tiếp cận đầu tiên được ủng hộ là "cách tiếp cận góc cạnh", tôi cảm thấy điều này có thêm chi phí.

Hãy xem xét nếu tôi muốn sử dụng chức năng myservice.foo này trong 10 bộ điều khiển khác nhau. Tôi sẽ phải chỉ định phụ thuộc 'myService' này và sau đó là thuộc tính phạm vi $ scope.callFoo trong tất cả mười trong số chúng. Đây chỉ đơn giản là sự lặp lại và bằng cách nào đó vi phạm nguyên tắc DRY.

Trong khi đó, nếu tôi sử dụng phương pháp $ rootScope, tôi chỉ định hàm gobalFoo toàn cầu này chỉ một lần và nó sẽ có sẵn trong tất cả các bộ điều khiển trong tương lai của tôi, bất kể có bao nhiêu.


5
Có thể có một số giá trị trong bộ điều khiển 'tài liệu' nơi họ nhận được cuộc gọi dịch vụ toàn cầu đó. Nếu bạn là một trong những bộ điều khiển của mình vào một ứng dụng khác thì sẽ không rõ chức năng toàn cầu đó đến từ đâu. Tôi nghe nhận ra tranh luận của bạn mặc dù.
Matthew Payne

Nó chỉ phải được đặt trên phạm vi nếu bạn cần gọi nó từ chế độ xem. Trong bộ điều khiển, bạn có thể gọi nó trực tiếp từ dịch vụ.
mcv

10
Đây là một nhận xét không phải là một câu trả lời
Elliott

Biến $ rootScope luôn null khi làm mới trang trong trường hợp đó bạn sẽ không nhận được hàm. Đó là lý do tại sao nên tiêm dịch vụ và sử dụng tài liệu tham khảo trong ứng dụng.
Ehsan Hafeez

4

AngularJs có " Dịch vụ " và " Nhà máy " chỉ dành cho các sự cố như của bạn. Những thứ này được sử dụng để có một cái gì đó toàn cầu giữa Bộ điều khiển, Chỉ thị, Dịch vụ khác hoặc bất kỳ thành phần angularjs nào khác .. Bạn có thể xác định chức năng, lưu trữ dữ liệu, tạo hàm tính toán hoặc bất cứ điều gì bạn muốn bên trong dịch vụ và sử dụng chúng trong AngularJs Components như toàn cầu .like

angular.module('MyModule', [...])
  .service('MyService', ['$http', function($http){
    return {
       users: [...],
       getUserFriends: function(userId){
          return $http({
            method: 'GET',
            url: '/api/user/friends/' + userId
          });
       }
       ....
    }
  }])

nếu bạn cần thêm

Tìm hiểu thêm về lý do tại sao chúng tôi cần các dịch vụ và nhà máy của AngularJs


0

Tôi mới hơn một chút so với Angular nhưng điều tôi thấy hữu ích để làm (và khá đơn giản) là tôi đã tạo một tập lệnh toàn cầu mà tôi tải lên trang của mình trước tập lệnh cục bộ với các biến toàn cục mà tôi cần truy cập trên tất cả các trang. Trong kịch bản đó, tôi đã tạo một đối tượng gọi là "globalFifts" và thêm các chức năng mà tôi cần để truy cập trên toàn cầu dưới dạng các thuộc tính. ví dụ globalFunctions.foo = myFunc();. Sau đó, trong mỗi tập lệnh cục bộ, tôi đã viết $scope.globalFunctions = globalFunctions;và ngay lập tức tôi có quyền truy cập vào bất kỳ chức năng nào tôi đã thêm vào đối tượng globalFifts trong tập lệnh toàn cầu.

Đây là một chút giải pháp và tôi không chắc nó có giúp gì cho bạn không nhưng nó chắc chắn đã giúp tôi vì tôi có nhiều chức năng và thật đau đớn khi thêm tất cả chúng vào mỗi trang.


1
Tôi chỉ tò mò tại sao các downvote? Tôi là người mới và muốn biết từ các chuyên gia.
Izzy

Có vẻ như một giải pháp làm việc với tôi. Điều duy nhất tôi muốn biện hộ, để đảm bảo phạm vi của bạn được cách ly đủ, là tạo một lớp tiện ích Javascript gốc toàn cầu và treo các phương thức tiện ích của bạn để bạn không vô tình bước vào một tên hàm khác trong biển lớn của những thứ được tiêm bởi Angular.
JE Carter II

Một điều cần lưu ý và có thể tại sao điều này bị hạ cấp, bạn chỉ có thể sử dụng các hàm đó trong các mẫu của mình chứ không phải các mô-đun .ts vì các lệnh gọi hàm của bạn sẽ không giải quyết được trong thời gian biên dịch. Đây là lý do để làm điều đó theo cách "góc cạnh". Nhưng, nếu bạn chỉ muốn thêm các trang trí và như vậy vào các mẫu của mình, một tệp tiện ích toàn cầu là đơn giản và tốt.
JE Carter II
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.