Created
April 4, 2018 09:26
-
-
Save awinogradov/7a5dff0594f22a13fda2bb52f32798f9 to your computer and use it in GitHub Desktop.
BEM Compose
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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