2015-06-09 27 views
9

Poniższy kontroler działa bez problemu.Metoda `bind` JavaScript nie działa zgodnie z oczekiwaniami

app.controller('foo', ['$scope',function ($scope) { 
     $scope.delete = function(){ 
      bar($scope); 
     } 
    }]); 

Próbowałem zrobić to trochę czystsze za pomocą bind:

app.controller('foo', ['$scope',function ($scope) { 
     $scope.delete = bar.bind(null, $scope); 
    }]); 

Niestety, ta forma nie działa zgodnie z oczekiwaniami i $scope jest zawsze dostarczane ze starą wersją $ zakres w metodzie związanej (bar tutaj), nawet po zmianie zakresu, aby odnosić się do innej wartości. Co jest z tym nie tak?

Co jeszcze?

Jeśli nie powinienem używać tutaj bind, jaka jest alternatywa?

+0

Co znajduje się wewnątrz Util? Nie mogę myśleć, dlaczego miałbyś to zrobić. –

+1

Wydaje mi się niewłaściwe użycie powiązania. –

+1

Czy problem polega na tym, że wartość * jest * podawana do '$ scope.delete', ale jest to * stara * wartość? A może funkcja całkowicie zawodzi (lub nie jest w ogóle dostarczana)? – apsillers

Odpowiedz

10

Zakładam, że Twój problem jest to, że granica Util.bar jest zawsze dostarczane ze starą wersją $scope nawet po $scope uległa zmianie w odniesieniu do innej wartości.

bind wiąże wartości, a nie zmiennych. Wiążesz bieżącą wartość z $scope na Util.bar. Z drugiej strony, twój pierwszy styl zmusza identyfikator $scope do wartości do (lub, naprawdę, rekord zmiennej zewnętrznej) za każdym razem, gdy funkcja działa.

Jeśli $scope zmienia się w celu odniesienia się do zupełnie innej wartości, musisz użyć pierwszego formularza. .bind(null, $scope) natychmiast rozwiąże wartość $scope i użyje tej wartości na zawsze, podczas gdy pierwszy formularz bez bind rozwiąże wartość $scope z wartością za każdym razem, gdy ta funkcja zostanie uruchomiona.

+0

Dzięki, jaka jest alternatywna metoda dla drugich kodów. – PHPst

+0

@PHPst Alternatywą jest to, co już robisz w swoim pierwszym przykładzie. Czy możesz edytować, aby wyjaśnić, dlaczego to nie wystarczy? – apsillers

+0

jak @apsillers powiedział w 'bind' $ scope zostaje rozwiązany i zostaje użyty w kolejnych wywołaniach czystszy sposób jest pierwszy, ale wciąż chce się wiązać, następnie użyj tej app.controller ('foo', ['$ scope', function ($ scope) { $ scope.delete = function() {bar.bind (null, $ scope);} }]); – vinayakj

2

Czy jesteś pewien, że bar nie używa niczego od Util? Wykonaj:

app.controller('foo', ['$scope',function ($scope) { 
    $scope.delete = Util.bar.bind(Util, $scope); 
}]); 
1

Jak wspomniano w powyższej odpowiedzi na temat apsillerów, metoda wiązania jest natychmiastowo analizowana po przypisaniu - więc bieżącą wartość $ scope jest wiązana jako argument do przekazania funkcji paska. Jeśli chodzi o "czystszą" alternatywę, nie widzę powodu, dla którego potrzebujesz czegoś "czystszego": chcesz przypisać $ scope.delete jako funkcję, która wywołuje pasek z bieżącą wartością $ scope, którą twój obecny kod robi do T. Jeśli wciąż szukasz czegoś nieco szczuplejszego, możesz zawsze zastosować tłustą składnię ES6 (ale potrzebujesz transpilatora takiego jak babel) - Twój kod będzie wyglądał następująco:

app.controller('foo', ['$scope',function ($scope) { 
    $scope.delete =() => bar($scope); 
}]); 
4

Spójrz na to Plunker.

$scope.delete1 = function(){ 
     bar($scope); 
    }; 

    $scope.delete2 = bar.bind(null, $scope); 

    $scope.delete3 = function(){ 
     bar(this); 
    }; 

Dla mnie wydaje się zachowywać dokładnie tak jak powinien: delete1 i delete2 wydają się zrobić to samo na obu rodzicem a dzieckiem kontrolera. Usuń 3 zachowuje się inaczej - przyczyna jest wyjaśniona bardzo ładnie w tej odpowiedzi: controller's scope

Być może możesz dokładnie określić, które zachowanie (przypadek) uważasz za nieprawidłowe. Linki powrotne są tak, że można opuścić stronę kontrolera, a następnie wrócić do nowej instancji kontrolera (i nowego zakresu - jak widać z $ scope. $ Id).

-1

jak @apsillers powiedział w zakresie powiązań $ zostanie rozwiązany i przyzwyczaja w kolejnych połączeń, tak przejrzysty sposób jest pierwszym, ale wciąż Jeśli chcesz użyć wiążą następnie użyć

app.controller('foo', ['$scope',function ($scope) { 
    $scope.delete = function(){ 
     bar.bind(null, $scope); 
    } 
}]); 
+0

Po wywołaniu 'delete' po prostu tworzy wartość funkcji, która jest wyrzucana. –