【问题标题】:Separating DOM manipulation from Angular controllers - Best Practice wanted将 DOM 操作与 Angular 控制器分离 - 需要最佳实践
【发布时间】:2015-05-13 08:33:18
【问题描述】:

试图找到构建 Angular 应用程序的“最佳”方式,我发现了几篇最佳实践文章。有了这个输入,我做到了:

angular.module('xApp', [])
//..... some services, factories, controllers, ....

.directive('dirNotification',[ function dirNotification() {
    return {
        scope: {}, 
        templateUrl: 'xNotification.html',
        replace: true,
        controller: 'CtrlNotification',
        link: function($scope){
            // if this is 'DOM manipulation, should be done here ... ?
            /*
            $scope.$on('session.update',function(event, args) {
                if (args == null) {
                    $scope.notificationdata.username = "";
                    $scope.notificationdata.sid = "";
                } else {
                    $scope.notificationdata.username = args.username;
                    $scope.notificationdata.sid = args.accessToken;
                }
            });
            */
        }

    };
}])
.controller('CtrlNotification',['$scope' ,function CtrlNotification($scope) {

    $scope.notificationdata = {
        username: "",
        sid: ""
    };

    // this is not real DOM manipulation, but only view data manipulation?
    $scope.$on('session.update',function(event, args) {
        if (args == null) {
            $scope.notificationdata.username = "";
            $scope.notificationdata.sid = "";
        } else {
            $scope.notificationdata.username = args.username;
            $scope.notificationdata.sid = args.accessToken;
        }
    });

}])

HTML 模板就是这样的:

<div>
    <p>{{notificationdata.username}}</p>
    <p>{{notificationdata.sid}}</p>
</div>

所以我的问题是,数据更改是否应该被视为 DOM 操作?在控制器中执行此操作的当前版本对我来说似乎更实用(例如设置默认值)。此外,如果我向其中添加更多功能,“指令链接”块将增长并包含比定义更多的功能。我猜应该在指令中根据范围数据更改颜色或隐藏元素等操作。

社区是什么意思?你同意我的假设吗?

谢谢, 雷纳

【问题讨论】:

    标签: javascript angularjs angularjs-directive


    【解决方案1】:

    作为一个好的开始,请阅读此SO question/answer

    控制器:

    您不应该在控制器中进行 DOM 操作(或查找 DOM 元素,或对视图做出任何假设)的原因是因为控制器的意图是仅处理app - 通过更改 ViewModel - 无论状态如何反映在 View 中。该控制器通过对来自模型和视图的事件做出反应并设置 ViewModel 的属性来实现这一点。 Angular 将通过绑定处理在视图中反映应用程序的“状态”。

    所以,是的,当然,更改 ViewModel 会导致 View 做出反应并操纵 DOM,但其想法是控制器不应该知道或关心 View 究竟是如何反应的。这使关注点的分离保持不变。

    指令:

    当内置指令不够用并且您需要更严格地控​​制视图的反应方式时,这是创建自定义指令的好理由。

    关于指令要记住两件事。

    1) 将指令视为可重用组件很有用,因此应用程序特定的逻辑越少越好。绝对要避免那里的任何业务逻辑。定义输入和输出(通常通过属性)并仅对它们做出反应。事件侦听器(就像您拥有的一样)是非常特定于应用程序的(除非该指令旨在与另一个发布事件的指令一起使用),因此如果可能的话,最好避免使用。

    .directive("notification", function(){
      return {
        restrict: "A",
        scope: {
          notification: "=" // let the attribute get the data for notification, rather than
                            // use scope.$on listener
        },
        // ...
      }
    })
    

    2) 仅仅因为指令“允许进行 DOM 操作”并不意味着您应该忘记 ViewModel-View 分离。 Angular 允许您在链接或控制器函数内定义范围,并提供包含所有典型 Angular 表达式和绑定的模板。

    template: '<div ng-show="showNotification">username:{{notification.username}}</div>',
    
    // controller could also have been used here
    link: function(scope, element, attrs){ 
       scope.showNotification = Math.floor(Math.random()* 2);    
    }
    

    【讨论】:

    • 非常感谢! ViewModel 的想法确实使它更清晰。让我多读一点,暂时用你的提示玩一下。
    • @Rainer,我解决了你的问题吗?
    • 当然,再次感谢!抱歉,希望我很快就能每天使用 Angular 工作,但不幸的是目前不行。
    猜你喜欢
    • 2014-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-22
    • 1970-01-01
    相关资源
    最近更新 更多