Вычисляемые объекты. Функция ko.computed

Последнее обновление: 17.05.2016

Иногда требуется осуществить привязку не к одному объекту из ViewModel, а к какому-то объекту, который вычисляется динамически. Например, пусть у нас есть модель, которая представляет человека:

<p><span data-bind="text: name"></span> <span data-bind="text: surname"></span></p>
<script>
var personViewModel = {
	name: ko.observable("Том"),
	surname: ko.observable("Джонс")
};
ko.applyBindings(personViewModel);
</script>

Если нам надо использовать данные о человеке - имя и фамилию вместе, то есть полное имя, как единое целое, то нам надо создать функцию, которая будет соединить имя и фамилию. Для этого надо создать вычисляемый наблюдаемый объект с помощью метода ko.computed():

<p>Полное имя: <span data-bind="text: fullName"></span></p>
<script>

function PersonViewModel() {
	var self = this;
    self.firstName = ko.observable("Том");
    self.lastName = ko.observable("Джонс");
	self.fullName = ko.computed(function() {
        return self.firstName() + " " + self.lastName();
    });
};

var person = new PersonViewModel();
ko.applyBindings(person);
</script>

Прежде всего вместо простого объекта JavaSctipt используется функция конструктора, которая создает объект ViewModel.

Во-первых, в данном случае применяется распространенный прием, который позволяет не отслеживать ссылку на объект, представленную ключевым словом this. Если конструктор объекта ViewModel копирует ссылку на this в другую переменную (обычно называется self), то затем эту переменную можно использовать для доступа к ViewModel внутри конструктора:

Во-вторых, после того, как ViewModel оказывается привязана к представлению, Knockout выполняет вычисляемую функцию в методе ko.computed() и возвращает результат. Если в функции применяются наблюдаемые объекты observable (как в данном случае), то функция подписывается на изменения в этих наблюдаемых объектах. И при наличии изменений Knockout синхронно обновляет значение вычисляемой функции. Рассмотрим этот момент на примере:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Привязка в KnockoutJS</title>
<script type="text/javascript" src="https://ajax.aspnetcdn.com/ajax/knockout/knockout-3.4.0.js"></script>
</head>
<body>
<p>Полное имя: <span data-bind="text: fullName"></span></p>
<button id="updateBtn">Update</button>
<script>
function PersonViewModel() {
	var self = this;
    self.firstName = ko.observable("Том");
    self.lastName = ko.observable("Джонс");
	self.fullName = ko.computed(function() {
        return self.firstName() + " " + self.lastName();
    });
};
var person = new PersonViewModel();
ko.applyBindings(person);

var updateBtn = document.getElementById("updateBtn");
updateBtn.addEventListener("click", function (e) {
	
    person.firstName("Боб");
});
</script>
</body>
</html>

Здесь добавлена кнопка, при нажатии на которую будет изменяться значение поля firstName. Это в свою очередь заставит обновить возвращаемое значение функцию fullName, и соответственно обновится и тот текст, который выводится на html-страницу:

Computed observables in Knockout

Pure computed functions

Если вычисляемые функции просто вычисляют и возвращают некоторое значение, которое основано на наблюдаемых значениях observable, то в этом случае лучше определить подобные функции с помощью метода ko.pureComputed(), а не через метод ko.computed(). Например:

<p>Полное имя: <span data-bind="text: fullName"></span></p>
<script>
function PersonViewModel() {
	var self = this;
    self.firstName = ko.observable("Том");
    self.lastName = ko.observable("Джонс");
	self.fullName = ko.pureComputed(function() {
        return self.firstName() + " " + self.lastName();
    });
};
var person = new PersonViewModel();
ko.applyBindings(person);
</script>

Фактически мы имеем тот же самый результат, что и при применении обычных вычисляемых функций, создаваемых с помощью ko.computed(). В чем же тогда отличие?

Подобные функции, создаваемые методом ko.pureComputed(), увеличивают производительность, предупреждают возможные утечки памяти. Подобная оптимизация возможна благодаря тому, что эти функции не отслеживают изменения в свойствах, если подписчики на эти изменения отсутствуют..

pureComputed-функции автоматически переключаются между двумя состояниями в зависимости от того, имеют они подписчиков на изменение значений или нет:

  • Состояние sleeping. Если функция не имеет подписчиков, то для нее удаляется все подписки на отслеживание ее зависимостей, то есть ссылки на всех используемых наблюдаемых объектов. Фактически функция "засыпает". Но если во время этого состояния возникнет попытка чтения значения pureComputed-функции, то ее значение автоматически обновляется, если значения зависимостей были изменены.

  • Состояние listening. Если функция имеет подписчиков, она находится в состоянии listening. В этот состоянии функция отслеживает изменения зависимостей и при наличии изменений автоматически обновляет возвращаемое значение. В общем ведет себя подобно функции,создаваемой с помощью ko.computed()

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850