Angular JS: Nhu cầu của chức năng liên kết của chỉ thị là gì khi chúng ta đã có bộ điều khiển của chỉ thị với phạm vi?


199

Tôi cần thực hiện một số thao tác trên phạm vi và mẫu. Dường như tôi có thể làm điều đó trong cả linkchức năng hoặc controllerchức năng (vì cả hai đều có quyền truy cập vào phạm vi).

Khi nào thì tôi phải sử dụng linkchức năng chứ không phải bộ điều khiển?

angular.module('myApp').directive('abc', function($timeout) {
    return {
        restrict: 'EA',
        replace: true,
        transclude: true,
        scope: true,
        link: function(scope, elem, attr) { /* link function */ },
        controller: function($scope, $element) { /* controller function */ }
    };
}

Ngoài ra, tôi hiểu rằng đó linklà thế giới không góc cạnh. Vì vậy, tôi có thể sử dụng $watch, $digest$apply.

Tầm quan trọng của linkhàm là gì, khi chúng ta đã có bộ điều khiển?


9
Ý bạn là gì bởi " Ngoài ra, tôi hiểu rằng liên kết là thế giới không góc cạnh. Vì vậy, tôi có thể sử dụng $watch, $digest$apply. "?
musically_ut

2
Bên trong linkchúng ta không thấy bất kỳ phép thuật góc cạnh nào. tức là không có ràng buộc 2 chiều, v.v ... Chỉ cần chúng ta có sẵn api của các góc.
Joly Julum

Câu trả lời:


299

Sau khi tôi ban đầu đấu tranh với các linkcontrollercác chức năng và đọc khá nhiều về họ, tôi nghĩ bây giờ tôi có câu trả lời.

Trước tiên hãy hiểu ,

Làm thế nào để chỉ thị góc làm việc một cách ngắn gọn:

  • Chúng tôi bắt đầu với một mẫu (dưới dạng chuỗi hoặc được tải vào chuỗi)

    var templateString = '<div my-directive>{{5 + 10}}</div>';

  • Bây giờ, điều này templateStringđược bao bọc như một yếu tố góc cạnh

    var el = angular.element(templateString);

  • Với el, bây giờ chúng tôi biên dịch nó $compileđể lấy lại chức năng liên kết .

    var l = $compile(el)

    Đây là những gì xảy ra,

    • $compile đi qua toàn bộ khuôn mẫu và thu thập tất cả các chỉ thị mà nó nhận ra.
    • Tất cả các chỉ thị được phát hiện được biên soạn đệ quylink chức năng được thu thập.
    • Sau đó, tất cả các linkchức năng được bọc trong một linkchức năng mới và được trả lại là l.
  • Cuối cùng, chúng tôi cung cấp scopechức năng cho chức năng l(liên kết) này để thực hiện thêm các chức năng liên kết được bao bọc với điều này scopevà các yếu tố tương ứng của chúng.

    l(scope)

  • Điều này thêm nút templatenhư một nút mới vào DOMvà gọi controllerthêm đồng hồ của nó vào phạm vi được chia sẻ với mẫu trong DOM.

nhập mô tả hình ảnh ở đây

So sánh biên dịch vs liên kết với bộ điều khiển :

  • Mỗi lệnh chỉ được biên dịch một lần và chức năng liên kết được giữ lại để sử dụng lại. Do đó, nếu có điều gì đó áp dụng cho tất cả các trường hợp của lệnh thì nên được thực hiện bên trong compilechức năng của lệnh.

  • Bây giờ, sau khi biên dịch, chúng ta có linkhàm được thực thi trong khi đính kèm mẫu vào DOM . Vì vậy, do đó chúng tôi thực hiện mọi thứ cụ thể cho mọi trường hợp của lệnh. Ví dụ: đính kèm các sự kiện , thay đổi mẫu dựa trên phạm vi , v.v.

  • Cuối cùng, bộ điều khiển có nghĩa là có sẵn để sống và phản ứng trong khi chỉ thị hoạt động trênDOM (sau khi được đính kèm). Vì thế:

    (1) Sau khi thiết lập chế độ xem [ V ] (tức là mẫu) có liên kết. $scopelà [ M ] $controllercủa chúng tôi và là [ C ] của chúng tôi trong MVC

    (2) Tận dụng ràng buộc 2 chiều với $ scope bằng cách thiết lập đồng hồ.

    (3) $scopeđồng hồ dự kiến ​​sẽ được thêm vào bộ điều khiển vì đây là thứ đang xem mẫu trong thời gian chạy.

    (4) Cuối cùng, controllercũng được sử dụng để có thể giao tiếp giữa các chỉ thị liên quan. (Giống như myTabsví dụ trong https://docs.angularjs.org/guide/directive )

    (5) Đúng là chúng ta cũng có thể thực hiện tất cả điều này trong linkchức năng nhưng đó là về việc phân tách các mối quan tâm .

Do đó, cuối cùng chúng ta có những thứ sau đây phù hợp với tất cả các mảnh một cách hoàn hảo:

nhập mô tả hình ảnh ở đây


5
Tôi cũng thấy bài viết này hữu ích để hiểu thứ tự thực hiện ở đây: Nitty-gritty của các hàm biên dịch và liên kết bên trong các chỉ thị AngularJS
BobbyA 21/07/2015

4
Giải thích tuyệt vời. Muốn đề cập rằng bộ điều khiển được gọi trước chức năng liên kết.
jsbisht

38
bộ điều khiển được thực thi trước khi liên kết
Royi Namir

10
Nó làm tôi bực mình rằng Stack Overflow yêu cầu chỉnh sửa ít nhất 6 ký tự, do đó không cho phép tôi sửa lỗi chính tả của câu trả lời trong câu trả lời này.
dùng1886323

79

Tại sao cần bộ điều khiển

Sự khác biệt giữa linkcontroller phát huy tác dụng khi bạn muốn lồng các lệnh trong DOM của mình và hiển thị các hàm API từ chỉ thị cha mẹ sang các lệnh lồng nhau.

Từ các tài liệu :

Thực hành tốt nhất: sử dụng bộ điều khiển khi bạn muốn đưa API ra các chỉ thị khác. Nếu không sử dụng liên kết.

Giả sử bạn muốn có hai chỉ thị my-formmy-text-inputvà bạn muốn my-text-inputchỉ thị để chỉ xuất hiện bên trongmy-form và ở nơi nào khác.

Trong trường hợp đó, bạn sẽ nói trong khi xác định lệnh my-text-input rằng nó yêu cầu bộ điều khiển từ parentphần tử DOM sử dụng đối số request, như thế này : require: '^myForm'. Bây giờ bộ điều khiển từ phần tử cha sẽ injectedvào linkhàm làm đối số thứ tư, theo sau$scope, element, attributes . Bạn có thể gọi các chức năng trên bộ điều khiển đó và liên lạc với chỉ thị cha.

Hơn nữa, nếu không tìm thấy bộ điều khiển như vậy, một lỗi sẽ xuất hiện.

Tại sao nên sử dụng liên kết

Không có nhu cầu thực sự để sử dụng linkhàm nếu người ta xác định controllertừ$scope có sẵn trên controller. Hơn nữa, trong khi xác định cả hai linkcontroller, người ta không cần phải cẩn thận về thứ tự gọi của hai ( controllerđược thực hiện trước đó).

Tuy nhiên, theo cách Angular , hầu hết các thao tác DOM và ràng buộc 2 chiều sử dụng $watchersthường được thực hiện trong linkhàm trong khi API cho trẻ em và $scopethao tác được thực hiện trong controller. Đây không phải là một quy tắc khó và nhanh, nhưng làm như vậy sẽ làm cho mã trở nên mô đun hơn và giúp tách các mối quan tâm (bộ điều khiển sẽ duy trì directivetrạng thái và linkchức năng sẽ duy trì các DOMràng buộc + bên ngoài).


Thật tuyệt. Bây giờ, bạn có thể giúp tôi với phần thứ hai của câu hỏi?
Joly Julum

Ý tôi là, vì chúng ta có bộ điều khiển tồn tại có thể được sử dụng để liên lạc với các chỉ thị khác. Vì vậy, nhu cầu là linkgì?
Joly Julum

1
Câu trả lời của bạn bằng cách nào đó không trả lời câu hỏi thực tế.
Joly Julum

1
Có bất kỳ vấn đề xảy ra khi chúng ta xác định một controller? Tại sao tôi muốn phát minh ra một chức năng hoàn toàn mới chỉ để tránh xác định bộ điều khiển?
Joly Julum

1
có vẻ như @scalaGirl s Link không còn hoạt động nữa
Minato

17

Các controllerchức năng / đối tượng đại diện cho một sự trừu tượng MVC (MVC). Mặc dù không có gì mới để viết về MVC, nhưng đây vẫn là một ưu điểm quan trọng nhất của góc cạnh: chia các mối quan tâm thành các phần nhỏ hơn. Và đó là nó, không có gì hơn, vì vậy nếu bạn cần để phản ứng về Modelnhững thay đổi đến từ Viewnhững Controllerlà quyền con người để làm công việc đó.

Câu chuyện về linkchức năng là khác nhau, nó đến từ quan điểm khác nhau sau đó là MVC. Và thực sự cần thiết, một khi chúng ta muốn vượt qua ranh giới của một controller/model/view (mẫu) .

Hãy bắt đầu với các tham số được truyền vào linkhàm:

function link(scope, element, attrs) {
  • phạm vi là một đối tượng phạm vi góc.
  • phần tửphần tử được bọc jqLite mà lệnh này khớp.
  • attrs là một đối tượng có tên thuộc tính được chuẩn hóa và các giá trị tương ứng của chúng.

Để đưa linkvào bối cảnh, chúng ta nên đề cập rằng tất cả các chỉ thị đang trải qua các bước quy trình khởi tạo này: Biên dịch , Liên kết . Một trích đoạn từ cuốn sách Brad Green và Shyam Seshadri Angular JS :

Biên dịch pha (một người chị em của liên kết, hãy đề cập đến nó ở đây để có được một hình ảnh rõ ràng):

Trong giai đoạn này, Angular đi bộ DOM để xác định tất cả các chỉ thị đã đăng ký trong mẫu. Đối với mỗi lệnh, sau đó nó biến đổi DOM dựa trên các quy tắc của lệnh (khuôn mẫu, thay thế, chuyển mã, v.v.) và gọi hàm biên dịch nếu nó tồn tại. Kết quả là một hàm mẫu được biên dịch,

Liên kết giai đoạn :

Để làm cho khung nhìn động, Angular sau đó chạy một hàm liên kết cho mỗi lệnh. Các hàm liên kết thường tạo các trình nghe trên DOM hoặc mô hình. Những người nghe này giữ cho quan điểm và mô hình đồng bộ mọi lúc.

Một ví dụ hay về cách sử dụng linkcó thể tìm thấy ở đây: Tạo Chỉ thị tùy chỉnh . Xem ví dụ: Tạo Chỉ thị Thao tác DOM , chèn "ngày giờ" vào trang, được làm mới mỗi giây.

Chỉ là một đoạn rất ngắn từ nguồn phong phú đó ở trên, cho thấy sự thao túng thực sự với DOM. Có chức năng được nối với dịch vụ $ timeout, và nó cũng bị xóa trong lệnh gọi hàm hủy của nó để tránh rò rỉ bộ nhớ

.directive('myCurrentTime', function($timeout, dateFilter) {

 function link(scope, element, attrs) {

 ...

 // the not MVC job must be done
 function updateTime() {
   element.text(dateFilter(new Date(), format)); // here we are manipulating the DOM
 }

 function scheduleUpdate() {
   // save the timeoutId for canceling
   timeoutId = $timeout(function() {
     updateTime(); // update DOM
     scheduleUpdate(); // schedule the next update
   }, 1000);
 }

 element.on('$destroy', function() {
   $timeout.cancel(timeoutId);
 });

 ...

3
Bạn dường như đã so sánh compilerlink. Họ đặt câu hỏi là tại sao linkkhi chúng ta đã cócontroller
Yrif Julum

Tôi đã mở rộng câu trả lời để mô tả ngay cả bộ điều khiển chi tiết hơn. Bây giờ các khái niệm về controllervs linknên rõ ràng hơn ...
Radim Köhler

1
Tôi có thể tìm cách giải quyết cho lời giải thích đó. Nhưng nó có vẻ là loại mờ ở đó. Sẽ thật tuyệt nếu ai đó từ chính đội ngũ góc cạnh có thể phát biểu cho nó, chiếu nơi họ thấy nó sẽ đến - với linkhoặc controller.
Joly Julum

1
Đó là phần duy nhất tôi muốn hiểu (Khi nào nó không đủ?). Thêm vào đó, tôi nhận được tất cả các lợi ích của góc cạnh controllerlinktương đối xấu. Vì vậy, đội góc cạnh phải có lý do chính đáng cho nó thay vì chỉ là một lựa chọn.
Joly Julum

1
Câu hỏi: Khi điều khiển không đủ? Trả lời: Khi bạn cần trải nghiệm Angular, chẳng hạn như sử dụng plugin JQuery hoặc sử dụng tính năng JQlite như được đề cập trong tài liệu ( docs.angularjs.org/api/ng/feft/angular.element :) , thì bạn sẽ cần liên kết
Hasteq
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.