Skip to content

Instantly share code, notes, and snippets.

@awinogradov
Created April 4, 2018 09:26
Show Gist options
  • Save awinogradov/7a5dff0594f22a13fda2bb52f32798f9 to your computer and use it in GitHub Desktop.
Save awinogradov/7a5dff0594f22a13fda2bb52f32798f9 to your computer and use it in GitHub Desktop.
BEM Compose
class Bem {
}
// src/common/Block/Block.js
class Block extends Bem {
constructor() {
super();
this.a = 1;
}
tag() {
return 'a';
}
}
// src/common/Block/_mod/Block_mod_val1.js
class BlockModVal1Common extends Bem {
constructor() {
super();
console.log(this.a); // 1
}
tag() {
return 'b';
}
}
BlockModVal1Common.predicate = props => {
console.log('BlockModVal1Common predicate props', props);
return props.mod === 'val1';
};
// src/desktop/Block/_mod/Block_mod_val1.js
class BlockModVal1Desktop extends BlockModVal1Common {
constructor() {
super();
this.a += 1;
console.log(this.a); // 2
}
tag() {
return 'bb';
}
}
// src/common/Block/_mod/Block_mod_val2.js
class BlockModVal2Common extends Bem {
constructor() {
super();
this.a += 1;
console.log(this.a); // 2 or 3
}
tag() {
return 'c' + super.tag(); // ca or cbb
}
}
BlockModVal2Common.predicate = props => props.mod === 'val2';
// Мутабельный метод. Меняет существующую цепочку прототипов. Было бы круто починить. Написал про это Филатову.
function inherits(Inherited, Super) {
Inherited.super_ = Super;
Object.setPrototypeOf(Inherited.prototype, Super.prototype);
return Object.setPrototypeOf(Inherited, Super);
}
const compose = (...mixins) => {
const Base = mixins.splice(0, 1)[0];
// hack to save predicates from static fields
// it's doesn't work after inherit, because prototype changes
const dict = mixins.reduce((dict, Mixin) => {
dict[Mixin.prototype.constructor.name] = Mixin.predicate;
return dict;
}, {});
return props => mixins
.filter(Mixin => dict[Mixin.prototype.constructor.name](props))
.reduce((Middle, Mixin) => inherits(Mixin, Middle), Base);
}
const hoc = compose(Block, BlockModVal1Desktop, BlockModVal2Common);
const props1 = { mod: 'val1' };
const applied1 = hoc(props1);
const res1 = new applied1(props1);
console.log('Composed: A, BB', res1.tag(), res1.a); // bb, 2
const props2 = { mod: 'val2' };
const applied2 = hoc(props2);
const res2 = new applied2(props2);
console.log('Composed: A, C', res2.tag(), res2.a); // ca, 2
// LET'S TRY AGAIN
const applied3 = hoc(props1);
const res3 = new applied3(props1);
console.log('Composed: A, BB', res3.tag(), res1.a); // bb, 2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment