Simple BEM-style class name generator for Vue.JS 2.*
Live demo: codepen
Block ui-button. Vue Single File Component:
<script>
export default {
name: 'ui-button', // set block name
props: ['size', 'look', 'type', 'icon'],
}
</script>
<template>
<button :class="b({ size, look })" :type="type">
<span :class="b('text', { look })">
<i v-if="icon" :class="b('icon', { icon })"> 👍 </i>
<slot></slot>
</span>
</button>
</template>
Using ui-button block in App.vue:
<script>
import Button from 'components/UI/Button.vue';
export default {
components: {
'ui-button': Button
},
}
</script>
<template>
<div class="example">
<ui-button type="button" class="mix-any-class" size="large" look="primary" icon="emoji"> I am BEM button! </ui-button>
</div>
</template>
Will be compile to:
<div class="example">
<button class="mix-any-class ui-button ui-button--size-large ui-button--look-primary" type="button">
<span class="ui-button__text ui-button__text--look-primary">
<i class="ui-button__icon ui-button__icon--icon-emoji">👍 </i>
I am BEM button!
</span>
</button>
</div>
- from npm:
npm i --save vue-bem-cn
/ yarn add vue-bem-cn
And install with Vue.use()
in your main.js
:
import vueBemCn from 'vue-bem-cn';
Vue.use(vueBemCn, {/* Your config, not required. See below */});
new Vue({...});
- from CDN:
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script src="https://unpkg.com/vue-bem-cn/dist/vue-bem-cn.umd.min.js"></script>
<script>
Vue.use(vueBemCn, {/* Your config, not required. See below */});
new Vue({...});
</script>
For class name generation, enough to call b()
method with v-bind:class
or use :class
in your template.
The Block name will be receive from name
field of component or block
field:
<script>
export default {
name: 'ui-button',
}
</script>
<template>
<div :class="b()"> DIV tag will receive 'ui-button' class name </div>
</template>
More examples in API section
After component initialization (created
lifecycle hook), every component, that has string
in name
or block
fields recive b()
method.
Also, you can call this.b()
method in your component, if you need it.
If you want, you can use block
field instead of name
, but keep in mind, block
prefer then name
:
<script>
export default {
name: 'ui-button',
block: 'bem-button', // prefer then `name: 'ui-button'`
}
</script>
<template>
<div :class="b()"> DIV tag will receive 'bem-button' class name </div>
</template>
No problem. You can set your settings object with Vue.use()
as second argument:
import Vue from 'vue';
import vueBemCn from 'vue-bem-cn';
// default delimiters settings
const bemConfig = {
delimiters: {
ns: '', // namespace
el: '__', // element delimeter
mod: '--', // modifier delimeter
modVal: '-', // value delimeter for modifier
}
}
Vue.use(vueBemCn, bemConfig);
new Vue({...});
Just change methodName
option in config:
import Vue from 'vue';
import vueBemCn from 'vue-bem-cn';
const bemConfig = {
methodName: 'bem',
}
Vue.use(vueBemCn, bemConfig);
new Vue({...});
Check hyphenate
option:
import Vue from 'vue';
import vueBemCn from 'vue-bem-cn';
const bemConfig = {
hyphenate: true,
}
Vue.use(vueBemCn, bemConfig);
new Vue({...});
Generate block name.
<script>
export default {
name: 'ui-button',
}
</script>
<template>
<div :class="b()"> DIV tag will receive 'ui-button' class name </div>
</template>
Generate modifier of block name.
<script>
export default {
name: 'ui-button',
}
</script>
<template>
<div :class="b({ size: 'large' })"> DIV tag will receive 'ui-button ui-button--size-large' class name </div>
</template>
Generate element of block name.
<script>
export default {
name: 'ui-button',
}
</script>
<template>
<div :class="b('text')"> DIV tag will receive 'ui-button__text' </div>
</template>
Generate modifier of element name.
<script>
export default {
name: 'ui-button',
}
</script>
<template>
<div :class="b('text', { look: 'primary' })"> DIV tag will receive 'ui-button__text ui-button__text--look-primary' class name </div>
</template>
Mix class names to block/element.
- with vue-bem-cn in your component:
<script>
export default {
name: 'ui-button',
}
</script>
<template>
<div>
<div :class="b(false, 'block-mixin')"> DIV tag will receive 'ui-button block-mixin' class name </div>
<div :class="b('text', 'element-mixin')"> DIV tag will receive 'ui-button__text element-mixin' class name </div>
</div>
</template>
- with Vue class attribute in parent component:
<script>
import Button from 'components/UI/Button.vue';
export default {
name: 'form',
components: {
'ui-button': Button
},
}
</script>
<template>
<form :class="b()">
<ui-button :class="b('button')"> ui-button root tag will receive 'form__button ui-button' class name </ui-button>
</form>
</template>
{
hyphenate: false,
methodName: 'b',
delimiters: {
ns: '',
el: '__',
mod: '--',
modVal: '-'
}
}
hyphenate: boolean
- hyphenation the resulting class name
// { hyphenate: true }
b({ hasFocus: true }) // block--has-focus
methodName: string
- name of the method for generating the class name
// { methodName: 'bem' }
b('elem') // [Vue warn]: Property or method "b" is not defined...
bem('elem') // block__elem
delimiters: Object<string>
- delimiters for BEM entities
// { delimiters: { ns: 'b-', modVal: '_'} }
b({ mod: 'val' }) // b-block b-block--mod_val