객체 리터럴과 함수로 선언 된 녹아웃 뷰 모델의 차이점


195

녹아웃 js에서 View Models가 다음 중 하나로 선언 된 것을 볼 수 있습니다.

var viewModel = {
    firstname: ko.observable("Bob")
};

ko.applyBindings(viewModel );

또는:

var viewModel = function() {
    this.firstname= ko.observable("Bob");
};

ko.applyBindings(new viewModel ());

둘 사이의 차이점은 무엇입니까?

knockoutjs Google 그룹 에서이 토론 을 찾았 지만 실제로 만족스러운 답변을주지 못했습니다.

예를 들어 다음과 같은 데이터를 사용하여 모델을 초기화하려는 이유를 알 수 있습니다.

var viewModel = function(person) {
    this.firstname= ko.observable(person.firstname);
};

var person = ... ;
ko.applyBindings(new viewModel(person));

그러나 내가 그렇게하지 않으면 내가 선택한 스타일이 중요합니까?


나는 차이가 있다고 생각하지 않습니다. 필자는 일반적으로 생성자 패턴을 사용합니다 prototype(예를 들어 서버에서 데이터를 가져 와서 뷰 모델을 적절하게 업데이트하는 방법과 같은 메소드). 그러나 여전히 객체 리터럴의 속성으로 명시 적으로 선언 할 수 있으므로 실제로 차이를 볼 수는 없습니다.
James Allardice

4
이것은 녹아웃과는 아무런 관련이 없으며 JavaScript로 커스텀 객체를 쉽게 인스턴스화 할 수 있습니다.
zzzzBov

1
@Kev viewModel이 생성자 함수이면 var PersonViewModel = function () {...}과 같이 UpperCase에 작성합니다.
엘리자베스

답변:


252

함수를 사용하여 뷰 모델을 정의하면 몇 가지 장점이 있습니다.

주요 이점은 this생성중인 인스턴스와 동일한 값에 즉시 액세스 할 수 있다는 것입니다. 이것은 당신이 할 수 있음을 의미합니다 :

var ViewModel = function(first, last) {
  this.first = ko.observable(first);
  this.last = ko.observable(last);
  this.full = ko.computed(function() {
     return this.first() + " " + this.last();
  }, this);
};

따라서 계산 된 옵저버 블은 this다른 범위에서 호출 된 경우에도 의 적절한 값에 바인딩 될 수 있습니다 .

객체 리터럴을 사용하면 다음을 수행해야합니다.

var viewModel = {
   first: ko.observable("Bob"),
   last: ko.observable("Smith"),
};

viewModel.full = ko.computed(function() {
   return this.first() + " " + this.last();
}, viewModel);

이 경우 viewModel계산 된 Observable에서 직접 사용할 수 있지만 즉시 (기본적으로) 평가되므로 viewModel개체 리터럴을 닫을 때까지 정의되지 않은 것처럼 개체 리터럴 내에 정의 할 수 없습니다 . 많은 사람들이 뷰 모델 생성이 한 번의 호출로 캡슐화되는 것을 좋아하지 않습니다.

this항상 적절한 지 확인하기 위해 사용할 수있는 또 다른 패턴 은 함수의 변수를 적절한 값과 동일하게 설정 this하고 대신 사용하는 것입니다. 이것은 다음과 같습니다

var ViewModel = function() {
    var self = this;
    this.items = ko.observableArray();
    this.removeItem = function(item) {
         self.items.remove(item);
    }
};

이제 개별 항목의 범위에 있고를 호출 $root.removeItem하면의 값 this은 실제로 해당 수준에서 바인딩되는 데이터 (항목)가됩니다. 이 경우 self를 사용하면 전체 뷰 모델에서 제거 될 수 있습니다.

다른 옵션은 bind최신 브라우저에서 지원하고 지원되지 않는 경우 KO에서 추가하는을 사용하는 것입니다. 이 경우 다음과 같습니다.

var ViewModel = function() {
    this.items = ko.observableArray();
    this.removeItem = function(item) {
         this.items.remove(item);
    }.bind(this);
};

이 주제에 대해 말할 수있는 것이 더 많고 모듈 패턴 및 모듈 패턴 표시와 같이 탐색 할 수있는 많은 패턴이 있지만 기본적으로 함수를 사용하면 오브젝트 작성 방법 및 참조 기능에 대한 유연성과 제어 기능이 향상됩니다. 인스턴스 전용 인 변수


1
좋은 대답입니다. 나는 종종 뷰 모델과 같은 복잡한 객체에 대해 (보이는 모듈 패턴을 사용하여) 함수를 사용합니다. 그러나 간단한 모델의 경우 모든 기능을 한곳에서 처리 할 수 ​​있도록 함수를 사용합니다.
John Papa

1
@JohnPapa-넉 아웃에서 PluralSight 비디오를 보았습니다 (반쯤 끝났을뿐입니다. 정말 잘하고 페니 하락을 도왔습니다. 그것만으로도 한 달 구독 가치가 있습니다.
Kev

@Kev-감사합니다. 당신이 그것에서 가치를 얻고 다행입니다. 일부는 실제로 녹아웃 개념이 아니라 더 많은 JavaScript 패턴으로 해당 모듈에 신경 쓰지 않습니다. 그러나 Knockout으로 더 나아갈 때 이러한 개념이 더 안정적인 코드를 만드는 데 실제로 도움이된다는 것을 알았습니다. 어쨌든, 당신이 그것을 즐기게되어 기쁘다 :)
John Papa

self.items가 아니어야합니다. = ko.observableArray (); 두 번째 예에서? 이걸 사용 했습니까? 맞습니까?
JackNova 2016 년

1
생성자 함수 @JackNova self하고 this있는 동일하므로 어느 동등한 것이다. removeItem 함수에서는 더 이상 하위 항목의 컨텍스트에서 실행될 때 현재 인스턴스가 아니므 self로 더 유용합니다 this.
RP Niemeyer

12

비슷한 방법으로 다른 방법을 사용합니다.

var viewModel = (function () {
  var obj = {};
  obj.myVariable = ko.observable();
  obj.myComputed = ko.computed(function () { return "hello" + obj.myVariable() });

  ko.applyBindings(obj);
  return obj;
})();

몇 가지 이유 :

  1. s 등에서 this사용될 때 혼동 될 수있는을 사용하지 않음ko.computed
  2. 내 뷰 모델 (즉 내가 여러 인스턴스를 만들 필요가 없습니다, 싱글 톤 new viewModel())

실수하지 않으면 모듈 패턴이 나타납니다. 좋은 대답이지만 질문은이 패턴에 관한 것이 아닙니다.
Phil

@paul : 오래된 스레드를 요청하여 죄송합니다. u가 말 My viewModel is a singleton, I don't need to create multiple instances (i.e. new viewModel()) 했지만 I don't need to create multiple instances u plzz가 더 많은 사용법을 제공 할 수 있으므로 귀하의 접근 방식의 이점을 이해할 수 있다고 말하는 것은 분명하지 않습니다 . 감사합니다
Mou

IMO, ViewModel을 선언하는 이유 중 하나는 function여러 번 실행하기 때문입니다. 그러나 내 예에서는 즉시 호출되는 익명 함수이므로 두 번 이상 만들어지지 않습니다. 위의 예제에서 객체 리터럴과 매우 유사하지만 더 많은 격리를 제공합니다.
paulslater19
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.