Javascript 为什么ng src不会触发AngularJS中的某些属性更改?
我有一个示例指令,用于监视元素中的更改,例如offsetWidth 如果我将该指令应用于通过src属性加载url的img元素,则一切正常 如果我将该指令应用于通过ng src属性加载url的img元素,则offsetWidth不会得到更新 HTML: 更新: 我在下面应用了Buu Nguyen的解决方案,以确保正确的变化受到关注,但似乎存在时间问题。当多次重新加载页面时,我注意到有时值会正确更新,有时则不会 更新的javascript:Javascript 为什么ng src不会触发AngularJS中的某些属性更改?,javascript,angularjs,angularjs-directive,Javascript,Angularjs,Angularjs Directive,我有一个示例指令,用于监视元素中的更改,例如offsetWidth 如果我将该指令应用于通过src属性加载url的img元素,则一切正常 如果我将该指令应用于通过ng src属性加载url的img元素,则offsetWidth不会得到更新 HTML: 更新: 我在下面应用了Buu Nguyen的解决方案,以确保正确的变化受到关注,但似乎存在时间问题。当多次重新加载页面时,我注意到有时值会正确更新,有时则不会 更新的javascript: angular.module('test', []).
angular.module('test', []).
directive('testing', function() {
return function(scope, element, attr) {
scope.$watch(
'element.offsetWidth',
function(newVal, oldVal) {
scope.offsetwidth = element[0].offsetWidth
}
)
scope.$watch(
'element.offsetLeft',
function(newVal, oldVal) {
scope.offsetleft = element[0].offsetLeft
}
)
}
});
angular.module('test', []).
directive('testing', function() {
return function(scope, element, attr) {
scope.$watch(
function() {
return element[0].offsetWidth
},
function(newVal, oldVal) {
scope.offsetwidth = element[0].offsetWidth
}
)
scope.$watch(
function() {
return element[0].offsetLeft
},
function(newVal, oldVal) {
scope.offsetleft = element[0].offsetLeft
}
)
}
});
您无法查看
元素的属性,因为它不在范围内。解决此问题的一种方法是将watch函数传递到$watch
,而不必使用不必要的字段污染作用域
注意:img
的load
事件可能无法在所有浏览器中可靠工作。要获得更可靠的方法,请尝试此方法。继Buu Nguyen的回答之后(这是正确的),我应该说,不建议使用监视程序来监视DOM,因为“Scope$watch性能注意事项”部分中的状态是:
脏检查属性更改的范围是中的常见操作
角度,因此,脏污检查功能必须
有效率的应注意脏污检查功能不起作用
不要进行任何DOM访问,因为DOM访问要慢几个数量级
然后对JavaScript对象进行属性访问
我不确定在您的情况下这是否会是一个问题,但请记住。我只是猜测,但可能是您的指令在ng src之后运行,因此它不会拾取更改,因为它及时错过了它(考虑到图像在浏览器缓存中)。指令的默认优先级为0,但ng src有99,因此尝试为测试指令分配高于99的优先级不会有任何影响。。那它以前是怎么工作的?调用'element.offsetLeft'进行监视将返回正确的值,因此它在作用域上的计算似乎正确。如果某个内容不在作用域中,则作用域无法通过字符串表达式进行监视。但是,watch listener总是使用初始值初始化一次(如果您想知道原因,请阅读文档或代码),因此,一些幸运的时机可能会让您的原始代码在某个时间点为某些属性工作,但这并不意味着它是正确的代码。它很容易验证,而不是使用元素[0].offsetLeft
在侦听器中,使用newVal
。我确信它将是未定义的
。我只是注意到这个解决方案不能保证有效。这是一个时间问题。我重新加载了10次页面,其中一次,0返回了offsetWidth。捕捉得好。如果img在初始摘要循环之后加载,则当其大小更改时,手表不会被处理。我更新了代码来处理“加载”事件并运行循环。那么我可以用另一种方式监视DOM吗?如果我的意图是让指令根据页面上呈现的元素的当前大小和位置来执行某些操作,您会有什么建议?我以前在Angular中没有做过类似的操作,因此我没有一个直接的答案。什么呈现元素?您的指令是否可以这样做,以便它知道元素的大小和位置,而无需监视这些属性?
angular.module('test', []).
directive('testing', function() {
return function(scope, element, attr) {
scope.$watch(
function() {
return element[0].offsetWidth
},
function(newVal, oldVal) {
scope.offsetwidth = element[0].offsetWidth
}
)
scope.$watch(
function() {
return element[0].offsetLeft
},
function(newVal, oldVal) {
scope.offsetleft = element[0].offsetLeft
}
)
}
});
angular.module('test', []).
directive('testing', function() {
return function(scope, element, attr) {
element.on('load', function() {
scope.offsetwidth = element[0].offsetWidth
scope.offsetleft = element[0].offsetLeft
scope.$apply();
});
}
});