AngularJS最佳实践 - $scope vs this

4

我试图遵循最佳实践,但在何时使用 $scope 和何时使用 'this' 方面存在困惑。我有一个简单的示例,使用的是 AngularJS 1.4.8。

<!DOCTYPE html>
<html ng-app="testApp">
<head>
<title>Test button action</title>
<script src="./angular.min.js"></script>
<script src="./testBtn.js"></script>
</head>
<body>
    <div ng-controller="TestCtrl as test">
        <button ng-click="testBtn()">test button</button>
        {{testResult}}
    </div>
    <div ng-controller="Test1Ctrl as test1">
        <select ng-model="chosen" ng-change="getDetails(chosen)">
            <option value='option1'>Option1</option>
            <option value='option2'>Option2</option>
            <option value='option3'>Option3</option>
        </select>
        <p>You choose {{test1Result}}</p>
    </div>
</body>
</html>

testBtn.js文件长这样:

(function() {
    'use strict';
    angular.module("testApp", []);
    angular.module("testApp").controller("TestCtrl", testCtrl);
    angular.module("testApp").controller("Test1Ctrl", test1Ctrl);
    function testCtrl($scope) {
        $scope.testBtn = testBtn;
        function testBtn() {
            if (this.testResult == '' || this.testResult == null) {
                this.testResult = "Button clicked";
            } else {
                this.testResult = '';
            }
        }
    }
    function test1Ctrl($scope) {
        $scope.getDetails = getDetails;
        function getDetails(opt) {
            this.test1Result = opt;
        }
    }
})();

当前代码可以正常运行。但是,如果我将两个函数改为this.testBtn = testBtn;this.getDetails = getDetails;,那么单击按钮或选择选项将无法正常工作,并且控制台日志中不会显示任何错误。

为什么这些示例中的'this'无法正常工作?是否有更好的方法来解决这个问题?

4个回答

3
当您使用ng-click="testBtn()"时,Angular默认会在控制器的$scope对象中查找testBtn函数。因此,如果您没有将上述函数定义为$scope.testbtn = function()...,则Angular不会执行任何操作,因为该函数未定义。
在控制器的as语法中,使用this作用域来定义函数/模型。最佳实践是将其存储在控制器的第一行变量中,以避免出现任何作用域冲突。
angular.module("testApp").controller("Test1Ctrl", test1Ctrl);
    function testCtrl($scope) {
        var ctrlScope = this;
        ctrlScope.testBtn = function() {
            if (ctrlScope.testResult == '' || ctrlScope.testResult == null) {
                ctrlScope.testResult = "Button clicked";
            } else {
                ctrlScope.testResult = '';
            }
        }
    }

<div ng-controller="TestCtrl as test">
    <button ng-click="test.testBtn()">test button</button>
    {{test.testResult}}
</div>

"as"语法在我的观点中使代码更易读,并且如果控制器嵌套,它还可以处理名称冲突。

非常感谢您的解释。现在我已经能够从我的代码中消除$scope了。 - user3017691

1

您需要在视图中使用test和test1控制器别名。然后您必须在控制器中使用this。优势:具有相同模型名称的嵌套控制器。

<div ng-controller="TestCtrl as test">
    <button ng-click="test.testBtn()">test button</button>
    {{test.testResult}}
</div>
<div ng-controller="Test1Ctrl as test1">
    <select ng-model="test1.chosen" ng-change="test1.getDetails(test1.chosen)">
        <option value='option1'>Option1</option>
        <option value='option2'>Option2</option>
        <option value='option3'>Option3</option>
    </select>
    <p>You choose {{test1.test1Result}}</p>
</div>

$scope在控制器绑定到像ng-route模块或像ui-router这样的状态时使用。


$scope在控制器绑定到像ng-route模块或类似ui-router的状态时使用。为什么我不能在没有ng-route或state的情况下使用$scope?为什么编辑要求我在controllerAs语法中必须使用'this'关键字? - Avinash

0

this 在 JavaScript 中非常通用,它指的是当前对象的自我引用,但在 AngularJS 中,要在控制器和 HTML 之间共享任何内容,必须通过 $scope 进行共享。实际上,您的代码首先在 $scope.testBtn = testBtn; 中注册了 "testBtn",然后在 function testBtn() 中实现。为了理解它,让我在这里重写一下:

$scope.testBtn = this.testBtn;
this.testBtn = function() {}

JavaScript语言不会遇到任何排序问题,并将其理解为:
this.testBtn = function() {}
$scope.testBtn = this.testBtn;

在您的函数内部,this将引用您所在的对象,即$scope,因此您只能通过函数内部的this访问$scope中的任何内容,因为它已经在$scope中注册。

我建议您使用$scope而不是使用this以避免混淆,也不需要注册然后实现,您可以一步完成它,这很令人困惑。在这里,我正在重写您的控制器:

function testCtrl($scope) {
    $scope.testBtn = function () {
        if ($scope.testResult == '' || $scope.testResult == null) {
            $scope.testResult = "Button clicked";
        } else {
            $scope.testResult = '';
        }
    }
}

0

我正在使用vm作为controllerAs变量。

John Papa有一篇很棒的文章,对我和我的团队来说,它成为了一种良好的实践。

AngularJS的Controller As和vm变量

主要优点:

  1. 提供了一种一致且易读的方法来创建控制器中的绑定
  2. 消除了处理此作用域或绑定(即嵌套函数中的闭包)的任何问题
  3. 从控制器中删除了$scope,除非我明确需要它用于其他事情
  4. 让我感到高兴,因为它很短 :)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接