[번역] directive scope에서 “@” 와 “=” 의 차이

STACKOVERFLOW의 What is the difference between ‘@’ and ‘=’ in directive scope 를 번역한 글 입니다.

 

276 / 189

제가 AngularJS 관련 문서도 읽어보고, fiddle에서 directive도 좀 만져봤어요. 내가 만졌던 fiddle.

일단 아래 코드좀 봐주세요:

  • html:
  • pane directive:

     

그런데 여기에서 이걸 잘 모르겠다는 거죠:

  • 왜 ‘@’ 에다가는 “{{title}}” 이걸 쓰고, ‘=’ 여기다가는 “title” 이렇게 쓸까요?
  • 엘리먼트에 attribute 쓰지 않고 그냥 부모 scope에 바로 접근할 수 있을까요?
  • 문서에서는 “isolated scope에서 expression을 통해 부모 scope로 데이터를 전달하는게 바람직하다”고 하는데,  사실 양방향 데이터 바인딩을 해도 잘 되는것처럼 보이거든요? 왜 expression을 쓰는게 낫다는거죠?

expression 쓰는거에 대해서는 다른 fiddle을 찾기는 했는데 말이죠… : http://jsfiddle.net/maxisam/QrCXh/

3
This would make an excellent technical interview question! –  jonathanconway Apr 22 at 5:32
2
@jonathanconway Only if you want to hire a developer that wouldn’t be able find this on SO when so challenged irl :p –  iwein May 7 at 11:26
Fair point. Ability to research and find answers is important. –  jonathanconway May 7 at 13:43

 

6 Answers

 

437

왜 ‘@’ 에다가는 “{{title}}” 이걸 쓰고, ‘=’ 여기다가는 “title” 이렇게 쓸까요?

@ 바인딩은 로컬/directive scope 요소를 DOM attribute의 값으로 사용하기 위해 쓰입니다. 만약 당신이 title=title1 이나 title=”title1″을 쓰면, ‘title’ DOM attribute의 값은 단순하게 title1이라는 string이 될 겁니다. 만약에 title=”{{title}}” 을 사용한다면,  ‘title’ attribute의 값은 {{title}} 의 값으로 대치되서 들어가겠지요, 부모 scope의 property가 무엇이든 간에, title은 지금 설정된 값으로 지정 될 겁니다. 왜냐하면 attribute의 값은 항상 string이기 때문이죠.

= 바인딩은 로컬/directive scope 요소를 부모 scope 요소로 쓰는데 사용됩니다. 그렇기 때문에 = 를  쓰면, 당신은 parent model/scope의 요소의 이름을 DOM attribute의 이름으로 쓸 수 있는거지요. 또 그렇기 때문에 당신은 = 랑은 {{}}을 같이 쓸 수가 없지요.

@ 를 쓰면, 당신은 title=”{{title}} 어쩌구 저쩌구 ” 처럼 쓸 수 있어요. {{title}} 값 뒤에, String이 붙어서 합쳐지는거지요. 마지막으로 합쳐진 string을 로컬/directive scope 요소가 받게 됩니다. (= 로는 이런걸 할 수 없어요, @로만 할 수 있어요.)

@을 쓸때, 아마 attr.$observe(’tile’, function(value) {…})  를 써야 할 지도 모르겠네요. 만약에 당신이 link function 안에서 이걸 사용해야 한다면요. 예를 들면, if(scope.title == “…”) 이건 당신이 생각한대로 작동하지 않을거에요. 이 Attribute에 비동기적으로 접근할 수 밖에 없다는 사실을 꼭 명심하세요. 만약 당신이 이 값을 template에서만 사용한다면, 당신은 $observe()를 쓸 필요가 없어요. 예를 들면, template : ‘<div>{{title}}</div>’ 처럼요.

=를 쓸때는, $observe 안 써도 됩니다. 괜찮아요.

엘리먼트에 attribute 쓰지 않고 그냥 부모 scope에 바로 접근할 수 있을까요?

네! 하지만 isolate scope를 사용하지 않을때만요. 당신의 custom directive 에서 다음과 같은 내용을 지우세요 ~~ scope : { … } ~~ 이러면 directive에서 새로운 scope를 만들지 않고, 부모 scope를 사용합니다. 이러면 부모 scope의 모든 property에 접근 할 수 있지요.

문서에서는 “isolated scope에서 expression을 통해 부모 scope로 데이터를 전달하는게 바람직하다”고 하는데,  사실 양방향 바인딩을 해도 잘 되는것처럼 보이거든요? 왜 expression을 쓰는게 낫다는거죠?

음, 양방향 바인딩은 로컬/directive scope와 부모 scope 사이에 데이터를 공유할 수 있게 해주죠. “Expression 바인딩” 은 directive가 DOM attribute에 정의되어 있는  expression (이나 함수)를 호출하게끔 해주죠, – 그리고 그걸로 argument 형식으로 데이터도 expression이나 function으로 보낼 수 있지요. 하여간, 부모 scope랑 데이터를 공유할 필요가 없으면 ( 그러니까, 부모 scope에 정의된 함수만 부르고 싶다면 ) “&” 이걸 활용하세요.

추가적으로, 아래 내용을 한번 살펴보시는게 어떠신지,

shareimprove this answer
29
Good stuff, I wish the documentation was as clear on this topic. –  iwein Dec 30 ’12 at 13:04
5
Writing ‘@’ or ‘=’ is so much clearer then writing “eval-dom” or “parent-scope” or any other human-readable text. Good design decision. –  Den Mar 3 ’14 at 16:57
5
@ (‘at’) copies the value of the ‘ATtribute’. = (‘equals’) is equivalent to saying the key equals your expression. This, at least, is how I keep them strait. –  Matt DeKrey Jun 25 ’14 at 12:18
2
@JonathanAquino, yes that works, but @ would be more appropriate — with foo="{{1+1}}" — because we don’t need two-way data binding here. The point I tried to make in the comment above is that we should use = only when the directive needs two-way data binding. Use @ or & otherwise. –  Mark Rajcok Oct 17 ’14 at 18:15
1
Thank you for pointing out the possibility to access the parent scope after removing the scope def in the directive! –  cessor May 6 at 13:10

 

이미 굉장한 답변들이 많지만, 제가 유용하게 여기는 ‘@’,’=’,’&’ 바인딩간의 차이에 대한 제 견해를 적어볼게요.

이 세가지 바인딩 방법 모두 element의 attribute를 통해 부모 scope에서 directive의 isolated scope로 데이터를 넘기는 방법이지요:

  1. @ 바인딩은 스트링을 넘기기 위해 사용합니다. 이 스트링은 값을 더 풍부하게 만들기 위해 {{}} 표현법을 지원 합니다.
  2. = 바인딩은 양방향 바인딩을 위해 사용합니다. 부모 scope의 모델이 directive의 isolated scope에 연결되지요. 하나를 바꾸면 나머지도 바뀌어요.
  3. & 바인딩은 directive scope로 함수를 전달하기 위해서 사용합니다. 함수는 directive의 부모 scope에 넣어지구요, 파라미터도 지원합니다. 예를 들면, 부모 scope에 hello(name)이라는 함수가 있으면, directive에서는 $scope.hello({name:’world’}) 이런 식으로 사용할 수 있게 되는 거지요.

이걸 더 쉽게 기억하기 위해서 이렇게 부르면 어떨까해요,:

  • @ Attribute string binding
  • = Two-way model binding
  • & Callback method binding

특수문자 모양에 연관지어서 directive내에서 어떤 역할을 할 수 있을지 기억할 수도 있어요:

  • @ string
  • = model
  • & method

어쨌든 저한테 유용한 순서대로 적으라면 아래와 같네요:

  1. =
  2. @
  3. &
shareimprove this answer
1
Actually, "&" does support arguments (or, rather, locals) of the form: callback({foo: "some value"}), which could then be used <my-dir callback="doSomething(foo)">. Otherwise, good answer – New Dev Mar 20 at 15:29
@New Dev thanks, corrected. –  pixelbits Mar 22 at 4:49
3
Should be accepted answer. Here is an concise article with the same information, but with added code examples: umur.io/… –  Kevin Apr 28 at 15:37

‘=’는 양방향 바인딩이에요, 얘는 부모 scope의 변수를 참조 할 수 있게 해줘요. 이게 무슨 뜻이냐면, directive에서 변수 값을 바꾸면, 부모 scope에서도 그 값이 잘 바뀔거라는 뜻이죠.

‘@’를 쓰면 directive 안으로 부모 scope의 변수가 복사되서 들어와요.

내가 알기로는, 이것도 잘 작동 할 거에요.

bi-title은 부모 scope의 변수의 값을 받을거고, 이 값은 directive 내에서 바뀔 수 있을 거에요.

만약 부모 scope의 여러 변수를 수정해야 할 필요가 있다면, directive 내에서 부모 scope의 함수를 통해 수정하는게 더 나을겁니다. (아니면 service를 통하시던지요!)

shareimprove this answer
Yes, that part I get, see the fiddle in the question. But what about the parts that are unclear? –  iwein Dec 27 ’12 at 7:25
3
the thing is that {{}} doesn’t work with =. = isn’t evaluated, but the string is taken as the property name as is. Thanks for the answer! –  iwein Dec 30 ’12 at 13:06
I don’t think that = is just for variables in the parent scope. It works with any expression (e.g., 1+1). – Jonathan Aquino Oct 15 ’14 at 22:42
@JonathanAquino you’re right that it evaluates expressions. imho this is actually weird and I wouldn’t use it that way. It’s this kind of clever tricks that make directive scopes so hard for me to understand in the first place. –  iwein May 16 at 12:23
Am I the only one who think this answer is wrong ! ‘=’ mean angular expect a javascript expression and will do a bidirectionnal mapping if a scope variable is passed. Whereas @ mean angular expect a String and that all. In fact, it’s true that if you use @ in combinaison with {{}} you will clone the value of the variable. But it’s not the definition of @ ! –  Luc DUZAN May 21 at 7:34

아래 내용에 대해 예제를 더 보고싶으면, 아래로 가세요 : http://jsfiddle.net/juanmendez/k6chmnch/

 

shareimprove this answer
hi,, I just wanted to share an example.. just stackoverflow threw me off.. –  juanmendezinfo Nov 22 ’14 at 2:06
There are several examples linked in the question and top answer. What does this add? –  iwein Nov 24 ’14 at 9:00
@iwein, it adds clarity. If I could understand and assimilate full-featured examples, I would not need this site.–  Tony Ennis Jan 9 at 15:47
juan, maybe fix your typos? ‘transclude’ is misspelled. better yet, remove it (and everything else, like ‘replace’) that does not contribute directly to the problem so your solution is even simpler and clearer. +1 for the example. –  Tony Ennis Jan 9 at 15:49
@TonyEnnis should it be compiled into the accepted answer as sort of a summary? –  iwein Jan 13 at 7:13

Directive에 scope를 추가하는거, 3가지 방법으로 할 수 있어요:

  1. Parent scope: 이게 기본적인 scope 상속 방법이에요.

Directive랑 그 부모 (Controller 나 Directive 에 들어가있는) Scope가 동일한 scope가 되요. directive 내에서 scope를 수정하면, 부모 Controller에도 동일하게 반영이 되죠. 기본 상속 방식임으로 딱히 뭐 손 댈 필요 없이 바로 적용됩니다.

  1. Child scope: directive 에서 여러분이 특정하게 지정한 부모 scope의 변수를 상속받아서 자식 scope를 만드는 상속 방식이에요.

directive 내에서 어떤 변수를 바꿔도, 부모 scope에는 반영되지 않죠. 하지만 scope 변수의 속성을 바꾸면, 이건 실제로 부모 scope 변수에도 적용된답니다.

예를 들면,

 

  1. Isolated scope: 얘는 당신이 controller scope에서 상속받지 않는 새로운 scope를 새로 만들고 싶을때 사용하는 방식이죠.

얘는 plugin 처럼 범용적인 directive 만들때, 부모 scope의 영향을 절대 받지 않아야 할 때 사용합니다.

정말로 부모 scope랑 전혀 상호작용 할 필요가 없으면, scope를 빈 object로 선언해버리면 되요. 이렇게요 :

 

그런데, 이런 경우는 진짜 드문 경우겠죠. 우리는 부모 scope 와 제한적으로나마 상호작용 하고 싶을거고, 부모 scope의 변수들을 사용 하고 싶을거에요. 아래 방법들을 살펴보시겠어요? :

@ 를 쓰면 controller scope에서의 변화가 directive scope에 같이 적용됩니다. 그런데 그 반대는 아니에요. directive scope에서 변화를 줘도 controller scope에는 적용되지 않아요.

@ 는 expression을 통해 (directive)의 attribute에 포함되어야 해요. 이게 되게 중요합니다; “@” 을 쓰면, 항상 attribute의 값이 {{}} 안에 들어가 있어야 하거든요.

= 는 상호작용을 할 수 있게 해요. directive scope에서 바꾸면, controller scope에서도 그대로 잘 바뀌는거죠.

& 는 주로 controller scope의 함수 (method) 를 바인딩 할 때 쓰여요.

shareimprove this answer

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.