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

Bor*_*ris 2 javascript coding-style function hoisting angularjs

关于使用变量绑定与私有方法命名函数约定时构造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]
})();
Run Code Online (Sandbox Code Playgroud)

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

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;
       }; 
    }
]);
Run Code Online (Sandbox Code Playgroud)

Sir*_*att 5

使用"私有"方法并通过公共别名公开它们的第一种方法被称为显示模块模式,尽管在该示例中方法实际上不是私有的.

后者是一个非常标准的构造函数模式,使用$ scope作为上下文.

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

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

TL; DR

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

  • 在某些情况下,您可能需要私有方法或值.使用变量this/ vmover 还有风格和(可能无关紧要)的性能原因$scope.这些不是相互排斥的.

  • 你可能想要使用一个基本的,裸露的骨头,旧学校的构造函数模式,并且许多人通过this代替而暴露状态和行为$scope.

  • 您可以在Controller中允许自己的数据隐私,但大多数情况下,这应该由服务/工厂利用.主要的例外是代表View状态的数据.

  • 请不要在Controller中使用jQuery.

参考文献:

Todd Motto的AngularJS风格指南.

AngularJS Up&Running


为了彻底回答您的问题,我认为理解财务主任的责任非常重要.每个控制器的工作都是向View公开一组严格的状态和行为.简而言之,只能在您的视图中分配this$scope不想让用户看到或玩的东西.

variable问题(vm,$scope)是上下文(this由控制器功能正在创建的实例).

$scope是Angular的"特殊"背景; 它已经为你定义了一些行为(例如$ scope.$ watch).$scopes也遵循继承链,即$ scope继承分配给其父$ scope的状态和行为.

拿这两个控制器:

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

一个观点

<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>
Run Code Online (Sandbox Code Playgroud)

这里的例子

您会注意到,即使我们没有$scope.tab在OtherController中定义,它也会从Controller继承它,因为Controller是它在DOM中的父级.在显示选项卡的两个位置,您应该看到"0".这可能是你所指的"吊装",尽管这是一个完全不同的概念.

点击第一个按钮会发生什么?在这两个地方,我们都暴露了"标签",它们现在将显示"1".当您按下第二个按钮时,两者都会更新和增加.

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

.controller("OtherController", ["$scope", function($scope) {
    $scope.tab = 42;
}]);
Run Code Online (Sandbox Code Playgroud)

您会注意到此行为已更改 - 选项卡的值不再同步.

但现在令人困惑:我有两个叫做"tab"的东西是不一样的.其他人可能会使用"tab"在线下编写一些代码并无意中破坏我的代码.

我们过去通过使用命名空间来解决这个问题$scope,例如$scope.vm并将所有内容分配给命名空间:$scope.vm.tab = 0;

<div ng-controller="OtherController">
    <p>{{ vm.tab }}</p>
    <button ng-click="vm.incrementTab();">Increment</button>
</div>
Run Code Online (Sandbox Code Playgroud)

另一种方法是使用简单和简洁,this并利用controllerAs语法.

.controller("OtherController", function() {
    this.tab = 0;
});

<div ng-controller="OtherController as oc">
    <p>{{ oc.tab }}</p>
</div>
Run Code Online (Sandbox Code Playgroud)

对于习惯使用普通JS的人来说,这可能会更舒服,并且通过这种方式避免与其他Angular源冲突也更容易.您可以随时更改命名空间.由于你没有创建一个新的$scope实例,它的性能也有点"轻" ,但我不确定它有多大的收益.


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

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

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

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

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!
}
Run Code Online (Sandbox Code Playgroud)

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

function Controller() {
    var buttonClicked = false;

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

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

$("#existConfirmDialog").modal('hide'); 
Run Code Online (Sandbox Code Playgroud)

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