观察集合吞噬正在观察的属性

8 浏览
0 Comments

观察集合吞噬正在观察的属性

有两个属性selCountrysearchText。有一个监视器来监视这两个变量。第一个属性绑定到一个选择元素,另一个属性绑定到一个输入文本框。

我期望的行为是:如果我改变下拉框的值,文本框应该清空,反之亦然。然而,由于我编写的监视器的方式,第一次按键(在与选择元素交互后)会吞噬掉按键操作。

肯定有一种Angular的方式可以告诉Angular不要处理这些变量的变化,但仍然允许它们的变化传播到视图中...?

$scope.$watchCollection('[selCountry, searchText]', function(newValues, oldValues, scope){
    console.log(newValues, oldValues, scope.selCountry, scope.searchText);
    var newVal;
    if(newValues[0] !== oldValues[0]) {
      console.log('1');
      newVal = newValues[0];
      scope.searchText = '';
    }
    else if(newValues[1] !== oldValues[1]) {
      console.log('2');
      newVal = newValues[1];
      scope.selCountry = '';
    }
    $scope.search = newVal;
    var count = 0;
    if(records)
      records.forEach(function(o){
        if(o.Country.toLowerCase().indexOf(newVal.toLowerCase())) count++;
      });
    $scope.matches = count;
  });

Plunk

0
0 Comments

问题出现的原因是在ng-change事件中,当选择了一个国家或者输入了搜索文本时,会调用searched()函数。在searched()函数中,首先将$scope.countries数组重置为$scope.allCountries数组,然后根据搜索文本进行过滤,最后将过滤后的结果赋值给$scope.countries数组。这样做的结果是,每次选择一个国家或者输入搜索文本时,$scope.countries数组都会被不断地修改和赋值,从而导致watchers频繁触发,性能下降。

解决方法是利用lodash库来简化数组/对象的操作,并优化代码逻辑。具体的解决方法如下:

1. 在HTML模板中引入lodash库:


2. 在JavaScript代码中使用lodash库的函数来简化操作:

angular.module('myapp',[])
  .controller('MainCtrl', function($scope, $http) {
    $http.get('http://www.w3schools.com/angular/customers.php').then(function(response){
      $scope.allCountries = _.uniq(_.pluck(_.sortBy(response.data.records, 'Country'), 'Country'));
      $scope.countries = $scope.allCountries;
    });
    $scope.searched = _.debounce(function() {
      $scope.countries = $scope.allCountries;
      if ($scope.search) {
        var result = _.filter($scope.countries, function(country) {
          return country.toLowerCase().indexOf($scope.search.toLowerCase()) != -1;
        });            
        $scope.countries = result;
      }
    }, 300);
  });

通过使用_.debounce函数,可以将searched()函数的执行延迟300毫秒,从而减少watchers触发的次数。此外,使用lodash库的函数可以简化对数组的操作,提高代码的可读性和性能。

通过以上的修改,可以解决watchcollection swallowing an attribute being watched的问题,并提升应用的性能。

0
0 Comments

问题原因:问题出现的原因是在watchCollection事件处理程序中捕捉到了被观察属性的变化,但当改变第二个变量的值时,它也被watchCollection处理程序捕捉到并清除该值。这是因为当在作用域对象上改变selCountry的值时,watchCollection也被调用,然后它说“好的,我现在需要清除searchText”。

解决方法:可以通过使用ng-change指令来捕捉变化,并使用onChange事件处理程序来修复这个问题。尝试以下方法:

// 注释或删除当前的watchCollection事件处理程序
// 在JS文件中添加以下内容
$scope.searchTextChange = function(){
  $scope.selCountry = '';
  $scope.search = $scope.searchText;
  search($scope.search);
};
$scope.selectCountryChange = function(){
  $scope.searchText = '';
  $scope.search = $scope.selCountry;
  search($scope.search);
};
function search(value){
  var count = 0;
  if(records)
    records.forEach(function(o){
      if(o.Country.toLowerCase().indexOf(value.toLowerCase())) count++;
    });
  $scope.matches = count;
}

在HTML文件中添加以下内容:




新的plunker链接: [http://plnkr.co/edit/xCWxSM3RxsfZiQBY76L6?p=preview](http://plnkr.co/edit/xCWxSM3RxsfZiQBY76L6?p=preview)

0