原文:108 Hidden Grids
隐藏的表格
当UI-Grid在加载页面的时候不是可见状态,比如在tabset页面中,或者是在可折叠的页面内。最终的结果往往是一个表格,呈现出“错误”或者行列出现意想不到的宽度或高度。让我们从这个场景开始:
想象一下,在一个<div>
内的表格,这个<div>
没有宽度或高度。您提供的表格没有CSS类,所以它的高度和宽度CSS值设置为自动,这意味着浏览器将自动计算。
UI-Grid的出现是为了显示大量的数据更容易。它通过一个称为“虚拟化”的过程。这意味着,如果你有10000行和50列,而不是渲染500000 DOM元素来拖慢浏览器, UI-Grid将尽其所能,只显示其所需的最小数量展现给用户。对用户来说,看起来所有的数据都在屏幕上,事实上只有一小部分正在渲染。
这将成为我们在上面创建的场景中的一个问题,因为当我们告诉UI-Grid,我们有10000行和50列时,它知道我们实际上不想同时显示它们,所以它必须找出可见的空间,允许它“绘制”。这个空间被称为“窗口”,我们通过这个“窗口”来查看数据,这个窗口外都是空的内容,除了我们滚动时添加出现的行和列。
当你把UI-Grid放在没有指定高度的容器div中,网格没有CSS指定的高度时,它就不知道你希望它有多大。你想看5行吗?100?它不能告诉。目前这只是假设,在窗口中10行是一个很好的默认值。可以通过minRowsToShow 设置这个值。
如果你给UI-Grid的高度100%,但它的父容器div没有高度?然后它也不知道它应该有多大。100%什么?什么也没有?所以,它会调整大小以适应minRowsToShow所指定的行数。还可以通过给表格一个特定的高度来解决这个问题,或可变的高度并给父容器一个有效的高度或父容器内放置其他元素,比如有一个图像和表格在同一容器中,并且图像的高度是500px,表格的指定高度是:50%,那么表格的高度就是250px。
让我们看一下表格在隐藏的情况下,无论是在一个标签或折叠菜单或ng-show表达式。隐藏元素没有高度或宽度,因为他们未被渲染。如果设置一个元素的CSS属性为display: none,并注销其offsetWidth 属性,这个元素将为0。即使当它可见时的高度有1000px,当它隐藏后它没有高度。UI Grid也是像JQuery这样处理,创建一个“虚拟”克隆的元素,元素属性display: none改变为visibility: hidden(这意味着它是不可见的但仍占用空间),然后将这个克隆的元素附加到上,计算它的高度,最后删除它。是唯一安全的地方,因为当隐藏的元素占用空间时,它可以导致周围其他元素的移动,并出现“闪烁”的效果。
所以当你把表格放在一个没有渲染的地方,并且表格的CSS没有设置它有多大,当它创建这个克隆元素并测量它时,它的高度和宽度将为0。即使0px太小,UI-Grid也会尽力调整,所以它会调整到可用高度,但真的没有办法告诉它应该有多宽,所以列会是最小宽度(30px左右),窗口将会很小,看起来像UI-Grid渲染错误,而且窗口太小的表格单元本身会占用父容器的宽度。
为了解决这个问题,你必须给表格一些设置。这里有一些选项:
- 在下面的例子中给表格一个特定的高度和宽。
- 用 ng-if 来防止表格在元素(面板/折叠/等)被激活前渲染。
- 使用 autoResize 让表格重新绘制,这可能会导致页面闪烁,autoResize 的检测周期是250ms。
代码:
index.html
<!doctype html>
<html ng-app="app">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular-touch.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular-animate.js"></script>
<script src="http://ui-grid.info/docs/grunt-scripts/csv.js"></script>
<script src="http://ui-grid.info/docs/grunt-scripts/pdfmake.js"></script>
<script src="http://ui-grid.info/docs/grunt-scripts/vfs_fonts.js"></script>
<script src="/release/ui-grid.js"></script>
<script src="/release/ui-grid.css"></script>
<script src="app.js"></script>
</head>
<body>
<div ng-controller="MainCtrl">
<button type="button" class="btn btn-success" ng-click="hideGrid = !hideGrid">
{{ hideGrid && 'Show' || 'Hide' }} Grid
</button>
<div class="well" ng-hide="hideGrid">
<div ui-grid="gridOptions" class="grid"></div>
</div>
</div>
</body>
</html>
main.css
.grid {
width: 500px;
height: 150px;
}
app.js
var app = angular.module('app', ['ngTouch', 'ui.grid']);
app.controller('MainCtrl', ['$scope', '$http', function ($scope, $http) {
$scope.hideGrid = true;
$scope.gridOptions = { };
$http.get('/data/100.json')
.success(function(data) {
$scope.gridOptions.data = data;
});
}]);
Demo
文章来源:西柚叨叨的个人博客