Last active
March 23, 2020 17:00
-
-
Save AndersSchmidtHansen/024cf71fec08835481d2 to your computer and use it in GitHub Desktop.
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/
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
/* | |
|-------------------------------------------------------------------------- | |
| 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
@AndersSchmidtHansen this is great; haven't tested it out, but useful just to read thru the logic.