用途
ng-switch 属性用来根据一个范围的值来控制页面内元素的添加或移除。子元素必须配合ng-switch-when或ng-switch-default来使用,否则ng-switch将被忽略。
用法
<div ng-controller="Ctrl"> <select ng-model="selection" ng-options="item for item in items"> </select> <tt>selection={{selection}}</tt> <hr/> <div class="animate-switch-container" ng-switch on="selection"> <div class="animate-switch" ng-switch-when="settings">Settings Div</div> <div class="animate-switch" ng-switch-when="home">Home Span</div> <div class="animate-switch" ng-switch-default>default</div> </div> </div>
上述实例中,on属性可以不写,直接将swich的对象表达式设置到 ng-swtich属性:
<div class="animate-switch-container" ng-switch="selection">
实在不解作者为啥这么设计!从源代码以及使用效果来看,on属性完全是多余的。难不成历史遗留?
另外一点也需要特别注意:
ng-switch接收表达式(如上例中的$scope.selection),而ng-switch-when接收的是字符串值而不是表达式。譬如:ng-switch-when="someVal"
将匹配字符串 "someVal" 而不是
$scope.someVal的值。这点和js中的switch的用法是一样的:switch变量,case指定值。
工作原理
ng-switch由三个子指令组成: ng-switch,ng-switch-when以及ng-switch-default。
ng-switch-when指令和ng-switch-default指令比较简单,将监视的字符串以及元素添加到父元素ng-switch的controller的cases中去。
ng-switch指令监视表达式的变化,变化后将当前元素移除,将ontroller的cases中的符合要求的元素添加到页面。
ng-switch的核心代码:
var ngSwitchDirective = ['$animate', function($animate) { return { require: 'ngSwitch', // asks for $scope to fool the BC controller module controller: ['$scope', function ngSwitchController() { this.cases = {}; }], link: function(scope, element, attr, ngSwitchController) { var watchExpr = attr.ngSwitch || attr.on scope.$watch(watchExpr, function ngSwitchWatchAction(value) { var i, ii; for (i = 0, ii = previousLeaveAnimations.length; i < ii; ++i) { $animate.cancel(previousLeaveAnimations[i]); }for (i = 0, ii = selectedScopes.length; i < ii; ++i) { var selected = getBlockNodes(selectedElements[i].clone); selectedScopes[i].$destroy(); var promise = previousLeaveAnimations[i] = $animate.leave(selected); promise.then(spliceFactory(previousLeaveAnimations, i)); } if ((selectedTranscludes = ngSwitchController.cases['!' + value] || ngSwitchController.cases['?'])) { forEach(selectedTranscludes, function(selectedTransclude) { selectedTransclude.transclude(function(caseElement, selectedScope) { selectedScopes.push(selectedScope); var anchor = selectedTransclude.element; caseElement[caseElement.length++] = document.createComment(' end ngSwitchWhen: '); var block = { clone: caseElement }; selectedElements.push(block); $animate.enter(caseElement, anchor.parent(), anchor); }); }); } }); } }; }]; var ngSwitchWhenDirective = ngDirective({ transclude: 'element', priority: 1200, require: '^ngSwitch', multiElement: true, link: function(scope, element, attrs, ctrl, $transclude) { ctrl.cases['!' + attrs.ngSwitchWhen] = (ctrl.cases['!' + attrs.ngSwitchWhen] || []); ctrl.cases['!' + attrs.ngSwitchWhen].push({ transclude: $transclude, element: element }); } }); var ngSwitchDefaultDirective = ngDirective({ transclude: 'element', priority: 1200, require: '^ngSwitch', multiElement: true, link: function(scope, element, attr, ctrl, $transclude) { ctrl.cases['?'] = (ctrl.cases['?'] || []); ctrl.cases['?'].push({ transclude: $transclude, element: element }); } });