// this - // "x" this.bindNode('x', 'input.my-node'); // , alert this.on('change:x', function() { alert(this.x); }); // , // "x" this.x = 'Wow!';
var object = {}; // "x" MK.bindNode(object, 'x', 'input.my-node'); // , alert MK.on(object, 'change:x', function() { alert(object.x); }); // , // "x" object.x = 'Wow!';
let object = {}; // "x” '.my-node' MK.bindNode(object, 'x', '.my-node'); // "y” x z MK.linkProps(object, 'y', 'x z', (x, z) => x + z); //”z” - , , MK.mediate(object, 'z', Number); // ...
// this.bindNode('x', '.my-node'); // MK.bindNode(object, 'x', '.my-node');
class MyArray extends MK.Array { itemRenderer() { return '<li>'; } constructor() { super().bindNode('sandbox', '.some-node'); } } let arr = new MyArr(); arr.push(someData);
MatreshkaMagic
or a shorter version of magic
, which contains all the static methods of the Matreshka
class. magic.bindNode(object, 'x', '.my-node'); magic.linkProps(object, 'y', 'x z', (x, z) => x + z); // . .
this.a = {b: {c: {d: 41}}} this.bindNode('abcd', '.my-node');
this.ab = {c: {d: 42}};
this.linkProps('a', 'bc d', (b, c, d) => b + c + d); this.b = 1; this.c = 2; this.d = 3; alert(this.a); // 6
this.linkProps('a', [ externalObject, 'b', externalObject2, 'c', this, 'd' ]); externalObject.b = 1; externalObject2.c = 2; this.d = 3; alert(this.a); // 6
linkProps
supports specifying the path to the property: this.linkProps('a', 'bcd e.f', (d, f) => d + f); this.b = {c: {d: 40}}; this.e = {f: 2}; alert(this.a); // 42
this.bc = {d: 1};
let targetObject = {}, o1 = {b: {c: {d: 40}}}, o2 = {e: {f: 2}}; MK.linkProps(targetObject, 'a', [ o1, 'bcd', o2, 'ef' ], (d, f) => d + f); alert(targetObject.a); // 42
this
), but also on an object of arbitrary nesting. But the syntax made you want something better. I will give a small example. Say, an instance of the Matryoshka has or should appear a certain property, which, in turn, is also an instance of the Matryoshka. this.a = new Matreshka();
this.on('a@someevent', handler); this.a.trigger('someevent');
this.on('@someevent', handler); this.push(new Matreshka()); this[0].trigger('someevent');
"a"
contains a collection: this.a = new MK.Array(); this.a.push(new Matreshka());
"a"
catch the event "@someevent"
-> in the array element, catch the event "someevent"
”. this.on('a@@someevent', handler); this.a[0].trigger('someevent');
""
then the syntax remains the same: this.on('a@someevent', handler);
this.on('@someevent', handler);
this.on('*@someevent', handler);
this.on('a@@someevent', handler);
this.on('a.*@someevent', handler);
// ( ) this.x = {a: 41}; // this.setClassFor('x', MyClass); // , MyClass console.log(this.x instanceof MyClass); // true // "a” console.log(this.xa); // 41 // // "x” var x = this.x; // this.x = {a: 42}; // , console.log(xa); // 42 // , console.log(x === this.x); // true // Wow! , !
setClassFor
also running in nested objects, you can do interesting things. For example, save the presentation of multi-level data in the local storage. localStorage.x = JSON.stringify(this.x);
this.x = JSON.parse(localStorage.x);
// app.js class App extends MK { constructor(appData) { this.appData = appData; this.setClassFor('appData', AppData); } } // app-data.js class AppData extends MK.Object { constructor(data) { super(data) .setClassFor({ friends: Friends, settins: Settings }); } } // friend.js class Friend extends MK.Object { constructor(data) { super(data); } } // friends.js class Friends extends MK.Array { Model = Friend; constructor(data) { super(...data); } } // settings.js class Settings extends MK.Object { constructor(data) { super(data) .setClassFor('credentials', Credentials); } } // credentials.js class Credentials extends MK.Object { constructor(data) { super(data); } } // app-init.js var app = new App({ settings: { name: 'Vasiliy Vasiliev', credentials: { email: 'vasia.vasia@gmail.com' } }, friends: [{ name: 'Yulia Zuyeva', id: 1 }, { name: 'Konstantin Konstantinopolsky', id: 2 }, { name: 'nagibator3000', id: 3 }] }); // JSON.stringify(app.appData); // appData // , app.appData = { settings: { name: 'Petr Petrov', credentials: { email: 'petr.petrov@gmail.com' } }, friends: [{ name: 'Yulechka Zuyeva', id: 1 }, { name: 'Konstantin Konstantinopolsky', id: 2 }] };
{{KEY}}
and creates bindings where these constructs are found. <a href="http://{{website.domain}}/{{category}}/{{page}}">Look at the {{info.title}}</a>
this.parseBindings(); this.website.domain = 'example.com'; this.category = 'foo'; this.page = 42; this.info.title = 'cool stuff';
useBindingsParser: true
). class MyArray extends MK.Array { itemRenderer = '<span>Hello, {{name}}</span>'; ... }
setClassFor
can see that the methods are run immediately after super()
. This possibility became real thanks to a very simple change: all three constructors ( Matreshka
, Matreshka.Array
, Matreshka.Object
) return this
instead of undefined
. class MyObject extends MK.Object { constructor(data) { super(data) .bindNode('x', '.my-node'); } } // MyObject a b, // myObject = new MyObject({a: 1, b: 2}); class MyCollection extends MK.Array { constructor(data) { super(...data) .bindNode('x', '.my-node'); } } // , 5 myCollection = new MyCollection([1,2,3,4,5]);
this.on('eventname1', handler1); this.on('eventname2', handler2);
this.on({ 'eventname1': handler1, 'eventname2': handler2 });
this.on({ 'eventname1': evt => this.x = 42, 'eventname2': evt => doSomethingElse() });
this.on({ 'eventname1': function(evt) { this.x = 42 }, 'eventname2': function(evt) { doSomethingElse(); } });
itemRenderer
is a virtual property of the collection ( Matreshka.Array
), which tells how to draw the elements of the collection. // , ES7 class MyCollection extends MK.Array { itemRenderer = "<div>Hi there!</div>"; constructor() { super() .bindNode('sandbox', '.array-sandbox') .push({a: 1}, {a: 2}); } }
itemRenderer
, the collection is automatically redrawn. // - span this.itemRenderer = '<span>I'm a span</spam>'; // - div this.itemRenderer = '<div>I'm a div</div>';
fetch('templates/my-template.html') .then(resp => resp.text()) .then(text => this.itemRenderer = text);
this.bindNode('x', '.my-node', binder); this.x = 42; //
this.bindNode('x', '.my-progress'); this.x = 42; // 42
textContent
or innerText
property. this.bindNode('x', '.my-node', MK.binders.innerText()); this.x = 'Some <i>Text</i>'; // " ”,
style
element. this.bindNode('x', '.my-node', MK.binders.style('color')); this.x = 'red'; //
input[type=”file”]
, but also read the file in the format you need: this.bindNode('x', '.my-file', MK.binders.file('dataURL')); // , this.on('change:x', function() { console.log(this.x.readerResult); // "data:image/png;base64,iVBO..." });
<div class="my-div">Some data</div>
// , this.x . this.bindNode('x', '.my-div', MK.binders.innerHTML()); alert(this.x); //"Some data"
Matreshka.Array
has a new virtual method onItemRender
. It is called when one of the elements of the collection has been drawn. The method makes the code more flat, allowing you to avoid listening to the "render"
event."render"
event has always been a standard pattern that allows you to add the necessary bindings when rendering. class MyCollection extends MK.Array { Model: MyModel; itemRenderer = '<li>'; constructor() { super() .bindNode('sandbox', '.array-sandbox') .on('*@render', evt => { evt.self.bindNode(...); }); } }
class MyCollection extends MK.Array { Model: MyModel; itemRenderer = '<li>'; constructor() { super() .bindNode('sandbox', '.array-sandbox'); } onItemRender(item, evt) { item.bindNode(...); } }
onRender
. class MyModel extends MK.Object { constructor() { super() .on('render', evt => { this.bindNode(...); }); } }
class MyModel extends MK.Object { constructor() { super() } onRender() { this.bindNode(...); } }
bound
returns the first bound element, $bound
- all elements as a jQuery or Balalaika collection. this.bindNode('x', '.my-node'); var boundNode = this.bound('x'); var allBoundNodes = this.$bound('x');
nodes
and $nodes
properties allow you to do the same, but practically for free, in terms of performance, since these properties are ordinary objects. this.bindNode('x', '.my-node'); var boundNode = this.nodes.x; var allBoundNodes = this.$nodes.x;
MK.Object
and MK.Array
.MK.Array
.MK.Array
.Array
is twice as fast as Array.prototype.slice does.for..in
loop instead of the each
function) and larger changes, it turned out to achieve excellent results. For example, in a benchmark with small collections (10 items), the Matryoshka fell behind React by 10-20 percent in Chrome and Firefox (although it overtook in benchmarks with a large number of collection items). Now in the same test, Matryoshka is 50% faster than React in Chrome, and 3 times faster in Firefox.this
is an instance of Matryoshka. this.bindNode('key', '.node');
var mk = new Matreshka(); mk.bindNode('key', '.node');
var object = {}; MK.bindNode(object, 'key', '.node');
var object = MK.to({}); MK.bindNode(object, 'key', '.node');
bindNode
method bindNode
more informative: now in the text, besides the key, the selector is indicated (if a selector is transmitted).f(x)
instead of f( x )
) are removed from the code and from the examples on the site.Greetings
Again, the same question that I previously had, but the answer I did not find it beautiful.
For example, the correspondence as in VK:
User = { id: 5, name: 'Fedor', online: true }
We place this user in different rooms: room1, room2, room3.
If User.online = false, then in all 3 rooms, for example, the color should change.
So 3 collections that contain one object and at the same time this object is displayed in 3 places.
Note: it is not necessary that these collections will be of the same type (not only rooms), they can be of different types and representations.
Is it possible to bind one object to multiple views?
Yes, collections containing an object can be different.bindRenderedAsSandbox: false
, , (, , ). .render
, , , .
: jsbin.com/cidise/12/edit .user
( ul), -.tableUsers[0].name = 'xxx'
, , . , .
Shl. IE 8, , ,.instanceOf
object.instanceOf( MyClass ); // object instanceof MyClass
Source: https://habr.com/ru/post/267483/
All Articles