我正在尝试使用Angular JS指令来居中div的内容。
这是模板的简化版本:
<div id="mosaic" class="span12 clearfix" s-center-content>
<div ng-repeat="item in hits" id="{{item._id}}" >
</div>
</div>
这是指令:
module.directive('sCenterContent', function() {
var refresh = function(element){
var aWidth= element.innerWidth();
var cWidth= element.children()[0].offsetWidth;
var cHeight= element.children()[0].offsetHeight;
var perRow= Math.floor(aWidth/cWidth);
var margin=(aWidth-perRow*cWidth)/2;
if(perRow==0){
perRow=1;
}
var top=0;
element.children().each(function(index, child){
$(child).css('margin-left','0px');
if((index % perRow)==0){
$(child).css('margin-left',margin+'px');
}
});
};
return {
link : function(scope, element, attrs) {
$(window).resize(function(event){
refresh(element);
});
}
};
});
它基本上浮动一些内部div并为每行中的第一个div添加一个边距,因此内容居中。
调整浏览器大小时,这可以正常工作。当我尝试在初始化之后进行刷新时出现问题。
我尝试过使用post链接功能,如图所示 这个问题。预链接和后链接函数按预期顺序调用,但不会在具有s-center-content指令的elemenet的子节点被渲染之后调用。由于没有找到孩子,因此刷新调用失败。
如何拨打电话以确保孩子们已经处理完毕?
我认为使用角度 $腕表 是一个更好,更优雅的解决方案:
link : function(scope, element, attrs) {
$(window).resize(function(event){
refresh(element);
});
var watchCount = 0,
unWatcher = $watch(
function() {
return $('*[s-center-content] img').length !== 0;
},
function() {
// ensure refresh isn't called the first time (before the count of elements is > 0)
if (++watchCount === 1) {
return;
}
refresh(element);
// stop watching the element now that refresh has been called
unWatcher();
}, true);
}
关于停止观看: AngularJS:清除$ watch
我认为使用角度 $腕表 是一个更好,更优雅的解决方案:
link : function(scope, element, attrs) {
$(window).resize(function(event){
refresh(element);
});
var watchCount = 0,
unWatcher = $watch(
function() {
return $('*[s-center-content] img').length !== 0;
},
function() {
// ensure refresh isn't called the first time (before the count of elements is > 0)
if (++watchCount === 1) {
return;
}
refresh(element);
// stop watching the element now that refresh has been called
unWatcher();
}, true);
}
关于停止观看: AngularJS:清除$ watch
这是一个反复出现的问题(某处存在与此相关的问题,以及谷歌论坛中的一个帖子..)
Angular无法知道dom何时完成,它只能知道它调用的函数何时返回(并且任何promise都被解析)。如果这些函数是异步的并且没有回调或承诺,则无法通知。
我看到它完成的方式(以及我完成它的方式)是使用setInterval定期检查DOM以查看它是否处于已完成状态。我讨厌这个解决方案,并会感激一个替代方案,但它确实完成了工作。
终于成功了!
我使用了livequery插件,并在链接方法的末尾添加了以下行:
$('*[s-center-content] > *').livequery( function(event){
refresh(element);
});
我选择元素的任何第一级子(当前和未来) s-center-content
指令并附加在将元素添加到DOM时调用的处理程序。
编辑
最后一点。我的内容布局主要取决于动态评估的内部图像 src
属性。为了使它工作,我不得不将代码更改为:
$('*[s-center-content] img').livequery( function(event){
$(this).load(function(){
refresh(element);
});
});
将左浮动div放在中心的指令的完整代码如下。请注意,它依赖于向行中的第一个div添加计算的边距。
module.directive('sCenterContent', function() {
var refresh = function(element){
var aWidth= element.innerWidth();
var cWidth= element.children()[0].offsetWidth;
var cHeight= element.children()[0].offsetHeight;
var perRow= Math.floor(aWidth/cWidth);
var margin=(aWidth-perRow*cWidth)/2;
if(perRow==0){
perRow=1;
}
var top=0;
element.children().each(function(index, child){
$(child).css('margin-left','0px');
if((index % perRow)==0){
$(child).css('margin-left',margin+'px');
}
});
};
return {
link : function(scope, element, attrs) {
$(window).resize(function(event){
refresh(element);
});
$('*[s-center-content] img').livequery( function(event){
$(this).load(function(){
refresh(element);
});
});
}
};
});
我相信这可以用css完成。无论这样的数字,目标都是中心元素吗?
[] [] [] [] []
[] [] []
如果是这样,这绝对可以用css实现,并且可以以更低的复杂度实现。
这是一个例子:
http://codepen.io/thetallweeks/pen/kvAJb