(Archive) Matreshka.js - MK.Array

  • Tutorial
The article is out of date. The new documentation contains the most relevant information from this post. See Matreshka.Array .



(Let me remind you, the repository is here )

Greetings to all. I ended the previous article on the fact that we might need an array of data. An array in the Matreshka.js project are instances of the class MK.Array. How are they different from regular arrays? Almost nothing. The prototype MK.Arraycontains all the methods that the "traditional" array has, the constructor takes the same arguments as the original one Array, and the instances have several interesting features.

MK.ArrayIs an array on steroids that can:
  • All that can Array
  • Generate events upon modification
  • Use chain method calls where possible
  • Knows what Matryoshka can do: bind elements to properties and generate custom events


Remember the gif from the first article in the series?


When using, MK.Arrayyou need to remember 5 things:

0. The methods that came from Arrayto are MK.Arraynot rewritten again. MK.Arrayuses the built-in capabilities of the array, which means that, firstly, the class code is very compact, and secondly, we avoid bugs of incorrect implementation of methods. It also means that many new methods will not work in Internet Explorer 8 until you connect, say, es5-shim . When an unsupported method is called, an error is generated, the message of which will offer to connect this library.

The list of implemented methods was compiled when studying the prototype Arrayin the latest Chrome build and the MDN documentation.

1. Methods that modify an instance generate two events:"modify"and method name. For example, after the method is executed .push, not only "modify", but also is generated "push". UPD : When adding elements, an event is generated "add", when deleting - "remove".

var mkArray = new MK.Array;
mkArray.on( 'push', function() {
	alert( 'push' );
});
mkArray.on( 'modify', function() {
	alert( 'modify' );
});
mkArray.push( 42 );


List of modifying methods:


2. To avoid generating relevant events, use methods starting with silent. For example, if you want to add an element to an array, but want to avoid generating events, use silentPush(note that the name of the original method is capitalized).

var mkArray = new MK.Array;
mkArray.silentPush( 42 );

The list of modifying methods that are not triggered when triggered:


3. The method .forEachthat Arrayreturns in the prototype of the original returns undefinedto MK.Array:
var mapped = mkArray
	.forEach( function() {
		...
	})
	.forEach( function() {
		...
	})
	.map( function() {
		...
	})
;


4. The original methods Arraythat modify the array and perform a secondary function by returning the length of the array ( .push, .unshift) or the deleted element ( .pop, .shift) ( UPD : Fixed in 0.1) MK.Arrayreturn to themselves. This allows me to build chains of methods (something that I always lacked). Methods whose primary task is to return a value of another type work in the traditional way. This means that it .indexOfreturns a number .toString- a string ...

mkArray
	.push( 1, 2, 3, 4 )
	.unshift( 0 )
	.push( 5 )
	.forEach( function() { ... } )
	.sort()
	.reverse()
;


Compensating for this behavior is very simple, for example, for a method .push:
var array = new Array( 1, 2, 3, 4 ),
	mkArray = new MK.Array( 1, 2, 3, 4 ),
	arrayLength, mkArrayLength;
arrayLength = array.push( 6, 7 );
mkArray.push( 6, 7 );
mkArrayLength = mkArray.length;


5. Methods iterator ( .forEach, .map, .filter, ...) and as a first function of the argument, the third argument is a native copy of the array. The peculiarity of the eighth Donkey does not allow the use of Array.prototype[ method ].applyMatryoshka in the context, therefore, the launch of the methods is as follows:
1. The instance is MK.Arrayconverted to an instance Array.
2. Method Array.prototype[ name ].apply( array, arguments );
3 MK.Arrayis executed . The instance is cleared and updated with the resulting array Array.

mkArray.forEach( function( item, index, array ) {
	console.log( array === mkArray ); // false
});


This is a feature of the implementation of Matryoshka, which can cause bewilderment among experienced programmers. Do not rush to write an angry comment. If it will be interesting to Habr, I will tell the most important thing: how Matryoshka works.

UPD : In version 1.0, this feature will be fixed due to the rejection of support for IE8

Inheritance

Matryoshka-array is inherited in the same way as any class inherited from Matryoshka:
var MyArray = Class({
	'extends': MK.Array,
	constructor: fucntion() {
		this.initMK();
	}
});

The method .initMK, in this case, in addition to initializing the basic pseudo-private properties of Matryoshka, adds the event handlers needed by the array and is required to be run upon inheritance.

The text under the spoiler has lost relevance after the release of Matryoshka 0.1. You can not read it.
Practical application

MK.ArrayIt is itself a ready-to-use class that will add sugar to any application. There is only one “but”: the nested doll array cannot bind data to the elements of the array. Of .bindElementcourse, you can bind an element to an index with the help of , but, obviously, it makes little sense: indexes constantly change during modification. What if you, say, have a list that should be updated when the array changes. In this case, you need to track the necessary methods and change the DOM manually. For example, if the application involves adding and removing elements, you need to listen to events "push"and "splice", the only question is what your application needs.

The gig at the beginning of the post is a demonstration of the work of the (so far) undocumented MK.DOMArray plugin, which, responding to data changes, automatically changes the DOM. The plugin was created as an experiment, to demonstrate the capabilities of Matryoshka and to get closer to the idea that the DOM should update itself when the data changes. But the experiment turned out to be so successful that, perhaps, the plugin code will merge into the code MK.Array. Changes in the DOM are optimal: when objects are added to the array, new elements are added to the page, when deleted, they are deleted, when sorted, they are sorted. This is to ensure that the table is not redrawn again, but reacts sequentially.

Here the nested doll-array (or rather its descendant:) MK.DOMArrayin the example can be called an analog of Collection in Backbone, and its elements are an analog of Model. An example can be seen here: jsbin.com/aZEseWE/16(the gif was recorded from this example). And here: jsbin.com/eQomoJe/9 is a more ascetic option. There is no override of built-in methods in it. I prefer the second method, despite the apparent redundancy.

MK.DOMArrayIt works this way: when adding objects (to the beginning, the end, the middle ... no matter), it checks whether the "itself" has a method .rendererand, if any, inserts the returned element into the page tree and triggers an event on the object "render".
var Example = Class({
	'extends': MK.DOMArray,
	constructor: function() {
		this
			// инициализируем Матрешку
			.initMK()
			// Привязываем элементы
			.bindElement( this, 'table tbody' )
		;
	},
	renderer: function( object ) {
		// Возвращает строку с пустыми тегами. Значения ячеек обновятся автоматически, при привязке
		return '';
	}
});

The task of the added object is to catch the event "render"and bind the elements inside the element bound to "__this__".
var ExampleObject = Class({
	'extends': MK.Object,
	constructor: function( o ) {
		this
			.initMK()
			.jset( o )
			.on( 'render', function( evt ) {
				this
					// аргумент обработчика события 'render' — объект, содержащий отрендереный элемент
					// почему MK.DOMArray самостоятельно не привязывает HTML элемент к элементу коллекции? 
					// потому что объект (элемент коллекции) сам должен решать, что делать,
					// так как один объект может содержаться в разных коллекциях
					.bindElement( this, evt.el )
					// привязываем необходимые элементы
					.bindElement({
						a: this.$( '.a' ),
						b: this.$( '.b' ),
						c: this.$( '.c' )
					}, MK.htmlp )
				;
			})
		;
	}
});



Idea
This is where the plugin works, working exclusively with tables. Perhaps it will work like this:
var table = MK.Table({
	table: '.my-table'
	rows: [{
		title: 'A',
		key: 'a'
	}, {
		title: 'B',
		key: 'b'
	}]
});
table.push({
	a: 'Fuck',
	b: 'Yeah'
});



At the end of the cycle


Matryoshka is a compact, easy-to-learn framework that will continue to develop. Regardless of the level of preparation of the programmer, Matryoshka is easy to learn and, most likely, is a great start when transitioning to structured code by beginners. Compactness and extensibility gives a bunch of ideas for plugins and add-ons. Over time, the dependency on jQuery will be removed ( UPD : Already removed), support for Internet Explorer 8, improved performance and much more ...

Thank you for your attention, all the best.

PS There is now a roadmap in the README repository .

Also popular now: