bem / bem-xjst

bem-xjst (eXtensible JavaScript Templates): declarative template engine for the browser and server
https://bem.github.io/bem-xjst
Other
115 stars 47 forks source link

Bring "Notable changes" up to date #122

Closed qfox closed 8 years ago

qfox commented 8 years ago

Guess we should add something like this:


elemMatch() and this.elem changes

There is no sense in elemMatch() since you can't test this.elem now. (More info?)

apply() behaves slightly different

Since a notable performance jump apply() can't call custom modes in other blocks.

block('b2').mode('custom')('in b2'); // won't be called
block('b1').mode('custom')('in b1'); // will be called instead
block('b1').content()(function() {
  return apply('custom', { block: 'b2' });
});

Also there is no more polymorphism in apply() and you should always explicitly pass a first argument, e.g. 'default'.

applyNext() don't use guard-flags to prevent executing template in nested

Every template now applies to the each block of the same name in nested tree when called in applyNext().

E.g. for template:

block('b1').content()(function() {
  return {
    elem: 'inner',
    content: applyNext()
  };
});

And json:

{ block: 'b1', content: { block: 'b1' } }

Will result in:

<div class="b1"><div class="b1__inner"><div class="b1"><div class="b1__inner"></div></div></div></div>

Instead of:

<div class="b1"><div class="b1__inner"><div class="b1"></div></div></div>

Static objects shortcuts in mix, content, etc.

Because new templates were not compiled variables will share references to the same objects and that can look like a memory leak.

Just switch to function generator if you're not sure how somebody will redefine it.

For bemjson:

([
    { block: 'b1', mods: { a: true } },
    { block: 'b1' },
    { block: 'b1' }
]);

And templates:

// Don't do that!
block('b1')(
  mix()([]), // Use function generator instead: `function() { return []; }`.
  mix()(function () {
    var res = applyNext();
    res.push({block: 'b2'});
    return res;
  }),

  attrs()([]), // Use function generator instead: `function() { return {}; }`.
  mod('a', true).attrs()(function () {
    var res = applyNext();
    res.withMod = 'a';
    return res;
  })
);

You'll see unnecessary attribute withMod and more duplicates in mixes for each next block:

<div class="b1 b1_a b2" withMod="a"></div>
<div class="b1 b2 b2" withMod="a"></div>
<div class="b1 b2 b2 b2" withMod="a"></div>

once() helper to apply template just once

Literally, it guards template block from being applied several times.

NB: It behaves like an old applyNext().

Code like:

block('b1').def()(function() {
  return applyNext();
});

now should be rewritten to:

block('b1').match(function() { return !this._guard; }).def()(function() {
  return applyNext({_guard: true});
});

Or with once():

block('b1').once().def()(function() {
  return applyNext();
});

wrap() helper for wrapping

Literally, it sets guard-flag into this.ctx, and applying context. Sugar for def() and applyCtx().

Code like:

block('b1').def()(function() {
  return applyCtx({ block: 'wrapper', content: this.ctx });
});

should now be rewritten to:

block('b1').match(function() { return !this.ctx._guard; }).def()(function() {
    this.ctx._guard = true;
    return applyCtx({ block: 'wrapper', content: this.ctx });
});

Or with wrap() helper:

block('b1').wrap()(function() {
    return { block: 'wrapper', content: this.ctx };
});

replace() helper for replacing

block('b1').def()(function() {
  return applyCtx({ block: 'replacer' });
});
block('b1').replace()(function() {
  return { block: 'replacer' };
});

/cc @tadatuta @veged

veged commented 8 years ago

:+1:

qfox commented 8 years ago

@veged Updated, thanks!

https://github.com/bem/bem-xjst/wiki/Notable-changes-between-bem-xjst@1.x-and-bem-xjst@2.x