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
'programing' 카테고리의 다른 글
CREATE TABLE의 1064 오류...TYPE=MYISAM (0) | 2023.11.04 |
---|---|
ASP에서 서버의 IP 주소를 가져오는 중입니다.NET? (0) | 2023.11.04 |
Node.js에서 새 줄에 추가하는 방법 (0) | 2023.11.04 |
두 XML 문서를 어떻게 비교하시겠습니까? (0) | 2023.11.04 |
jQuery: 속성이 값보다 큰 모든 요소 선택 (0) | 2023.11.04 |