Parent 独立范围在 Firefox 中仅更新一次
Parent isolated scope updated only once in Firefox
我正在尝试在 child 自定义指令中触发 onchange
事件时更新 parents 范围变量。
我在 child 指令中使用的事件是一个 input
文件,是由 jqLite 触发的 onchange
。这意味着,
Angular 范围外的操作。为了更新范围,我使用了 scope.$evalAsync
函数(也尝试了 $timeout
和 scope.$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
对象,但在上传同名文件时不会触发该事件。
我正在尝试在 child 自定义指令中触发 onchange
事件时更新 parents 范围变量。
我在 child 指令中使用的事件是一个 input
文件,是由 jqLite 触发的 onchange
。这意味着,
Angular 范围外的操作。为了更新范围,我使用了 scope.$evalAsync
函数(也尝试了 $timeout
和 scope.$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
对象,但在上传同名文件时不会触发该事件。