2015-04-24 19 views
10

Tôi biết chúng ta thường vượt qua chức năng để chỉ thị thông qua một phạm vi riêng biệt:Đúng cách để vượt qua chức năng để chỉ thị để thực hiện trong liên kết

.directive('myComponent', function() { 
    return { 
     scope:{ 
      foo: '&' 
     }   
    }; 
}) 

Và sau đó trong mẫu chúng ta có thể gọi chức năng này giống như ví dụ:

<button class="btn" ng-click="foo({ myVal: value })">Submit</button> 

Trong đó myVal là tên của tham số có chức năng foo trong phạm vi chính sẽ mất.

Bây giờ nếu tôi có ý định sử dụng này từ link chức năng thay vì mẫu, tôi sẽ phải gọi nó với: scope.foo()(value), vì scope.foo phục vụ như là một wrapper của hàm gốc. Điều này có vẻ hơi tẻ nhạt với tôi.

Nếu tôi vượt qua chức năng để các myComponent chỉ sử dụng =:

.directive('myComponent', function() { 
    return { 
     scope:{ 
      foo: '=' 
     }   
    }; 
}) 

Sau đó, tôi sẽ có thể chỉ cần sử dụng scope.foo(value) từ chức năng liên kết của tôi. Vậy đây có phải là trường hợp sử dụng hợp lệ để sử dụng chức năng ràng buộc 2 chiều trên các chức năng hay tôi đang thực hiện một số loại hack mà tôi không nên làm?

+0

Tôi không thấy bất kỳ điều gì sai trái với điều này, nhưng có thể xem xét ủy quyền cho một dịch vụ. – Mosho

+0

Tôi do dự vì ràng buộc 2 chiều dường như được thiết kế cho mô hình dữ liệu, nhưng tôi đang sử dụng nó trên một hàm. Nói chung, các chức năng này không được dự kiến ​​sẽ được thay đổi. –

Trả lời

19

Đây là lý do tại sao tôi downvoted câu trả lời.

Trước tiên, bạn không bao giờ nên sử dụng '=' để chuyển tham chiếu hàm tới chỉ thị.

'=' tạo hai đồng hồ và sử dụng chúng để đảm bảo rằng cả phạm vi chỉ thị và tham chiếu phạm vi gốc đều giống nhau (liên kết hai chiều). Đó là một ý tưởng thực sự tồi để cho phép một chỉ thị thay đổi định nghĩa của một hàm trong phạm vi cha mẹ của bạn, đó là những gì xảy ra khi bạn sử dụng kiểu ràng buộc này. Ngoài ra, đồng hồ nên được giảm thiểu - trong khi nó sẽ làm việc, thêm hai đồng hồ $ là không cần thiết. Vì vậy, nó không phải là tốt - một phần của cuộc bỏ phiếu xuống là cho thấy rằng nó được.

Thứ hai - câu trả lời xuyên tạc những gì '&'. & không phải là "một cách ràng buộc". Nó được rằng misnomer chỉ đơn giản bởi vì, không giống như '=', nó không tạo ra bất kỳ $ đồng hồ và thay đổi giá trị của tài sản trong phạm vi chỉ thị không tuyên truyền cho phụ huynh.

Theo các tài liệu:

& hay & attr - cung cấp một cách để thực hiện một biểu thức trong bối cảnh phạm vi mẹ

Khi bạn sử dụng & trong một chỉ thị, nó tạo ra một hàm trả về giá trị của biểu thức được đánh giá dựa vào phạm vi gốc. Biểu thức không phải là một cuộc gọi hàm. Nó có thể là bất kỳ biểu thức góc hợp lệ nào. Ngoài ra, hàm được tạo ra này nhận một đối số đối tượng có thể ghi đè lên giá trị của bất kỳ biến cục bộ nào được tìm thấy trong biểu thức.

Để mở rộng ví dụ của OP, giả phụ huynh sử dụng chỉ thị này theo cách sau:

<my-component foo="go()"> 

Trong chỉ thị (mẫu hoặc chức năng liên kết), nếu bạn gọi

foo({myVal: 42}); 

bạn gì đang làm là đánh giá biểu thức "go()", điều này xảy ra để gọi hàm "go" trên phạm vi gốc, không truyền tham số.

Ngoài ra,

<my-component foo="go(value)"> 

Bạn đang đánh giá khái niệm "đi (giá trị)" trên phạm vi phụ huynh, mà sẽ được về cơ bản gọi $ parent.go ($ parent.value)"

<my-component foo="go(myVal)"> 

Bạn đang đánh giá khái niệm "đi (myVal)", nhưng trước khi biểu thức được đánh giá, myVal sẽ được thay thế bằng 42, vì vậy biểu thức được đánh giá sẽ là "đi (42)".

<my-component foo="myVal + value + go()"> 

Trong trường hợp này, $ scope.foo ({myVal: 42}) sẽ trả lại kết quả của:

42 + $parent.value + $parent.go() 

Về cơ bản, mô hình này cho phép các chỉ thị để "tiêm" biến mà người tiêu dùng của các chỉ thị có thể tùy ý sử dụng trong biểu thức foo.

Bạn có thể làm điều này:

<my-component foo="go"> 

và trong chỉ thị:

$scope.foo()(42) 

$ scope.foo() sẽ đánh giá khái niệm "đi", mà sẽ trả về một tham chiếu đến $ hàm parent.go. Sau đó nó sẽ gọi nó là $ parent.go (42). Nhược điểm của mẫu này là bạn sẽ gặp lỗi nếu biểu thức không đánh giá một hàm.

Lý do cuối cùng cho cuộc bỏ phiếu xuống là xác nhận rằng chỉ thị ng-event sử dụng &. Đây không phải là trường hợp. Không ai trong số được xây dựng trong chỉ thị tạo phạm vi cô lập với:

scope:{ 
} 

Việc thực hiện '& foo' được (đơn giản hóa cho rõ ràng), nắm tới:

$scope.foo = function(locals) { 
    return $parse(attr.foo)($scope.$parent, locals); 
} 

Việc thực hiện ng nhấp chuột là tương tự, nhưng (cũng đơn giản):

link: function(scope, elem, attr) { 
    elem.on('click', function(evt) { 
     $parse(attr.ngClick)(scope, { 
      $event: evt 
     } 
    }); 
} 

Vì vậy, quan trọng cần nhớ là khi bạn sử dụng '&', bạn không phải đi qua một functio n - bạn đang đi qua một biểu thức. Chỉ thị có thể nhận được kết quả của biểu thức này bất kỳ lúc nào bằng cách gọi hàm được tạo ra.

+0

Tôi không nhìn thấy những gì biện minh cho downvote và tôi đã làm tương tự cho cùng một lý do. Một chiều chỉ là một cái tên nhưng tôi giải thích cách nó đánh giá một biểu thức. Bạn, giống như tôi, nhận ra '$ scope.foo() (42)' là một mô hình chống làm cho ít ý nghĩa. Cuối cùng, 'ngRepeat' không tạo ra một phạm vi cô lập (cũng không phải ng-click và được xây dựng trong chỉ thị, tôi cung cấp cho bạn điều đó, xấu của tôi), vì vậy người dùng vẫn có thể sử dụng những gì đã tồn tại trước trên phạm vi của nó. Bạn có thể đã chỉnh sửa câu trả lời của tôi thay vì sao chép các giải thích để phục vụ cộng đồng tốt hơn. – floribon

+2

(chỉnh sửa, tôi loại bỏ downvote của tôi, không chơi trò chơi này) – floribon

+0

@JoeEnzminger Điều gì nếu các chức năng được thông qua là loại gọi lại? I E. nó cần được gọi với các tham số được chỉ định trong hàm 'link' chỉ thị. Có ok để sử dụng '=' trong tình huống như vậy không? – kefir500

3

Hai chiều ràng buộc để vượt qua một hàm là tốt miễn là chức năng của bạn sẽ luôn luôn có cùng các thông số trong cùng một thứ tự. Nhưng cũng vô ích cho mục đích đó.

Ràng buộc một chiều hiệu quả hơn và cho phép gọi một hàm với bất kỳ tham số nào và theo bất kỳ thứ tự nào và cung cấp khả năng hiển thị nhiều hơn trong HTML. Ví dụ chúng ta không thể tưởng tượng ngClick là một chiều hai ràng buộc: đôi khi bạn muốn một cái gì đó giống như <div ng-click="doStuff(var1)"> đến những điều phức tạp hơn như

<div ng-click="doStuff('hardcoded', var1+4); var2 && doAlso(var2)"> 

Xem: bạn có thể thao tác các thông số trực tiếp từ HTML.

Bây giờ tôi cảm thấy như bạn đã hiểu lầm cách sử dụng các ràng buộc một chiều. Nếu bạn thực sự xác định onFoo: '&' trong Chỉ thị của bạn, sau đó từ chức năng liên kết mà bạn nên làm ví dụ:

// assume bar is already in your scope 
scope.bar = "yo"; 
// Now you can call foo like this 
scope.onFoo({extra: 42}); 

Vì vậy, trong HTML của bạn, bạn có thể sử dụng

<div on-foo="doSomething(bar, extra)"> 

Lưu ý rằng bạn có quyền truy cập vào không chỉ tất cả các thuộc tính của phạm vi cô lập chỉ thị (bar), nhưng cũng thêm "người dân địa phương" bổ sung tại thời điểm cuộc gọi (extra).

Ký hiệu của bạn như scope.foo()(value) trông giống như một hack với tôi, đó không phải là cách được khuyến khích để sử dụng các liên kết một chiều.

Lưu ý: một chiều tổ hợp phím thường được sử dụng với một số "sự kiện" các chức năng như when-drop, on-leave, ng-click, when-it-is-loaded vv

+0

Tại sao điều này lại được bình chọn? Người đã làm nó, bạn có thể vui lòng chia sẻ một số cái nhìn sâu sắc? –

+0

Cảm ơn @Xavier_Ex, tôi cũng tò mò về điều đó. Nếu tôi sai, tôi mong muốn tìm hiểu chính xác những gì. – floribon

Các vấn đề liên quan