Use controlleras instead of $scope

Time:2021-1-19

What did controllers do

When we define a route

.state('account.register', {
    url: '/register',
    templateUrl: 'app/account/register.html',
    controller: 'RegisterCtrl',
    controllrtAs: 'vm'
})

In the angular source code:

locals.$scope[state.controllerAs] = controllerInstance;

It can be found that angular takes the instance of the controller as an object property named by the value of controlleras in $scope.
We useBatarangCheck it out
Use controlleras instead of $scope

It turns out that’s true.

Why use controlleras

  1. The $scope is inherited based on the prototype. For example, when we search for a user object, angular will first find out whether there is a user in the current $scope. If not, it will continue to search the upper $scope until $rootscope.
    Use controlleras instead of $scope
    In controlleras, suppose we use controlleras

    UserCtrl as ctrl
    Angular mounts the controller itself on $scope, and the user becomes ctrl.user , there will be no layer by layer search process mentioned above. In many cases, for example, in nested routing, the above $scope prototype based search sometimes provides some convenience, but these can be implemented with services, and should also be implemented with services.
    Use controlleras instead of $scope

  2. When you first contact angular, you will be recommended to bind all data to an object of $scope (such as$ scope.data )To avoid some problems that may be caused by the replication of JS values and the reference of objects (most of the newcomers in the company have indeed encountered such problems), and after using controlleras, you don’t need this step, because they are.

  3. Because if you don’t use $scope, you can’t use methods like $on, $watch and $emit. These methods should be used as little as possible, so that you can better control the code in the project. When you have to use these methods, you can refer to the following cases.

  4. It’s easy for newcomers to learn. I find that newcomers often can’t understand $scope. After using controller as VM, it’s easier to understand VM (short for view model) as a view model.

What to do when you have to use $watch ($on, $emit, $broadcast)

When this happens, we can use $scope as a simple service. It provides the above methods, such as:

function MyCtrl ($scope) {
    var vm = this;
    vm.name = 'liulei';
    vm.count = 0;
    $scope.$watch('vm.count', function (newVal, oldVal) {
        vm.count ++;
    });
}

Using controlleras in instructions

In the instruction, if data binding is not required, we simply set the scope option totrueperhaps{}That is to say, what should we do when we need to bind a value or object from outside to the instruction? Because we know that if we use the scope option, it must be bound to the scope object of the instruction. Here, we can directly use the bindtocontroller option to load the code

'use strict';
angular.module('nodeInAction')
.directive('countCard', function () {
    return {
        restrict: 'E',
        controllerAs: 'vm',
        scope: {},
        bindToController: {
            icon: '@',
            title: '@',
            count: '@',
            unit: '@',
            colorStyle: '@'
        },
        templateUrl: 'app/components/countCard/countCard.html',
        controller: function () {
            var vm = this;        
            console.log(vm);
        }
    };
});

Use controlleras instead of $scope
The result is what we want. The role of bindtocontroller is also well understood, that is, binding attributes to the controller itself.
You can also write like this

'use strict';
angular.module('nodeInAction')
.directive('countCard', function () {
    return {
        restrict: 'E',
        scope: {
            icon: '@',
            title: '@',
            count: '@',
            unit: '@',
            colorStyle: '@'
        },
        controllerAs: 'vm',
        bindToController: true,
        templateUrl: 'app/components/countCard/countCard.html',
        controller: function () {
            var vm = this;        
            console.log(vm);
        }
    };
});

The effect is the same.