AngularJS에서 ng-repeat 범위가있는 지시 격리 범위


95

격리 범위가있는 지시문이 있습니다 (다른 위치에서 지시문을 재사용 할 수 있도록).이 지시문을에서 사용할 때 ng-repeat작동하지 않습니다.

이 주제에 대한 모든 문서와 Stack Overflow 답변을 읽었으며 문제를 이해했습니다. 나는 모든 일반적인 문제를 피했다고 믿습니다.

따라서 ng-repeat지시문에 의해 생성 된 범위 때문에 내 코드가 실패한다는 것을 이해합니다 . 내 자신의 지시문은 격리 범위를 만들고 부모 범위의 개체에 양방향 데이터 바인딩을 수행합니다. 내 지시문은이 바인딩 된 변수에 새 개체 값을 할당하며 내 지시문이없이 사용되면 완벽하게 작동합니다 ng-repeat(부모 변수가 올바르게 업데이트 됨). 그러나를 사용 ng-repeat하면 할당이 ng-repeat범위에 새 변수를 만들고 상위 변수에 변경 사항이 표시되지 않습니다. 이 모든 것은 내가 읽은 것을 바탕으로 예상 한 것입니다.

또한 주어진 요소에 여러 지시문이있을 때 하나의 범위 만 생성된다는 것도 읽었습니다. 그리고 priority각 지시문에 a 를 설정하여 지시문이 적용되는 순서를 정의 할 수 있습니다. 지시문은 우선 순위별로 정렬 된 다음 컴파일 기능이 호출됩니다 ( http://docs.angularjs.org/guide/directive 에서 우선 순위 단어 검색 ).

그래서 우선 순위를 사용하여 내 지시문이 먼저 실행되고 분리 범위를 생성하고 ng-repeat실행될 때 부모 범위에서 프로토 타입 적으로 상속되는 범위를 만드는 대신 분리 범위를 재사용 할 수 있기를 바랐습니다 . ng-repeat문서 상태 우선 순위 레벨에서 지시어 실행합니다 1000. 1더 높은 우선 순위 레벨인지 낮은 우선 순위 레벨 인지 는 명확하지 않습니다 . 1지시문에서 우선 순위를 사용했을 때 차이가 없어서 2000. 그러나 그것은 상황을 더 악화 undefined시킵니다. 내 양방향 바인딩이 되고 내 지시문은 아무것도 표시하지 않습니다.

내 문제를 보여주기 위해 바이올린을 만들었습니다 . priority내 지시에 설정을 주석으로 처리했습니다 . 이름 개체 목록과 이름 개체의 이름 name-row및 성 필드를 표시 하는 지시문이 있습니다. 표시된 이름을 클릭하면 selected메인 스코프에 변수 를 설정하고 싶습니다 . 이름 배열, selected변수는 name-row양방향 데이터 바인딩을 사용 하여 지시문에 전달됩니다 .

주 범위에서 함수를 호출하여이 작업을 수행하는 방법을 알고 있습니다. 또한 selected다른 개체 안에 있고 외부 개체에 바인딩하면 모든 것이 작동 한다는 것도 알고 있습니다. 그러나 현재로서는 이러한 솔루션에 관심이 없습니다.

대신 내가 가진 질문은 다음과 같습니다.

  • 어떻게 방지 할 ng-repeatprototypically의 상위 범위에서 상속하고, 대신 내 지시어의 분리-범위를 사용하는 것으로 범위를 만들 수?
  • 2000디렉티브의 우선 순위 레벨 이 작동하지 않는 이유는 무엇 입니까?
  • Batarang을 사용하여 사용중인 스코프 유형을 알 수 있습니까?

1
일반적으로 지시문이 다른 지시문과 동일한 요소에 사용되는 경우 격리 범위를 사용하지 않으려 고합니다. 자체 범위 속성을 만들고 ng-repeat로 작업해야하므로 scope: true지시문에 사용 하는 것이 좋습니다 . 또한 참조하십시오 (아직하지 않은 경우) stackoverflow.com/questions/14914213/… 또한 지시문이 여러 위치에서 사용된다고해서 격리 범위를 자동으로 사용해야한다는 의미는 아닙니다.
Mark Rajcok 2013 년

나는 당신의 대답을 많이 읽었지만 (그들은 훌륭하지 않습니다, 그것들을 써 주셔서 감사합니다), 당신의 질문을 읽은 적이 없었습니다 :-). 나는 당신이 연결 한 것을 읽었습니다. 격리 범위 지시문은 다른 지시문과 함께 사용할 수 없습니다. 나는 그러한 지침이 구성 요소이므로 다른 지침과 혼합 할 필요가 없다는 정서에 동의합니다. (지금까지) 한 가지 예외는 ng-repeat. 독립형 지시문을 .NET과 혼합 할 수있는 것이 중요하다고 생각합니다 ng-repeat. ... 계속하려면
디팍 Nulu

위에서 계속 ... 따라서 요소에 대한 범위가있는 지시문이 하나만 있어야한다면 범위가 ng-repeat없어야합니다. ng-repeat범위를 갖는 것은 일반적인 사용 사례에 적합하므로 변경을 제안하지 않습니다. 대신 Alex Osborn의 답변에서 언급했듯이 ng-repeat자체 범위를 만들지 않는 반복 지시문을 만들 것이라고 생각 합니다. 그런 다음 자체 격리 범위가있는 반복 지시문에 사용할 수 있습니다. ... 계속하려면
디팍 Nulu

지시문을 반복하는 코드는 이제 사용 여부 ng-repeat또는 사용자 지정 범위없는 반복 지시문 을 알아야합니다 . 나는 "호출자"가 이것을 아는 것은 괜찮다고 생각하지만 "callee"(반복되는 지시)가 그것이 반복되고 있는지 아닌지를 아는 것은 옳지 않다. ... 계속하려면
디팍 Nulu

여기에 주석을 달아서 조금 미쳐가는 중 ... :-) ngRepeat 자체 범위를 만들어야합니다. 여기에 격리 범위가 필요한 이유는 무엇입니까?
Josh David Miller

답변:


203

좋아, 위의 많은 의견을 통해 혼란을 발견했습니다. 첫째, 몇 가지 설명이 있습니다.

  • ngRepeat는 선택한 격리 범위에 영향을주지 않습니다.
  • 당신의 지시자의 속성에서 사용하기 위해 ngRepeat에 전달 된 매개 변수는 않습니다 prototypically 상속 범위를 사용
  • 지시문이 작동하지 않는 이유는 격리 범위와 관련이 없습니다.

다음은 동일한 코드이지만 지시문이 제거 된 예입니다.

<li ng-repeat="name in names"
    ng-class="{ active: $index == selected }"
    ng-click="selected = $index">
    {{$index}}: {{name.first}} {{name.last}}
</li>

다음은 작동하지 않음을 보여주는 JSFiddle 입니다. 지시문에서와 똑같은 결과를 얻습니다.

왜 작동하지 않습니까? AngularJS의 범위는 프로토 타입 상속을 사용하기 때문입니다. selected부모 범위 의 값 은 기본 입니다. JavaScript에서 이것은 자식이 동일한 값을 설정하면 덮어 쓰게됨을 의미합니다. AngularJS 범위에는 황금률이 ​​있습니다. 모델 값 에는 항상 a .가 있어야 합니다. 즉, 그들은 결코 원시적이어서는 안됩니다. 자세한 내용은 이 SO 답변 을 참조하십시오.


다음은 스코프의 초기 모습입니다.

여기에 이미지 설명 입력

첫 번째 항목을 클릭하면 이제 범위가 다음과 같이 표시됩니다.

여기에 이미지 설명 입력

selectedngRepeat 범위에 새 속성이 생성되었습니다. 컨트롤러 범위 003은 변경되지 않았습니다.

두 번째 항목을 클릭하면 어떤 일이 발생하는지 짐작할 수 있습니다.

여기에 이미지 설명 입력


따라서 귀하의 문제는 실제로 ngRepeat로 인한 것이 아니라 AngularJS의 황금률을 위반하여 발생합니다. 이를 수정하는 방법은 단순히 객체 속성을 사용하는 것입니다.

$scope.state = { selected: undefined };
<li ng-repeat="name in names"
    ng-class="{ active: $index == state.selected }"
    ng-click="state.selected = $index">
    {{$index}}: {{name.first}} {{name.last}}
</li>

다음은 이 작업을 보여주는 두 번째 JSFiddle 입니다.

처음에 범위는 다음과 같습니다.

여기에 이미지 설명 입력

첫 번째 항목을 클릭 한 후 :

여기에 이미지 설명 입력

여기서 컨트롤러 범위는 원하는대로 영향을받습니다.

또한 이것이 격리 범위를 사용하여 지시문과 함께 작동한다는 것을 증명하기 위해 (다시 말하지만 이것은 문제와 관련이 없기 때문에) 여기에 JSFiddle 도 있습니다.보기는 객체를 반영해야합니다. 필요한 유일한 변경 사항은 primitive 대신 객체 를 사용하는 것입니다 .

초기 범위 :

여기에 이미지 설명 입력

첫 번째 항목을 클릭 한 후 범위 :

여기에 이미지 설명 입력

결론 : 다시 한 번, 귀하의 문제는 격리 범위와 관련된 것이 아니며 ngRepeat의 작동 방식과 관련이 없습니다. 문제는 바로이 문제를 일으키는 것으로 알려진 규칙을 위반하고 있다는 것입니다. AngularJS의 모델은 항상 ..


격리 범위 및 양방향 데이터 바인딩을 사용한 지시문에 대한 실험을 통해 .황금률은 프로토 타입 상속이있는 범위에만 필요 하다고 믿게 되었습니다. 격리 범위를 사용하면 관심 scope: {}있는 변수가 지시문 의 정의에 정의되므로 해당 변수는 처음부터 격리 범위에 존재합니다. 또한 격리 범위가 부모 범위에서 프로토 타입으로 상속되지 않기 때문에 부모 변수를 마스킹하지 않습니다. 즉, 마스킹 할 "상위"범위가 없습니다.
Deepak Nulu 2013 년

1
또한 말 했어야 합니다. 지시문이 하위 범위를 생성하지 않지만 하위 범위 가 필요한 컨텍스트에서 쉽게 사용할 수 있습니다 . ngRepeat는 하나의 경우입니다. 초월도 마찬가지입니다. 나를 믿으십시오- . .
Josh David Miller

1
@JoshDavidMiller가 마침내 내 혼란을 해결할 수 있었던 AngularJS Google 그룹에 대한 토론 !
Deepak Nulu 2013 년

2
이 멋진 다이어그램을 어디서 얻습니까? 나는 이것들을 게시하는 다른 사용자도 보았습니다.
Asad Saeeduddin 2014

3
@Asad, 나는 최근에 GitHub의에 도구를 넣어, 그것은라고 요정 $ 범위 .
Mark Rajcok 2015

6

질문에 직접 답하지 않고 대신 다음 바이올린을 살펴보십시오.

http://jsfiddle.net/dVPLM/

요점은 Angular의 기존 동작에 맞서 싸우고 변경하는 대신, ng-repeat재정의를 시도하는 대신 작업하도록 지시문을 구성 할 수 있다는 것입니다.

템플릿에서 :

    <name-row 
        in-names-list="names"
        io-selected="selected">
    </name-row>

당신의 지시에서 :

    template:
'        <ul>' +      
'            <li ng-repeat="name in inNamesList" ng-class="activeClass($index)" >' +
'                <a ng-click="setSelected($index)">' +
'                    {{$index}} - {{name.first}} {{name.last}}' +
'                </a>' +
'            </li>' +
'        </ul>'

귀하의 질문에 대한 답변 :

  • ng-repeat 스코프를 만들 것입니다. 정말로 이것을 변경하려고해서는 안됩니다.
  • 지시문의 우선 순위는 실행 순서가 아닙니다. 참조 : AngularJS : HTML 컴파일러는 컴파일 순서를 어떻게 정렬합니까?
  • Batarang에서 성능 탭을 확인하면 각 범위에 바인딩 된 표현식을 볼 수 있으며 이것이 예상과 일치하는지 확인할 수 있습니다.

빠른 답변 감사합니다. 내가 시도하는 것이 곡식에 어긋나면 조금 슬프다 (AngularJS는 그럼에도 불구하고 멋진 프레임 워크입니다). 지시문은 재사용 가능한 구성 요소를 의미합니다. 글을 쓸 때 저자는 그것과 함께 사용 될지 여부에 대해 걱정할 필요가 ng-repeat없습니다. 처음 작성 될 때 ng-repeat. 그리고 언젠가는와 함께 사용될 수 ng-repeat있으며 그 시점에서 다시 작성하지 않고 작동합니다. AngularJS의 향후 릴리스에서이를 가능하게 할 것입니다.
Deepak Nulu 2013 년

위의 의견을 명확히하고 싶습니다. 사용 여부를 걱정하지 않는 디렉티브를 작성할 수 있다고 생각합니다 ng-repeat. 그러나 지시문 자체 범위에서 양방향 바인딩을 변경하는 대신 부모 범위의 변수를 수정할 수 있도록 지시문에 함수를 전달해야하는 것으로 보입니다. 양방향 바인딩 및 재사용 가능한 지시문은 AngularJS에 대해 제가 가장 좋아하는 두 가지 사항이며 ng-repeat연고에서 파리로 입증되었습니다. 아마도 ng-repeat자체 범위를 만들지 않는 동등한 것을 작성할 수 있습니다 .
Deepak Nulu 2013 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.