Vue BEM Directive - A vue.js directive for automatic BEM class generation when creating components. A very rough example can be found here: https://jsfiddle.net/at1h1z1z/6/
/* | |
|-------------------------------------------------------------------------- | |
| Vue BEM Directive | |
|-------------------------------------------------------------------------- | |
| | |
| If you find yourself writing a lot of long, tedious CSS class names in | |
| order to be consistent with the BEM naming convention, then try this | |
| directive. It automagically does all the heavy lifting based on | |
| the component's name found in $options.name. | |
| | |
| It can produce BEM classes similar to those Harry Roberts advocate in | |
| this article: http://bit.ly/1R3nlNG | |
| | |
| With that said, if you write this: | |
| <div v-bem:,premium v-bem:o-media.block> | |
| <img src="" alt="" v-bem:photo v-bem:o-media,img.block v-bem:c-avatar.block /> | |
| <p v-bem:bio v-bem:o-media,body,large.block>...</p> | |
| </div> | |
| | |
| It produces: | |
| <div class="o-media c-user c-user--premium"> | |
| <img src="" alt="" class="o-media__img c-user__photo c-avatar"> | |
| <p class="o-media__body c-user__bio">...</p> | |
| </div> | |
| | |
| A different example with a more tedious component name like | |
| 'congratulations-card': | |
| <div v-bem> | |
| <section v-bem:content> | |
| <div v-bem:title>{{ title }}</div> | |
| <p v-bem:message>{{ message }}</p> | |
| </section> | |
| <footer v-bem:footer> | |
| <slot name="footer"></slot> | |
| </footer> | |
| </div> | |
| | |
| Produces: | |
| <div class="c-congratulations-card"> | |
| <section class="c-congratulations-card__content"> | |
| <div class="c-congratulations-card__title"></div> | |
| <p class="c-congratulations-card__message"></p> | |
| </section> | |
| <footer class="c-congratulations-card__footer"></footer> | |
| </div> | |
| | |
*/ | |
Vue.directive('bem', { | |
bind: function() { | |
var _namespace = ' ' + ( (this.modifiers.block) ? '' : 'c-' ) | |
var _block = _namespace + this.vm.$options.name | |
var _element = '' | |
var _modifier = '' | |
var _elementPrefix = '__' | |
var _modifierPrefix = '--' | |
if (this.arg) { | |
var _bem = this.arg.split(',') | |
var _element = (_bem[0]) ? _elementPrefix + _bem[0] : '' | |
var _modifier = (_bem[1]) ? _modifierPrefix + _bem[1] : '' | |
if ( this.modifiers.block ) { | |
_block = _namespace + _bem[0] | |
_element = _elementPrefix + _bem[1] | |
_modifier = _modifierPrefix + _bem[2] | |
if ( _bem[1] ) { | |
this.el.className += _block + _element | |
} else { | |
this.el.className += _block | |
} | |
if ( _bem[2] ) { | |
this.el.className += _block + _element + _modifier | |
} | |
} else { | |
if (_element) { | |
this.el.className += _block + _element | |
} else { | |
this.el.className += _block | |
} | |
if (_modifier) { | |
this.el.className += _block + _element + _modifier | |
} | |
} | |
} else { this.el.className += _block } | |
} | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
@AndersSchmidtHansen this is great; haven't tested it out, but useful just to read thru the logic.