我遇到旧的可变高度导航问题:顶部有position: fixes
导航,下面有margin-top: $naviHeight
内容。
当数据异步加载时导航可以改变高度,因此内容的边距必须随之改变。
我希望这是自包含的。所以没有加载数据的代码,只有在涉及的html-elements /指令中。
目前我在AngularJS 1.2.0中使用这样的计时器进行此操作:
/*
* Get notified when height changes and change margin-top
*/
.directive( 'emHeightTarget', function(){
return {
link: function( scope, elem, attrs ){
scope.$on( 'heightchange', function( ev, newHeight ){
elem.attr( 'style', 'margin-top: ' + (58+newHeight) + 'px' );
} );
}
}
})
/*
* Checks this element periodically for height changes
*/
.directive( 'emHeightSource', ['$timeout', function( $timeout ) {
return {
link: function( scope, elem, attrs ){
function __check(){
var h = elem.height();
if( h != scope.__height ){
scope.__height = h;
scope.$emit( 'heightchange', h );
}
$timeout( __check, 1000 );
}
__check();
}
}
} ] )
这有明显的使用计时器的缺点(我觉得有点难看)和导航调整大小后的某个延迟直到内容被移动。
有更好的方法吗?
答案 0 :(得分:40)
这可以通过在emHeightSource
中注册一个每$digest
调用一次的观察者来实现。它会更新__height
中依次监视的emHeightTarget
属性:
/*
* Get notified when height changes and change margin-top
*/
.directive( 'emHeightTarget', function() {
return {
link: function( scope, elem, attrs ) {
scope.$watch( '__height', function( newHeight, oldHeight ) {
elem.attr( 'style', 'margin-top: ' + (58 + newHeight) + 'px' );
} );
}
}
} )
/*
* Checks every $digest for height changes
*/
.directive( 'emHeightSource', function() {
return {
link: function( scope, elem, attrs ) {
scope.$watch( function() {
scope.__height = elem.height();
} );
}
}
} )
答案 1 :(得分:24)
您可以在不使用Div的情况下监控元素的高度变化,只需编写$watch
语句:
// Observe the element's height.
scope.$watch
(
function () {
return linkElement.height();
},
function (newValue, oldValue) {
if (newValue != oldValue) {
// Do something ...
console.log(newValue);
}
}
);
答案 2 :(得分:13)
您应该注意$window
'维度更改,例如:
.directive( 'emHeightSource', [ '$window', function( $window ) {
return {
link: function( scope, elem, attrs ){
var win = angular.element($window);
win.bind("resize",function(e){
console.log(" Window resized! ");
// Your relevant code here...
})
}
}
} ] )
答案 3 :(得分:6)
我使用了$ watch和resize事件的组合。我发现没有范围。$ apply();在调整大小事件中,元素的高度变化并不总是被$ watch选中。
link:function (scope, elem) {
var win = angular.element($window);
scope.$watch(function () {
return elem[0].offsetHeight;
},
function (newValue, oldValue) {
if (newValue !== oldValue)
{
// do some thing
}
});
win.bind('resize', function () {
scope.$apply();
});
};
答案 4 :(得分:4)
此方法避免(可能)触发每个摘要周期reflow
。它仅检查摘要周期结束后的elem.height()
/ /,并且只有在高度发生变化时才会生成新的摘要。
var DEBOUNCE_INTERVAL = 50; //play with this to get a balance of performance/responsiveness
var timer
scope.$watch(function() { timer = timer || $timeout(
function() {
timer = null;
var h = elem.height();
if (scope.height !== h) {
scope.$apply(function() { scope.height = h })
}
},
DEBOUNCE_INTERVAL,
false
)
答案 5 :(得分:1)
我写了另一个可以绑定到范围的基于计时器的变体,因为正如Jamie Pate正确指出的那样,在摘要周期内直接进行DOM访问并不是一个好主意。
Select price::Numeric(16,2)
from prices
现在你可以将它绑定在任何元素上:
.directive("sizeWatcher", ['$timeout', function ($timeout) {
return {
scope: {
sizeWatcherHeight: '=',
sizeWatcherWidth: '=',
},
link: function( scope, elem, attrs ){
function checkSize(){
scope.sizeWatcherHeight = elem.prop('offsetHeight');
scope.sizeWatcherWidth = elem.prop('clientWidth');
$timeout( checkSize, 1000 );
}
checkSize();
}
};
}
因此div始终保持(延迟为一秒)与图像的高度相同。
答案 6 :(得分:0)
此方法会监视元素的高度和宽度,并将其分配给元素属性上提供的范围内的变量
<div el-size="size"></div>
.directive('elSize', ['$parse', function($parse) {
return function(scope, elem, attrs) {
var fn = $parse(attrs.elSize);
scope.$watch(function() {
return { width: elem.width(), height: elem.height() };
}, function(size) {
fn.assign(scope, size);
}, true);
}
}])