2016-04-29 17 views
5

Hôm nay tôi gặp phải một số hành vi thực sự kỳ lạ trong AngularJS sử dụng đồng hồ $. Tôi đơn giản hóa mã của tôi như ví dụ sau:

https://jsfiddle.net/yLeLuard/

Ví dụ này chứa một dịch vụ mà sẽ theo dõi của một biến state. Các chỉ thị được sử dụng để liên kết sự kiện nhấp chuột với DOM thay đổi biến số state thông qua dịch vụ.

Có hai vấn đề trong ví dụ này:

  1. Nút đóng đầu tiên (với ng-click tài sản trên nó) chỉ thay đổi trạng thái trên nhấp chuột thứ hai
  2. Hai nút mà không ng- nhấp chuột không thay đổi nhà nước ở tất cả các

main.html

<div ng-controller="main"> 
    State: {{ api.isOpen | json }} 
    <div ng-click="" open> 
    <button>Open - Working fine</button> 
    </div> 
    <div ng-click="" close> 
    <button>Close - Works, but only on second click</button> 
    </div> 
    <div open> 
    <button>Open - Not Working</button> 
    </div> 
    <div close> 
    <button>Close - Not Working</button> 
    </div> 
</div> 

main.js

var myApp = angular.module('myApp', []); 

myApp.controller('main', ['$scope', 'state', function($scope, state) { 
    $scope.api = state; 

    $scope.api.isOpen = false; 

    $scope.$watch('api.isOpen', function() { 
    console.log('state has changed'); 
    }); 
}]); 

myApp.directive('open', ['state', function(state) { 
    return { 
    restrict: 'A', 
    scope: {}, 
    replace: true, 
    template: '<button>Open</button>', 
    link: function(scope, element) { 
     element.on('click', function() { 
     state.isOpen = true; 
     }); 
    } 
    }; 
}]); 


myApp.directive('close', ['state', function(state) { 
    return { 
    restrict: 'A', 
    scope: {}, 
    replace: true, 
    template: '<button>Close</button>', 
    link: function(scope, element) { 
     element.on('click', function() { 
     state.isOpen = false; 
     }); 
    } 
    }; 
}]); 

myApp.service('state', function() { 
    return { 
    isOpen: null 
    }; 
}); 
+2

cách bạn loại bỏ chỉ thị của mình mở và đóng và thay vào đó sử dụng 'ng-click =" api.isOpen = true "' và 'ng-click =" api.isOpen = false "'. Tốt hơn là nên sử dụng chỉ thị gốc thay vì ràng buộc sự kiện 'click' – floribon

+0

@floribon có nhiều chức năng hơn trong chỉ thị thực của tôi, do đó tôi không thể sử dụng ng-click. Bên cạnh đó, tôi thực sự muốn biết tại sao điều này không hoạt động đúng. – Pascal

+0

Tôi hiểu. Sau đó loại bỏ 'ng-click' và chỉ giữ chỉ thị của bạn. Điều gì đã xảy ra là 'ng-click' đã kích hoạt một phạm vi tiêu hóa vì vậy nó có vẻ là loại làm việc nhưng không đáng tin cậy – floribon

Trả lời

4

Đó là bởi vì bạn đang sử dụng một người biết lắng nghe sự kiện bản địa trên click. Sự kiện này là không đồng bộ và ra khỏi chu trình tiêu hóa góc, vì vậy bạn cần phải phân loại thủ công phạm vi.

myApp.directive('open', ['state', function(state) { 
    return { 
    restrict: 'A', 
    scope: {}, 
    link: function(scope, element) { 
     element.on('click', function() { 
     scope.$apply(function() { 
      state.isOpen = true; 
     }); 
     }); 
    } 
    }; 
}]); 

Fixed fiddle: https://jsfiddle.net/7h95ct1y/

Tôi sẽ đề nghị thay đổi nhà nước trực tiếp trong ng-click: ng-click="api.isOpen = true"

+0

Có vẻ như đây là câu trả lời đúng! Cảm ơn rất nhiều. Đây là một ví dụ làm việc của vấn đề của tôi bằng cách sử dụng giải pháp của bạn: https://jsfiddle.net/yLeLuard/2/ – Pascal

0

Bạn nên đặt chức năng liên kết của bạn như một chức năng pre-link, điều này giải quyết vấn đề của nhấp chuột thứ hai.

https://jsfiddle.net/2c9pv4xm/

myApp.directive('close', ['state', function(state) { 
    return { 
    restrict: 'A', 
    scope: {}, 
    link:{ 
    pre: function(scope, element) { 
     element.on('click', function() { 
     state.isOpen = false; 
     console.log('click', state); 
     }); 
    } 
    } 
    }; 
}]); 

Đối với các phần không làm việc, bạn đang đặt chỉ thị của bạn trên div, vì vậy khi bạn click vào div nó hoạt động nhưng không phải trên nút. Chỉ thị mở của bạn phải ở trên nút.

Chỉnh sửa: người nhận xét khác đề nghị bạn thay đổi trạng thái trực tiếp trong ng-click. Tôi sẽ không khuyên bạn nên nó, nó có thể làm việc trong trường hợp này, nhưng nếu bạn đang bị ràng buộc để có nhiều hơn một phân công để làm nó không khả thi.

+0

Như thế này? https://jsfiddle.net/2c9pv4xm/1/ Tôi không thấy dịch vụ cập nhật. – Pascal

+0

Sai lầm của tôi. Tôi đọc mã của bạn quá nhanh.Đặt liên kết như các công trình trước, tuy nhiên sự hiện diện của ng-click dường như là bắt buộc vì một lý do nào đó. Áp dụng $ là không thực sự khuyến khích, nó buộc một chu kỳ tiêu hóa mới và nếu ứng dụng của bạn có chứa rất nhiều người xem nó có thể làm chậm tiêu hóa của toàn bộ trang. Nếu bạn đang sử dụng chỉ ng-click tôi sẽ đặt nó trong một chức năng. – Seedy