사용자가 여러 번 수행 할 수있는 기능을 웹 페이지에 구축하고 있습니다. 사용자의 액션을 통해 ko.applyBindings ()를 사용하여 객체 / 모델을 생성하고 HTML에 적용합니다.
데이터 바인딩 된 HTML은 jQuery 템플릿을 통해 생성됩니다.
여태까지는 그런대로 잘됐다.
두 번째 개체 / 모델을 만들고 ko.applyBindings ()를 호출하여이 단계를 반복하면 두 가지 문제가 발생합니다.
- 마크 업은 이전 개체 / 모델과 새 개체 / 모델을 표시합니다.
- 객체 / 모델의 속성 중 하나와 관련하여 자바 스크립트 오류가 발생하지만 여전히 마크 업에 렌더링되어 있습니다.
이 문제를 해결하기 위해 첫 번째 패스 후 jQuery의 .empty ()를 호출하여 모든 데이터 바인딩 속성을 포함하는 템플릿 HTML을 제거하여 더 이상 DOM에 있지 않도록합니다. 사용자가 두 번째 패스를 위해 프로세스를 시작하면 데이터 바인딩 된 HTML이 DOM에 다시 추가됩니다.
그러나 내가 말했듯이 HTML이 DOM에 다시 추가되고 새 개체 / 모델에 다시 바인딩되면 첫 번째 개체 / 모델의 데이터가 여전히 포함되며 발생하지 않는 JS 오류가 계속 발생합니다. 첫 번째 패스 동안.
결론은 마크 업이 DOM에서 제거되었지만 Knockout이 이러한 바인딩 된 속성을 유지하고 있다는 것입니다.
그래서 제가 찾고있는 것은 Knockout에서 이러한 바인딩 된 속성을 제거하는 수단입니다. 더 이상 관찰 가능한 모델이 없다고 녹아웃에게 말하고 있습니다. 이를 수행하는 방법이 있습니까?
편집하다
기본 프로세스는 사용자가 파일을 업로드하는 것입니다. 그런 다음 서버는 JSON 개체로 응답하고 데이터 바인딩 된 HTML이 DOM에 추가 된 다음 JSON 개체 모델이 다음을 사용하여이 HTML에 바인딩됩니다.
mn.AccountCreationModel = new AccountViewModel(jsonData.Account);
ko.applyBindings(mn.AccountCreationModel);
사용자가 모델에서 일부를 선택하면 동일한 객체가 서버에 다시 게시되고 데이터 바인딩 된 HTML이 DOM에서 제거되고 다음 JS가 생성됩니다.
mn.AccountCreationModel = null;
사용자가이 작업을 한 번 더 원하면이 모든 단계가 반복됩니다.
jsFiddle 데모를 수행하기에는 코드가 너무 ‘관련’되어 있습니다.
답변
DOM 요소에서 녹아웃의 깨끗한 노드 메서드를 호출하여 메모리 바인딩 된 개체를 처리해 보셨습니까?
var element = $('#elementId')[0];
ko.cleanNode(element);
그런 다음 새 뷰 모델로 해당 요소에만 녹아웃 바인딩을 다시 적용하면 뷰 바인딩이 업데이트됩니다.
답변
작업중인 프로젝트의 ko.unapplyBindings
경우 jQuery 노드와 부울 제거를 허용하는 간단한 함수를 작성했습니다 . ko.cleanNode
메서드가 처리하지 않으므로 먼저 모든 jQuery 이벤트의 바인딩을 해제합니다 . 메모리 누수를 테스트했는데 제대로 작동하는 것 같습니다.
ko.unapplyBindings = function ($node, remove) {
// unbind events
$node.find("*").each(function () {
$(this).unbind();
});
// Remove KO subscriptions and references
if (remove) {
ko.removeNode($node[0]);
} else {
ko.cleanNode($node[0]);
}
};
답변
녹아웃이 제공하는 with binding을 사용해 볼 수 있습니다.
http://knockoutjs.com/documentation/with-binding.html
적용 바인딩을 한 번 사용하고 데이터가 변경 될 때마다 모델을 업데이트하는 것이 아이디어입니다.
최상위 뷰 모델 storeViewModel, cartViewModel로 표시되는 카트 및 해당 카트의 항목 목록 (예 : cartItemsViewModel)이 있다고 가정 해 보겠습니다.
최상위 모델 인 storeViewModel을 전체 페이지에 바인딩합니다. 그런 다음 카트 또는 카트 항목을 담당하는 페이지 부분을 분리 할 수 있습니다.
cartItemsViewModel에 다음 구조가 있다고 가정합니다.
var actualCartItemsModel = { CartItems: [
{ ItemName: "FirstItem", Price: 12 },
{ ItemName: "SecondItem", Price: 10 }
] }
cartItemsViewModel은 처음에 비어있을 수 있습니다.
단계는 다음과 같습니다.
-
html로 바인딩을 정의하십시오. cartItemsViewModel 바인딩을 분리합니다.
<div data-bind="with: cartItemsViewModel"> <div data-bind="foreach: CartItems"> <span data-bind="text: ItemName"></span> <span data-bind="text: Price"></span> </div> </div>
-
상점 모델은 서버에서 가져옵니다 (또는 다른 방법으로 생성됨).
var storeViewModel = ko.mapping.fromJS(modelFromServer)
-
최상위 뷰 모델에서 빈 모델을 정의합니다. 그런 다음 해당 모델의 구조를 실제 데이터로 업데이트 할 수 있습니다.
storeViewModel.cartItemsViewModel = ko.observable(); storeViewModel.cartViewModel = ko.observable();
-
최상위 뷰 모델을 바인딩합니다.
ko.applyBindings(storeViewModel);
-
cartItemsViewModel 개체를 사용할 수 있으면 이전에 정의한 자리 표시 자에 할당합니다.
storeViewModel.cartItemsViewModel(actualCartItemsModel);
장바구니 항목을 지우려면 :
storeViewModel.cartItemsViewModel(null);
Knockout은 html을 처리합니다. 즉, 모델이 비어 있지 않을 때 나타나고 div의 내용 ( “바인딩 포함”이있는 내용)이 사라집니다.
답변
검색 버튼을 클릭 할 때마다 ko.applyBinding을 호출해야하며 필터링 된 데이터는 서버에서 반환되며이 경우에는 ko.cleanNode를 사용하지 않고 다음 작업을 수행합니다.
foreach를 템플릿으로 바꾸면 collections / observableArray의 경우 잘 작동 할 것임을 경험했습니다.
이 시나리오가 유용 할 수 있습니다.
<ul data-bind="template: { name: 'template', foreach: Events }"></ul>
<script id="template" type="text/html">
<li><span data-bind="text: Name"></span></li>
</script>
답변
KO의 내부 함수를 사용하고 JQuery의 포괄적 인 이벤트 핸들러 제거를 처리하는 대신에 with
또는 template
바인딩을 사용하는 것이 훨씬 더 좋습니다 . 이렇게하면 ko는 DOM의 해당 부분을 다시 생성하므로 자동으로 정리됩니다. 이것은 또한 권장되는 방법입니다. https://stackoverflow.com/a/15069509/207661을 참조하십시오 .
답변
바인딩을 전체 시간 동안 유지하고 관련 데이터를 업데이트하는 것이 더 나을 것이라고 생각합니다. 이 문제가 발생하여 .resetAll()
데이터를 보관하고있는 배열에서 메서드를 사용하여 호출하는 것이 가장 효과적인 방법이라는 것을 알았습니다.
기본적으로 ViewModel을 통해 렌더링 할 데이터를 포함하는 전역 변수로 시작할 수 있습니다.
var myLiveData = ko.observableArray();
myLiveData
정상적인 배열을 만들 수 없다는 것을 깨닫는 데 시간이 걸렸습니다 ko.oberservableArray
. 부품이 중요했습니다.
그런 다음 원하는대로 진행할 수 있습니다 myLiveData
. 예를 들어 다음과 같이 $.getJSON
전화를 겁니다.
$.getJSON("http://foo.bar/data.json?callback=?", function(data) {
myLiveData.removeAll();
/* parse the JSON data however you want, get it into myLiveData, as below */
myLiveData.push(data[0].foo);
myLiveData.push(data[4].bar);
});
이 작업을 완료하면 평소처럼 ViewModel을 사용하여 바인딩을 적용 할 수 있습니다.
function MyViewModel() {
var self = this;
self.myData = myLiveData;
};
ko.applyBindings(new MyViewModel());
그런 다음 HTML에서 myData
평소 처럼 사용하십시오 .
이렇게하면 어떤 함수에서든 myLiveData를 사용할 수 있습니다. 예를 들어, 몇 초마다 업데이트하려면 해당 $.getJSON
줄을 함수로 감싸고 호출 setInterval
하면됩니다. myLiveData.removeAll();
줄 을 유지하는 것을 기억하는 한 바인딩을 제거 할 필요가 없습니다 .
데이터가 정말 방대하지 않으면 사용자는 어레이를 재설정 한 다음 최신 데이터를 다시 추가하는 사이의 시간도 알아 차리지 못할 것입니다.
답변
나는 최근에 메모리 누수 문제가 있었고 ko.cleanNode(element);
나를 위해하지 않을 것 ko.removeNode(element);
입니다. Javascript + Knockout.js 메모리 누수-객체가 파괴되고 있는지 확인하는 방법은 무엇입니까?