Javascript 延迟大小计算直到呈现ui
这是我的标记:Javascript 延迟大小计算直到呈现ui,javascript,css,html,angularjs,angularjs-directive,Javascript,Css,Html,Angularjs,Angularjs Directive,这是我的标记: <div resizer> <div class="a"></div> <div class="b"> This content generated dynamically using ng-include and other directives inside </div> </div> 当我启动应用程序时,有时,我的div的高度等于零(高度:0),因为b.oute
<div resizer>
<div class="a"></div>
<div class="b">
This content generated dynamically using ng-include and other directives inside
</div>
</div>
当我启动应用程序时,有时,我的div的高度等于零(高度:0),因为b.outerHeight();和元素。高度();返回零。为什么呢?我使用$timeout,以便浏览器有时间呈现视图。
有什么想法吗?您的问题似乎是指令模板中有一个
ng include
ng include
本身就是一个指令,它创建了一个新的作用域。但是,您的resizer
指令link
函数会在呈现HTML时立即执行,因此ng include
-d模板已经存在,但其内容尚未加载(如果之前未加载模板,则它甚至是一个单独的HTTP/GET请求)
我确信还有更多的修复,但其中之一是使用ng include
标记的onload
参数:
// ... your directive ...
link: function (scope, element, attrs) {
function updateSizes(event) {
console.log (element.find('.b').outerHeight());
}
scope.ngOnload = updateSizes;
}
因此,现在进入您的html模板:
<div resizer>
<div class="a"></div>
<div class="b">
<div ng-include="'sometemplate.html'" onload="ngOnload()"></div>
</div>
</div>
这对我起到了作用,div.b
元素outerHeight在控制台日志中不再是0
我明白了,您已经使用
$timeout
等待浏览器。如果我的解决方案不适用于您,那么这些div
中肯定加载了一些奇怪的内容,可能需要解决方案的更多详细信息。但是,在updateSizes
函数中使用chrome debugger的debugger
语句可能会有很大帮助。您有两种可能的选择(请参阅):
您可以在链接函数中指定侦听器,如下所示:
function link(scope, element, attrs) {
scope.$on('$includeContentLoaded', function(){
console.log('Template included');
// you can add all your height calculation and DOM manipulation here
});
}
'use strict';
myModule.directive('resizer', ['$timeout', function ($timeout) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
function updateSizes(event) {
var a = element.find('.a');
var b = element.find('.b');
var bHeight = b.outerHeight();
var totalHeight = element.height();
a.height(totalHeight - bHeight);
}
scope.$on('$includeContentLoaded', updateSizes);
}
};
}]);
请看一看(我希望内容是不言自明的)。您的代码应该是这样的:
function link(scope, element, attrs) {
scope.$on('$includeContentLoaded', function(){
console.log('Template included');
// you can add all your height calculation and DOM manipulation here
});
}
'use strict';
myModule.directive('resizer', ['$timeout', function ($timeout) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
function updateSizes(event) {
var a = element.find('.a');
var b = element.find('.b');
var bHeight = b.outerHeight();
var totalHeight = element.height();
a.height(totalHeight - bHeight);
}
scope.$on('$includeContentLoaded', updateSizes);
}
};
}]);
方法
使用angular的常见模式是,嵌套指令需要父指令,并向父指令注册自身。您可以使用此模式来解决您的问题。我已将嵌套指令resizer source和resizer dest添加到标记中:
<div resizer>
<div class="a" resizer-dest></div>
<div class="b" resizer-source>
This content generated dynamically using ng-include and other directives inside
</div>
</div>
调脂器
增塑剂
更灵活
如果由于某种原因,b的链接功能运行时,b的高度不可用,您可以通过在b的高度上设置$watch
并仅在手表计算为正数时注册b,使其更加灵活。之后,取消观察者,除非您期望元素的高度继续改变
附加信息
如果我要监视b的大小,我必须引起一个摘要循环(通过调用$apply()或$digest)。我正在通知resizer使用dom事件进行更新。你觉得怎么样
(1) $watch
调整尺寸是一项昂贵的操作,因为每次检查高度时都会强制回流。因此,请尽快取消$watch
。(2) 不能保证angular会在正确的时间触发摘要循环,因此可能需要使用您提到的dom事件
出于这些原因,使用$watch
可能根本不是最好的方法,但这取决于您的具体情况
在链接函数中使用元素不是一种好的做法吗
使用控制器而不是链接函数没有任何不符合角度的地方。它们有不同的调用顺序,但在这里不起作用
您无权访问控制器中的“元素”。。将大小调整器代码放入链接函数是否安全?我的意思是,我必须把registerSource和registerDest放在控制器上
如果需要,可以将
$element
注入控制器。或者,您可以将指令自己的控制器添加到require
属性,以从链接
功能访问它。无论您选择将代码放入控制器还是链接
功能,通常都取决于组织,因此,如果链接
功能简化了代码,请不要害怕使用控制器。我怀疑问题可能是由于加载ng include资源的延迟造成的。您可以预加载缓存:
$templateCache.put('template.html', '<b>Template</b>');
我知道这不是你想要的答案,但为什么你要走这么远,让这些简单的事情都能实现呢
最好的编程方式是不编程
我只建议您使用css唯一的解决方案
<style>
.tbl {display:table}
.tbl-row {display:table-row}
.tbl-cell {display:table-cell}
</style>
<div class="tbl">
<div class="tbl-row">
<div class="tbl-cell">Foo</div>
<div class="tbl-cell">
This content generated dynamically using ng-include and other directives inside
</div>
</div>
</div>
.tbl{display:table}
.tbl行{显示:表行}
.tbl单元格{显示:表格单元格}
福
此内容是使用ng include和内部的其他指令动态生成的
示例:角度方式是一个常见且好的问题。AngularJS有一个自然的流程,其中不断变化的模型重新定义了内容或样式。所以通常,对于改变内容之类的东西,“角度方式”就是HTML方式。似乎你想调整你的div大小以适应内容。但是,如果我理解正确的话,你做的工作太多了。div本质上就是要根据内容调整大小。因此,除非将固定高度或宽度指定给div,否则它的行为应该与您喜欢的一样。如果您想要额外的行为(填充、居中、固定宽度),这将更多地是CSS答案而不是“角度”。这应该由CSS来完成。@DaveA这不能使用CSS来完成,因为我还需要在运行时更新大小。我将更新我的代码-还有一个导致大小更新的事件绑定。现在清楚了吗?@Naor,还不清楚。我错过了一件大事。在我看来,div会自动调整大小以适应其内容。由于我对数据或内容进行了模型绑定,并对其进行了更改(或更改了指令以使用不同的模板),因此我的div已经调整了大小。我不知道,你的答案是什么意思
$templateCache.put('template.html', '<b>Template</b>');
$http.get('template.html', {cache:$templateCache});
<style>
.tbl {display:table}
.tbl-row {display:table-row}
.tbl-cell {display:table-cell}
</style>
<div class="tbl">
<div class="tbl-row">
<div class="tbl-cell">Foo</div>
<div class="tbl-cell">
This content generated dynamically using ng-include and other directives inside
</div>
</div>
</div>