Dataview.js

Kilka moich ostatnich tygodni to praca nad nową biblioteką open-source – Dataview.js. Pomaga ona zachować porządek w naszych aplikacjach, które silnie korzystają z danych przesyłanych via JSON. Wszystko dzięki temu, że możemy zdefiniować metody, które jako jedyne w aplikacji mogą zmieniać wartości w modelu danych. Jak to działa?

Przyjmijmy, że mamy taki obiekt z danymi:

{
	name: "John Doe",
	arr: [1, 2, 3],
	obj: { 
		foo: "bar" 
	}
}

Modyfikują go w naszym systemie różne zdarzenia i moduły, na przykład takie:

$("#foo").click(function() {
	data.name = "Jan Kowalski;
});
$("#bar").pick(function(name) {
	data.name = name;
});

Można zaradzić takiemu swobodnemu dostępowi do danych przy użyciu Dataview.js.

Tworzymy najpierw obiekt Dataview:

var data = dataview({
	name: "John Doe",
	arr: [1, 2, 3],
	obj: { 
		foo: "bar" 
	}
});

Następnie musimy mieć odpowiedni widok, który będzie o tyle uprzywilejowany, że będzie zawierał metody, które jako jedyne będą mogły zmieniać cokolwiek w data:

var view = {
	updateName: function () {
		// [...]
		/this.update("Leonardo da Vinci"); // zaktualizuje imię i nazwisko
	},
	removeFromArr: function () {
		// [...]
		this.remove(1); // usunie element z pierwszego indeksu tablicy
	},
	addToObj: function () {
		// [...]
		this.add("key", "value"); // doda element "key" o wartości "value" do obiektu
	}
};

Musimy teraz spoić całość tak, by metody widoku rzeczywiście mogły korzystać z this.update/add/remove. Wszystko odbywa się poprzez specjalne połączenie widoku z danymi i funkcje connect oraz on. Pierwsza odpowiada za połączenie z widokiem, w drugiej definiujemy, które metody mają modyfikować wybrane przez nas własności:

data.connect(view).on({
	name: "updateName", // view.updateName zmodyfikuje 'name'
	arr: "removeFromArr", // view.removeFromArr zmodyfikuje 'arr'
	obj: "addToObj" // view.addToObj zmodyfikuje 'obj'
});

Można też to zrobić w ten sposób, Dataview jest bardzo elastyczny:

data.connect(view).on("name", "updateName").on("arr", "removeFromArr").on("obj", "addToObj");

Jeśli już połączyliśmy metody z odpowiednimi własnościami obiektu danych, pora używać metod widoku gdziekolwiek. I tak analogicznie może to wyglądać w ten sposób:

$("#foo").click(function() {
	view.updateName();
	view.removeFromArr();
	view.addToObj();
});
$("#bar").pick(function(name) {
	view.updateName(name);
});

Nasze dane wyglądać będą teraz tak:

{
	name: "Leonardo da Vinci",
	arr: [1, 3],
	obj: {
		foo: "bar",
		key: "value"
	}
}

Oczywiście możemy używać callbacków, by śledzić zmiany danych w obrębie aplikacji:

data.onRemove({
	arr: function (index) {
		console.log("Usunięto element z tablicy o indeksie:", index)
	}
});
view.removeFromArr(); 
// Usunięto element z tablicy o indeksie: 1

Do dyspozycji mamy też inne ich rodzaje: onAdd i onUpdate.

Największą jednak siłą Dataview jest to, że możemy łatwo sprawić, że zdefiniowane wyżej własności, jak wspomniałem, mogą być modyfikowane tylko i wyłącznie przez wybrane metody. Jak to zrobić? Z pomocą przychodzi funkcja lock():

data.connect(view).on({
	name: "updateName",
	arr: "removeFromArr",
	obj: "addToObj"
}).lock();

Pamiętaj, by zawrzeć ją zawsze na końcu “połączenia”.

W ten sposób nie możemy już dodawać nowych widoków do danych:

data.connect(view).on({
	name: "somethingElse"
});
// "Couldn't connect new methods. Locked property: name"

Ani też zmienić danych poza metodami, które zdefiniowaliśmy:

data.update("arr", 1, "new value");

Wartość tablicy arr na pozycji 1 nie zmieni się na new value.

O Dataview.js możecie poczytać na stronie biblioteki – Dataviewjs.com. Jest ona napisana zgodnie z duchem TDD, więc na GitHubie znajdziecie również testy jednostkowe.

Komentarze

1

[…] więc jest to jak najbardziej open-source w pełnym tego słowa znaczeniu. Po więcej szczegółów odsyłam na mojego bloga oraz oficjalną stronę projektu – […]

2

Bardzo fajny koncept :)

irek
3

Wygląda całkiem dobrze. Dwa lub trzy pełne przykłady zrobiły by swoje.

frankie.the.coin
4

Zrobię jakieś dema w następnych dniach.

Dodaj komentarz

Dozwolone tagi: <blockquote>, <code>, <strong>