AngularJS从状态指令导航,正确的方式

时间:2014-11-03 09:13:57

标签: javascript angularjs angularjs-directive

我想做一个指令,它会使Angular UI-Router声明信息,并根据它创建一个导航栏。现在我们会采取什么正确的方式?

a)创建具有$state依赖关系的NavController,获取状态信息并将其转换为合适的JS数组,然后通过属性将此数组传递给指令并在那里执行DOM操作。

b)创建一个具有$state依赖关系的NavDirective,并在其中完成所有工作(状态信息转换和DOM操作)。

什么是好的做法?

现在我有以下内容:

app.directive('navigation', ['$parse', '$compile', function ($parse, $compile) {
return {
    restrict: 'A',
    scope: true,
    link: function (scope, element, attrs) {
        scope.selectedNode = null;


        scope.$watch(attrs.menuData, function (val) {
            var template = angular.element(
                '<ul class="nav navbar-nav">'
                + '<li ng-repeat="node in ' + attrs.menuData + '" active-tab="{{node.href}}">'
                + '<a ui-sref="{{node.state}}"><b>{{node.text}}</b></a>'
                + '</li>'
                + '</ul>'
            );

            var linkFunction = $compile(template);

            linkFunction(scope);
            element.html(null).append( template );
        }, true);
    }
};

}]);

app.controller('NavigationController', ['$scope', '$state', function ($scope, $state) {

    var menu = [];
    var states = $state.get();

    _.each(states, function(state, key) {
        if(!_.isObject(state) || _.has(state, 'abstract') || _.has(state, 'parent')) {
            return;
        }

        var object = {
            text: _.has(state.data, 'title') ? state.data.title : '(no title)',
            state: state.name,
            href: state.url
        }

        menu.push(object);
    });

    $scope.menu = menu;
}]);

2 个答案:

答案 0 :(得分:0)

通常不应使用控制器来执行DOM操作。

来自角度开发者指南:

https://docs.angularjs.org/guide/controller

  

不要使用控制器:

     

操纵DOM - 控制器应仅包含业务逻辑。将任何表示逻辑放入控制器会显着影响其可测试性。 Angular对大多数情况和指令进行数据绑定以封装手动DOM操作。

答案 1 :(得分:0)

这是指令的v2。这是在angular中执行指令的正确方法吗?

app.directive('navigation', ['$parse', '$compile', function ($parse, $compile) {
    return {
        restrict: 'A',
        templateUrl: 'views/widgets/navbar.html',
        replace: true,
        scope: {},
        controller: ['$scope', '$state', function ($scope, $state) {
            var menu = [];
                var states = $state.get();

            _.each(states, function(state, key) {
                if(!_.isObject(state) || _.has(state, 'abstract') || _.has(state, 'parent')) {
                    return;
                }

                var object = {
                    text: _.has(state, 'data') && _.has(state.data, 'title') 
                            ? state.data.title : '(no title)',
                    state: state.name,
                    href: state.url
               }

               menu.push(object);
            });

            $scope.nav = {};
            $scope.nav.menu = menu;
        }],
        link: function (scope, element, attrs) {
            scope.nav.brand = attrs.navBrand; 
            console.log(scope);
        }
    };
 }]);

模板:

<nav class="navbar navbar-default navbar-fixed-top">
<div class="navbar-header">
    <button type="button" class="navbar-toggle collapsed" data-toggle="collapse">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
    </button>
    <a class="navbar-brand" href="#">{{ nav.brand }}</a>
</div>
<div class="navbar-collapse collapse">
    <ul class="nav navbar-nav">
        <li ng-repeat="node in nav.menu" active-tab="{{node.href}}">
            <a ui-sref="{{node.state}}"><b>{{node.text}}</b></a>
        </li>
    </ul>
</div>

指令致电:

<div navigation nav-brand="My Brand"></div>