Parent 独立范围在 Firefox 中仅更新一次

Parent isolated scope updated only once in Firefox

我正在尝试在 child 自定义指令中触发 onchange 事件时更新 parents 范围变量。 我在 child 指令中使用的事件是一个 input 文件,是由 jqLit​​e 触发的 onchange。这意味着, Angular 范围外的操作。为了更新范围,我使用了 scope.$evalAsync 函数(也尝试了 $timeoutscope.$apply)。在 parents 自定义指令中,我使用 $watch 函数作为监听器。

请查看jsfiddle完整示例

标记

<div ng-app='myApp'>
  <parent></parent>
</div>

脚本

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

myApp.directive('parent', function() {

  return {
    restrict: 'E',
    template: '<div class="parent">Parent' + '<span class="file-name">{{selectedFileName}}</span>' + '<child files="files"></child>' + '</div>',
    scope: {
      files: '='
    },
    link: function(scope){
        scope.$watch('files', function(newVal) {
        if (newVal && newVal.length > 0) {
          scope.selectedFileName = "selected file name: " + newVal[0].name;
        }
      });
    }
  };
});

myApp.directive('child', function() {

  return {
    restrict: 'E',
    template: '<div class="child">Child<br />' + '<span class="file-name">{{selectedFileName}}</span>' + '<file-upload files="files"></file-upload>' + '</div>',
    scope: {
      files: '='
    },
    link: function(scope) {
      scope.$watch('files', function(newVal) {
        if (newVal && newVal.length > 0) {
          scope.selectedFileName = "selected file name: " + newVal[0].name;
        }
      });
    }
  };
});

myApp.directive('fileUpload', function() {

  return {
    restrict: 'E',
    template: '<input type="file" />',
    scope: {
      files: '='
    },
    link: function(scope, element) {
      element.bind('change', function(e) {
        scope.$evalAsync(function() {
          scope.files = (e.srcElement || e.target).files;
        });
      });
    }
  };
});

在示例中,每次我选择新文件时,parents 范围变量 files 都会完美更新,并调用其 $watch 函数。

问题是在 Firefox 中 parents 作用域 $watch 函数只被调用一次。只有第一次。

提前致谢

已解决。

多亏了这个 post,它告诉我问题是我正在使用 $watch

根据以下解释:

By default, $watch does not check for object equality, but just for reference

在我的例子中,我正在观察一个数组。它的引用没有改变,这就是 $watch 函数没有被调用的原因。实际上改变的只是数组的内部属性。因此,解决方案是改用 $watchCollection(),即:

Shallow watches the properties of an object and fires whenever any of the properties change ... ...for arrays this implies watching the array items

为什么 $watch 在 Firefox 中不工作,但在 Chrome 和 IE 中工作得很好?答案是关于文件输入 change 事件的实现。事实上,Firefox 总是触发 change 事件,即使在向它上传相同的文件时也是如此。这是 而不是 Chrome 和 IE 中的行为。因此,Firefox 显然在每个 change 事件上都保留相同的 files 数组对象,并且只更改其内部项目。 Chrome 和 IE,显然,在每个 change 事件上创建新的 files 对象,但在上传同名文件时不会触发该事件。