AngularJS页面双击输入框后数据才显示的问题求助
问题场景
你现在的代码逻辑是这样的:控制器里用findEmployeeById方法,通过jQuery的$.getJSON获取员工数据,然后在employee-detail.html里用ng-init调用这个方法,把employee.firstName绑定到输入框。但奇怪的是,数据不会自动显示,得双击输入框之后才出来。
你的控制器代码:
$scope.findEmployeeById = function() { if( !angular.isUndefined($location.search().employeeId) ) { $.getJSON( servicefindEmployeeById+$location.search().employeeId, function( data ) { $scope.employee = data; }); } }
页面代码:
<html> <body ng-init="findEmployeeById()"> <input type="text" ng-model="employee.firstName"/> </body> </html>
问题原因
核心问题出在jQuery的异步操作脱离了AngularJS的上下文:
AngularJS靠自身的脏检查机制来监听$scope的数据变化,从而更新视图。但$.getJSON是jQuery的异步方法,它的回调函数运行在Angular的上下文之外。当你在回调里给$scope.employee赋值时,Angular根本不知道数据变了,所以不会自动更新视图。而双击输入框的操作会触发Angular的内部事件(比如焦点变化),这时候Angular会执行一次脏检查,才发现$scope.employee已经有值了,于是把数据渲染到输入框里。
解决办法
这里有两种靠谱的解决方案,推荐优先用第一种:
方案1:改用AngularJS自带的$http服务(推荐)
Angular官方的$http服务是专门为Angular生态设计的,它的回调函数会自动运行在Angular的上下文里,请求完成后会自动触发脏检查,视图就能立刻更新。
修改后的控制器代码:
$scope.findEmployeeById = function() { if( !angular.isUndefined($location.search().employeeId) ) { $http.get(servicefindEmployeeById + $location.search().employeeId) .then(function(response) { $scope.employee = response.data; }); } }
注意:要确保你的控制器已经注入了$http服务,比如:
app.controller('YourController', ['$scope', '$location', '$http', function($scope, $location, $http) { // 你的代码逻辑 }]);
方案2:如果一定要用jQuery,手动触发脏检查
要是你因为某些原因必须保留$.getJSON,那就在更新$scope数据后,手动告诉Angular去检查数据变化。这里有两种方式:
方式A:使用$scope.$apply()
把赋值操作放到$scope.$apply()的回调里,强制Angular执行脏检查:
$scope.findEmployeeById = function() { if( !angular.isUndefined($location.search().employeeId) ) { $.getJSON( servicefindEmployeeById+$location.search().employeeId, function( data ) { $scope.$apply(function() { $scope.employee = data; }); }); } }
方式B:使用$timeout(更安全)
$timeout是Angular的服务,它会把代码放到下一次脏检查周期执行,避免直接调用$apply()可能出现的「$digest already in progress」错误:
// 记得先在控制器里注入$timeout $scope.findEmployeeById = function() { if( !angular.isUndefined($location.search().employeeId) ) { $.getJSON( servicefindEmployeeById+$location.search().employeeId, function( data ) { $timeout(function() { $scope.employee = data; }); }); } }
内容的提问来源于stack exchange,提问作者Sikandar Sahab

