programing

AngularJS: $scope 변수를 함수에 전달하는 시기

padding 2023. 11. 4. 10:18
반응형

AngularJS: $scope 변수를 함수에 전달하는 시기

Angular로 더 나아지기 위해 TodoMVC 앱을 사용하고 있습니다.JS 프레임워크.14-16행의 index.html에서는 다음을 볼 수 있습니다.

<form id="todo-form" ng-submit="addTodo()">
    <input id="new-todo" placeholder="What needs to be done?" ng-model="newTodo" autofocus>
</form>

ng-submit 지시어가 새로운 Todo 모델을 인수로 전달하지 않고 addTodo() 함수를 어떻게 호출하는지 주목합니다.

잠시 후 19번 라인에서 바로 그 파일에서 다음 코드를 발견했습니다.

<input id="toggle-all" type="checkbox" ng-model="allChecked" ng-click="markAll(allChecked)">

저자가 이번에 allChecked 모델을 markAll() 함수에 전달하기로 결정한 것을 확인할 수 있습니다.제가 제대로 이해했다면, 그들은 $scope을 참조했을 수도 있습니다.모두 컨트롤러를 전달하는 대신 내부를 확인했습니다.

동일한 파일에서 두 가지 다른 접근 방식을 사용하는 이유는 무엇입니까?어떤 상황에서는 한 가지 접근 방식이 더 나을까요?이것은 불일치의 경우입니까 아니면 더 심층적인 논리가 사용되고 있습니까?

함수에 항상 인수를 전달하고 싶습니다.

  • 함수가 기대하는 매개 변수가 무엇인지 보다 명확합니다.
  • 모든 파라미터가 함수주입되기 때문에 단위시험이 용이합니다. (단위시험에 적합)

다음과 같은 상황을 고려해 봅니다.

$scope.addToDo = function(){
   //This declaration is not clear what parameters the function expects.
   if ($scope.parameter1){
      //do something with parameter2
   }    
}

그리고 더 나쁜건

$scope.addToDo = function(){
    //This declaration is not clear what parameters the function expects.
    if ($scope.someobject.parameter1){ //worse

    }    
}

범위 상속 때문에parameter2상위 범위에서 올 수 있음, 액세스parameter2기능 내부는 견고한 결합을 생성하며, 해당 기능을 장치 테스트하려고 할 때 문제가 발생합니다.

함수를 다음과 같이 정의하면 다음과 같습니다.

//It's clearer that the function expects parameter1, parameter2
$scope.addToDo = function(parameter1, parameter2){
   if (parameter1){
      //do something with parameter2
   }    
}

당신의 경우.parameter2는 상위 범위에서 상속되므로 보기에서 전달할 수 있습니다.단위 테스트를 할 때 모든 파라미터를 쉽게 전달할 수 있습니다.

ASP와 함께 일해본 적이 있다면요.NET MVC, 당신은 비슷한 것을 알아차릴 것입니다: 프레임워크는 매개변수를 직접 접근하는 대신 액션 함수에 주입하려고 합니다.Request아니면HttpContext물건

다른 사람들이 같이 일하는 것처럼 언급한 경우에도 좋습니다.ng-repeat

제 생각에는 컨트롤러와 모델이 각도로 명확히 구분되어 있지 않습니다.$scope 개체는 속성 및 메서드가 있는 모델과 같습니다(모델에는 논리도 포함되어 있음).OOP 배경을 가진 사람들은 이렇게 생각할 것입니다. 우리는 객체에 속하지 않는 매개변수만 전달합니다.사람이 이미 가지고 있는 수업처럼hands, 우리는 통과할 필요가 없습니다.hands모든 객체 방식에 대해.예를 들어 다음과 같은 코드가 있습니다.

//assume that parameter1 belongs to $scope, parameter2 is inherited from parent scope.
    $scope.addToDo = function(parameter2){ 
        if ($scope.parameter1){ //parameter1 could be accessed directly as it belongs to object, parameter2 should be passed in as parameter.
            //do something with parameter2
        }   
    }

이 대답에는 두 부분이 있는데, 첫 번째 부분은 어떤 것이 더 나은 선택인지에 대한 대답이고, 다른 부분은 둘 다 좋은 선택이 아니라는 사실입니다!


어느 것이 맞습니까?

이번 건은:

$scope.addToDo = function(params1, ...) {
    alert(params1);
}

왜죠? 왜냐하면 A - 그것은 시험할 수 있기 때문입니다.테스트를 작성하지 않더라도 테스트 가능한 코드는 거의 항상 보다 판독성이 높고 장기적으로 유지보수가 가능하기 때문에 이는 매우 중요합니다.

또한 B 때문에 더 좋습니다. 발신자에 관해서는 불가지론적입니다.이 기능은 범위의 존재 여부나 해당 범위의 구조에 의존하지 않기 때문에 다양한 컨트롤러/서비스/등에 의해 재사용될 수 있습니다.

대신 이 작업을 수행할 경우:

$scope.addToDo = function() {
    alert($scope.params1);
}

A와 B 둘 다 실패합니다.자체적으로 테스트가 쉽지 않고 사용하는 범위가 다를 수 있기 때문에 쉽게 재사용할 수 없습니다.

편집: 특정 범위와 매우 밀접하게 연결된 작업을 수행하고 템플릿에서 해당 기능을 실행하는 경우 재사용이 불가능한 상황이 발생할 수 있습니다.그 기능은 단순히 일반적이지 않습니다.그럴 경우에는 신경 쓰지 마세요, 일부 기능은 재사용이 불가능합니다.사용자의 기본 모드로 작성한 내용을 확인해 두되 경우에 따라 맞지 않을 수도 있습니다.


왜 둘 다 틀린 거지?

일반적으로 컨트롤러에서 로직을 수행해서는 안 되며, 그것이 서비스의 일이기 때문입니다.컨트롤러는 서비스를 사용하여 함수를 호출하거나 모델에서 함수를 노출할 수 있지만 정의해서는 안 됩니다.

이것이 왜 중요합니까?왜냐하면 그것은 다시 그 기능을 쉽게 재사용할 수 있게 하기 때문입니다.컨트롤러에 정의된 기능은 HTML에서 컨트롤러가 호출되는 방식에 제한을 두지 않고는 다른 컨트롤러에서 재사용할 수 없습니다. 서비스에 정의된 기능은 원하는 곳에 주입하여 사용할 수 있습니다.

하지만 나는 그 기능을 다시 사용할 필요가 없습니다! - 네!지금 당장은 아닐 수도 있고 이 특정 기능에 대해서도 절대로 사용하지 않을 수도 있지만 조만간 다시 사용할 필요가 없다고 확신한 기능을 다시 사용하고 싶어질 것입니다.그리고 나서 당신은 당신이 이미 절반을 잊어버린 코드를 재작업해야 할 것이고, 이것은 항상 추가적인 시간을 필요로 합니다.

처음부터 제대로 하고 할 수 있는 모든 논리를 서비스로 옮기는 것이 좋습니다.이렇게 하면 다른 곳에서 필요한 경우(다른 프로젝트에서도) 현재 범위 구조에 맞게 다시 작성할 필요 없이 바로 잡고 사용할 수 있습니다.

물론 서비스는 사용자의 범위를 모르기 때문에 첫 번째 버전을 사용해야 합니다.보너스!그리고 절대 좋게 끝나지 않을 서비스에 전체 범위를 넘겨주고 싶은 유혹에 넘어가지 마세요 :-)

이는 IMO의 최선의 선택입니다.

app.service('ToDoService', [function(){
    this.addToDo = function(params1, ...){
        alert(params1);
    }
}]);

그리고 컨트롤러 안에서:

$scope.addToDo = ToDoService.addToDo;

제가 "일반적인 규칙"을 썼다는 것을 주목하세요.경우에 따라서는 서비스가 아닌 컨트롤러 자체에서 기능을 정의하는 것이 타당합니다.한 가지 예로, 기능이 컨트롤러의 상태를 어떻게든 전환하는 것과 같이 범위 특정한 것에만 관련되는 경우를 들 수 있습니다.일이 이상해지지 않으면서 서비스에서 그렇게 할 수 있는 진짜 방법은 없습니다.

하지만 여기서는 그렇지 않은 것처럼 들립니다.

앵귤러의 선은 다음과 같이 말합니다.

범위를 템플릿에서 읽기 전용으로 처리범위를 컨트롤러에서만 쓰기로 처리

이 원칙에 따라 항상 템플릿에서 매개 변수를 사용하여 함수를 명시적으로 호출해야 합니다.

하지만, 어떤 스타일을 따르든 간에, 여러분은 조심해야만 합니다.priorities명령의 집행 순서와 명령의 집행 순서.예를 들어 , 을 사용하는 것은 두 지시어의 실행 순서를 모호하게 합니다.솔루션은 다음을 사용하고 있습니다.ng-change, 실행 순서가 명확한 경우: 값이 변경된 에만 실행됩니다.

ng-click, ng-submit 등과 같은 사용자 지정 동작 방법을 사용하면 호출되는 방법에 매개 변수를 전달할 수 있습니다.컨트롤러의 핸들러에게 자유롭게 사용할 수 없는 것을 전달하고 싶을 수도 있기 때문에 이는 매우 중요합니다.예를 들면,

angular.module('TestApp')
.controller('TestAppController', ['$scope', function($scope) {
    $scope.handler = function(idx) {
        alert('clicked ' + idx.toString());
    };
}]);

<ul>
    <li ng-repeat="item in items">
        <button ng-click="handler($index)">{ item }</button>
        <!-- $index is an iterator automatically available with ngRepeat -->
    </li>
</ul>

당신의 두번째 예의 경우, 그 이후로.allChecked를 정의하는 동일한 컨트롤러의 범위 내에 있습니다.markAll(), 당신이 전적으로 옳습니다. 아무것도 통과시킬 필요가 없습니다.우리는 다른 복사본을 만들 뿐입니다.

이 방법은 범위 내에서 사용 가능한 것을 사용하기 위해 단순히 리팩토링해야 합니다.

$scope.markAll = function () {
    todos.forEach(function (todo) {
        todo.completed = $scope.allChecked;
    });
};

따라서 이러한 방법에 매개 변수를 사용할 수 있는 옵션이 있지만 일부 시간만 필요합니다.

저는 이것이 단순히 코드가 일관되지 않은 경우라고 생각합니다.전에 이 질문에 대해 생각해 본 적이 있는데 다음과 같은 결론에 도달했습니다.

규칙: $scope 변수를 $scope 함수에 전달하지 마십시오.

컨트롤러 코드를 읽는 것은 구성 요소의 기능을 설명하기에 충분한 코드여야 합니다.뷰에는 비즈니스 로직이 포함되지 않아야 하며 바인딩(ng-model, ng-click 등)만 포함되어야 합니다.시야에 있는 무언가가 컨트롤러로 이동됨으로써 더 명확해질 수 있다면, 그렇게 해야 합니다.

예외:조건부 ng-class 문 허용(예: ng-class 문 허용)ng-class='{active:$index==item.idx') - 컨트롤러에 클래스 조건을 넣는 것은 매우 장황할 수 있으며 컨트롤러의 논리를 보기에서 아이디어로 흐리게 합니다.시각적 속성이면 보기에 보관합니다.

예외:항목을 반복적으로 작업하고 있습니다.예를 들어,

<ul ng-repeat="item in items">
    <li><a ng-click="action(item)"><h1>{{item.heading}}</h1></a></li>
</ul>

저는 컨트롤러와 뷰를 작성할 때 이 규칙을 따르는데, 그 규칙들은 효과가 있는 것 같습니다.도움이 되길 바랍니다.

당신이 할 수 있다는 것을 설명하기 위해서?같은 컨트롤러라고 가정하면 둘 사이에 기능적 차이는 없습니다.하위 범위가 생성되는 경우 컨트롤러와 동일한 범위를 더 이상 가질 수 없게 됩니다.

언급URL : https://stackoverflow.com/questions/18967127/angularjs-when-to-pass-scope-variable-to-function

반응형