变量绑定/第一类函数是否优于私有方法命名?吊装如何受到影响?

时间:2015-04-27 23:11:52

标签: javascript angularjs function coding-style hoisting

关于使用变量绑定与私有方法命名函数约定时构造Angular代码和JavaScript行为的一些问题。是否存在使用AngularJS中的变量绑定函数/第一类函数而不是私有方法命名的性能或风格原因?每种方法如何影响吊装?下面的第二种方法是否会减少提升量,这会对应用性能产生明显影响吗?

私有方法命名的示例。这是构建Angular代码的推荐方法吗?

    (function () {
       'use strict'
        function modalController(dataItemsService, $scope) {
            var vm = this;

            function _getSelectedItems() {
               return dataItemsService.SelectedItems();
            }

            function _deleteSelectedItems() {
               dataItemService.DeleteItem();
               $("#existConfirmDialog").modal('hide');
            }

            vm.SelectedItems = _getSelectedItems;
            vm.deleteItemRecord = _deleteItemRecord;
        }

        angular.module('app').controller('modalController', ['dataItemService', '$scope', modalController]
})();

变量绑定函数的示例。在控制器中构造角度代码的这种方法怎么样?在性能/风格方面有任何缺点或优势吗?

angular.module('appname').controller("NameCtrl", ["$scope", "$log", "$window", "$http", "$timeout", "SomeService",
    function ($scope, $log, $window, $http, $timeout, TabService) {

    //your controller code
       $scope.tab = 0;    
       $scope.changeTab = function(newTab){
          $scope.tab = newTab;
       };    
       $scope.isActiveTab = function(tab){
          return $scope.tab === tab;
       }; 
    }
]);

1 个答案:

答案 0 :(得分:5)

第一种方法,使用" private"方法和通过公共别名公开它们被称为Revealing Module Pattern,尽管在这个例子中这些方法实际上并不是私有的。

后者是一个非常标准的Constructor Pattern,使用$ scope作为上下文。

  

在AngularJS中使用variable绑定函数/第一类函数是否存在性能或风格上的原因而不是私有方法命名?

     

是否有[推荐]构建Angular代码的方法?

TL; DR

  • 从根本上说,两种风格之间没有太大区别 以上。一个使用$scope,另一个使用this。一个构造函数在闭包中定义,一个是内联定义的。

  • 在某些情况下,您可能需要私有方法或值。 还有风格和(可能微不足道)的表现 使用变量this / vm而不是$scope的原因。这些不是相互排斥的。

  • 您可能想要使用 基本的,裸露的骨头,旧学校的构造函数模式,以及很多 人们通过this代替$scope来揭露状态和行为。

  • 您可以在Controller中自行保护数据隐私,但大部分都是如此 服务/工厂应该利用这个时间。主要的例外是代表View状态的数据。

  • 请不要在您的控制器中使用jQuery。

参考文献:

Todd Motto

AngularJS Style Guide

AngularJS Up & Running

要彻底回答您的问题,我认为理解财务主任的责任非常重要。每个控制器的工作都是向View公开一组严格的状态和行为。简而言之,只需将{* 1}}或this分配给用户在视图中看到或玩的内容。

有问题的$scopevariablevm)是Controller函数创建的实例的上下文($scope)。

this是Angular"特别"上下文;它已经为你定义了一些行为(例如$ scope。$ watch)。 $scope也遵循继承链,即$ scope继承分配给其父$ scope的状态和行为。

拿这两个控制器:

$scopes

和视图

angular.module("Module")
    .controller("Controller", ["$scope", function($scope) {
        $scope.tab = 0;
        $scope.incrementTab = function() {
            $scope.tab++;
        };
    }])
    .controller("OtherController", ["$scope", function($scope) {
        // nothing
    }]);

示例here

你注意到的是,即使我们没有在OtherController中定义<div ng-controller="Controller"> <p>{{ tab }}</p> <button ng-click="incrementTab();">Increment</button> <div ng-controller="OtherController"> <p>{{ tab }}</p> <button ng-click="incrementTab();">Increment</button> </div> </div> ,它也会从Controller继承它,因为Controller是它在DOM中的父级。在显示选项卡的两个位置,您应该看到&#34; 0&#34;。这可能是您所指的"hoisting",尽管这是一个完全不同的概念。

点击第一个按钮后会发生什么?在这两个地方,我们已经曝光了#34; tab&#34;,他们现在将显示&#34; 1&#34;。当您按下第二个按钮时,两者也会更新和增加。

当然,我可能不希望我的子标签与父标签的标签值相同。如果您将OtherController更改为:

$scope.tab

您会注意到此行为已更改 - 标签的值不再同步。

但是现在它令人困惑:我有两个叫做#34; tab&#34;不是一样的。其他人可能会在以后使用&#34; tab&#34;写下一些代码。并且无意中破坏了我的代码。

我们过去通过在.controller("OtherController", ["$scope", function($scope) { $scope.tab = 42; }]); 上使用命名空间来解决此问题。 $scope并将所有内容分配给命名空间:$scope.vm

$scope.vm.tab = 0;

另一种方法是使用<div ng-controller="OtherController"> <p>{{ vm.tab }}</p> <button ng-click="vm.incrementTab();">Increment</button> </div> 的简单性和简洁性,并利用controllerAs语法。

this

对于习惯使用普通JS的人来说,这可能会更舒服,并且通过这种方式更容易避免与其他Angular源的冲突。您可以随时更改命名空间。它也有点“轻”&#34;因为您没有创建新的.controller("OtherController", function() { this.tab = 0; }); <div ng-controller="OtherController as oc"> <p>{{ oc.tab }}</p> </div> 个实例,但我不确定是否有很多收获。

为了实现隐私,我建议将数据封装在服务或工厂中。记住,控制者并不总是单身; View和Controller之间存在1:1的关系,您可以多次实例化同一个控制器!但是,工厂和服务对象是单身人士。他们非常擅长存储共享数据。

让所有控制器从单例中获取状态的副本,并确保所有控制器都使用在服务/工厂上定义的行为来修改单例状态。

$scope

但是等等,我怎么知道我的应用程序的另一部分何时更改了我的私人数据?我如何知道何时获取SelectedItems的新副本?这是$ scope。$ watch发挥作用的地方:

function modalController(dataItemsService) {
    var vm = this;
    vm.selectedItems = dataItemsService.SelectedItems(); // get a copy of my data
    vm.updateItem = dataItemService.UpdateItem; // update the source
}

如果您的数据未被共享,或者您的私人数据代表的是View图层而不是Model图层,那么将它保存在控制器中是完全可以的。

function modalController(dataItemsService, $scope) {
    var vm = this;

    vm.updateItem = dataItemService.UpdateItem; // update the source

    // periodically check the selectedItems and get a fresh copy.
    $scope.$watch(dataItemsService.SelectedItems, function(items) {
        vm.items = items;
    });

    // thanks $scope!
}

最后,不要像你的参考那样在你的控制器中使用JQUERY!

function Controller() {
    var buttonClicked = false;

    this.click = function() {
        buttonClicked = true; // User can not lie and say they didn't.
    };
}

这个例子可能不是纯粹的邪恶,但是避免在指令之外访问和修改DOM,你不想通过修改它下面的DOM来打破你应用程序的其他部分。