I’d like to bring my little experience on the subject.
I’m developing an app with 3 tabs, and 2 of these are quite heavy (a list with few hundred items and a leaflet map).
In my test I tried to override the ionTab
directive to not delete scope and dom element of each tab when unselected, but instead hide it (well, actually setting a lower z-index).
Here is the code, you can try it by putting it in a file, including in a <script>
tag in your index.html and set ionTabReplace
module as a dependency of your main app module (like ionic). The .config(…)
take care of removing the default ionTab
directive
var extend = angular.extend,
forEach = angular.forEach,
isDefined = angular.isDefined,
isString = angular.isString,
jqLite = angular.element;
angular.module('ionTabReplace',[])
.config(function($provide){
$provide.decorator('ionTabDirective', ['$delegate', function($delegate) {
console.log($delegate);
$delegate.shift();
return $delegate;
}]);
})
.directive('ionTab', [
'$rootScope',
'$animate',
'$ionicBind',
'$compile',
function($rootScope, $animate, $ionicBind, $compile) {
//Returns ' key="value"' if value exists
function attrStr(k,v) {
return angular.isDefined(v) ? ' ' + k + '="' + v + '"' : '';
}
return {
restrict: 'E',
require: ['^ionTabs', 'ionTab'],
replace: true,
controller: '$ionicTab',
scope: true,
compile: function(element, attr) {
//We create the tabNavTemplate in the compile phase so that the
//attributes we pass down won't be interpolated yet - we want
//to pass down the 'raw' versions of the attributes
var tabNavTemplate = '<ion-tab-nav' +
attrStr('ng-click', attr.ngClick) +
attrStr('title', '*'+attr.title) +
attrStr('icon', attr.icon) +
attrStr('icon-on', attr.iconOn) +
attrStr('icon-off', attr.iconOff) +
attrStr('badge', attr.badge) +
attrStr('badge-style', attr.badgeStyle) +
'></ion-tab-nav>';
//Remove the contents of the element so we can compile them later, if tab is selected
//We don't use regular transclusion because it breaks element inheritance
var tabContent = jqLite('<div class="pane">')
.append( element.contents().remove() );
return function link($scope, $element, $attr, ctrls) {
var childScope;
var childElement;
var tabsCtrl = ctrls[0];
var tabCtrl = ctrls[1];
var navView = tabContent[0].querySelector('ion-nav-view') ||
tabContent[0].querySelector('data-ion-nav-view');
var navViewName = navView && navView.getAttribute('name');
$ionicBind($scope, $attr, {
animate: '=',
onSelect: '&',
onDeselect: '&',
title: '@',
uiSref: '@',
href: '@',
});
tabsCtrl.add($scope);
$scope.$on('$destroy', function() {
tabsCtrl.remove($scope);
tabNavElement.isolateScope().$destroy();
tabNavElement.remove();
});
//Remove title attribute so browser-tooltip does not apear
$element[0].removeAttribute('title');
if (navViewName) {
tabCtrl.navViewName = navViewName;
}
$scope.$on('$stateChangeSuccess', selectIfMatchesState);
selectIfMatchesState();
function selectIfMatchesState() {
if (tabCtrl.tabMatchesState()) {
tabsCtrl.select($scope);
}
}
var tabNavElement = jqLite(tabNavTemplate);
tabNavElement.data('$ionTabsController', tabsCtrl);
tabNavElement.data('$ionTabController', tabCtrl);
tabsCtrl.$tabsElement.append($compile(tabNavElement)($scope));
//Create child scope and element
childScope = $scope.$new();
childElement = tabContent.clone();
$animate.enter(childElement, tabsCtrl.$element);
$compile(childElement)(childScope);
if (!$scope.$tabSelected) //Hide it if not selected
jqLite(childElement).css('z-index',-1);
$scope.$watch('$tabSelected', function(value) {
if (value) { //Show
jqLite(childElement).css('z-index',1);
} else { //Hide
jqLite(childElement).css('z-index',-1);
}
});
};
}
};
}]);
I didn’t do lot of test, but if the app consist only of some tab I think it’ll be quite faster when you switch between tabs, but it will take some more time in loading dom at the beginning.