bem / bem-react Goto Github PK
View Code? Open in Web Editor NEWA set of tools for developing user interfaces using the BEM methodology in React
Home Page: http://bem.github.io/bem-react
License: Other
A set of tools for developing user interfaces using the BEM methodology in React
Home Page: http://bem.github.io/bem-react
License: Other
Or, at least, make proper extend of style
in attrs
.
Reproducing steps:
git clone https://github.com/bem/bem-react-core
cd bem-react-core
npm i
npm test
Result:
all tests fail with:
● Test suite failed to run
Cannot find module 'babel-template'
After install dependencies with yarn
it works correctly(thats why Travis CI works – it uses yarn).
We can use context to get the parent block for element. So instead of writing
return (
<Bem block={this} elem='Wrapper'>
<Bem block={this} elem='Content'>
<Bem block={this} elem='Title'>title</Bem>
<Bem block={this} elem='Body' />
</Bem>
</Bem>
);
we can just write:
return (
<Bem elem='Wrapper'>
<Bem elem='Content'>
<Bem elem='Title'>title</Bem>
<Bem elem='Body' />
</Bem>
</Bem>
);
It looks much more elegant and cleaner.
this.__base.apply(this, arguments)
-> this.__base(...arguments)
<MyBlock mix={{ block : 'YetAnotherBlock' }}/>
Допустим у меня есть блок button
.
Внутри я использую модификатор, который должен быть подключен всегда вместе с button
. Например button_disable_yes
.
Если я напишу в файле button.js
import Button from "b:button m:disable=yes";
То файл button_disable_yes.js
подключится раньше button.js
. Получится что button
переопределяет button_disable_yes
, а не наоборот.
*.spec.js
with BEM imports.We can use presets instead of custom params for bem-naming and b_. List: canonical, harry-roberts, modern(current by default).
...
bemLoader: {
naming: 'harry-roberts',
levels: [...]
}
...
It shouldn't generate className
Because of dev dependencies.
@awinogradov did you see these msgs?
/Users/yeti-or/Projects/Y/BEM/bem-react-core/__tests__/propTypes.spec.js
6:20 error Using another component's propTypes is forbidden react/forbid-foreign-prop-types
14:27 error Using another component's propTypes is forbidden react/forbid-foreign-prop-types
21:20 error Using another component's propTypes is forbidden react/forbid-foreign-prop-types
/Users/yeti-or/Projects/Y/BEM/bem-react-core/lib/decls.js
22:29 error Using another component's propTypes is forbidden react/forbid-foreign-prop-types
22:71 error Using another component's propTypes is forbidden react/forbid-foreign-prop-types
48:44 error Using another component's propTypes is forbidden react/forbid-foreign-prop-types
65:34 error Using another component's propTypes is forbidden react/forbid-foreign-prop-types
65:85 error Using another component's propTypes is forbidden react/forbid-foreign-prop-types
declMod({ modName : ‘modVal’ }, …)
— for declaration of _modName_modVal with automatically adding of props.modName
to mods
declMod({ modName : ‘*’ }, …)
— for common declaration for any value of modName
(and auto adding to mods
)declMod({ modName : ({ modName }) => ... })
— for declaration additional custom matching for modName
(and auto adding to mods
)declMod(({ modName }) => …, { mods() { … } })
— for completely manual control of modifiersPlease release new version of bem-react-core via npm.
If we have file system structure:
node_modules/my-lib/blocks/
OtherBlock/OtherBlock.js
blocks/
OtherBlock/OtherBlock.js
MyBlock/
_myMod/MyBlock_myMod.js
MyBlock.js
pages/
index/index.js
and files content:
// node_modules/my-lib/blocks/OtherBlock/OtherBlock.js
import { Bem } from 'bem-react-core';
export default Bem.decl(/* ... */);
// blocks/OtherBlock/OtherBlock.js
import { Bem } from 'bem-react-core';
export default Bem.decl(/* ... */);
// blocks/MyBlock/MyBlock.js
import { Bem } from 'bem-react-core';
import OtherBlock from 'bem:OtherBlock';
export default Bem.decl(/* ... */)
// blocks/MyBlock/_myMod/MyBlock_myMod.js
import { Bem } from 'bem-react-core';
import MyBlock from 'bem:MyBlock';
export default MyBlock.declMod(/* ... */);
// pages/index/index.js
import React from 'react';
import ReactDom from 'react-dom';
import MyBlock from 'bem:MyBlock';
ReactDom.render(<MyBlock/>, document.getElementById('root'));
It should become:
// node_modules/my-lib/blocks/OtherBlock/OtherBlock.js
var Bem = require('bem-react-core').Bem;
module.exports = Bem.decl(/* ... */);
// blocks/OtherBlock/OtherBlock.js
require('../../node_modules/my-lib/blocks/OtherBlock/OtherBlock'); // NOTE: how will it work with tree-shaking?
var Bem = require('bem-react-core').Bem;
module.exports = Bem.decl(/* ... */);
// blocks/MyBlock/MyBlock.js
var Bem = require('bem-react-core').Bem;
var OtherBlock = require('../blocks/OtherBlock/OtherBlock');
module.exports = Bem.decl(/* ... */);
// pages/index/index.js
var React = require('react');
var ReactDom = require('react-dom');
var MyBlock = require('../../blocks/MyBlock/MyBlock');
ReactDom.render(React.createElement(MyBlock), document.getElementById('root'));
Sometimes we need base elems on blocks. For example menu__item
. It must provide all states from control
: hover, focus and etc. In current realization, we have different block menu-item
(it can be based on control
) or we are copy and paste code from control
to menu__item
. If we would base elems on blocks this problem will be solved.
addAttrs
, addCls
, addMods
, addStyle
and etc.
In my opinion, existing code examples are too formal. MyBlock_myMod1_myVal1
isn't very illustrative and related to real world use cases. What about making those examples more developer-friendly? We could use examples such as Button
, Input
or something like that instead of abstract MyBlock
.
Many examples to port.
if instance.buildClassName
exec else build by b
It doesn't work now.
<Bem block='Test'
dangerouslySetInnerHTML={{
__html: 'some html string'
}}
/>
Renders to empty string.
Relates to bem/webpack-bem-loader#15
// MyBlock.js
import Bem from 'bem:Bem';
import MyElem from 'bem:MyBlock-MyElem';
import OtherBlock from 'bem:OtherBlock';
import WrapBlock from 'bem:WrapBlock';
export default Bem.decl({
block : 'MyBlock',
tag : 'a',
mods({ disabled }) {
return { disabled };
},
// ... etc. about html
attrs({ disabled, onChange }) {
return {
disabled,
onChange,
onFocus: this.onFocus,
}
},
content() { // children?
return [
<Bem block={this} elem="MyElem" tag="span"/>,
<OtherBlock>{ this.props.children }</OtherBlock>,
<Bem block="OtherBlock" elem="OtherElem" tag="span"/>,
<MyElem .../>,
// ...
]
},
render() {
return WrapBlock({}, [this.__base()]);
},
componentWillMount,
componentDidMount,
componentWillReceiveProps,
shouldComponentUpdate,
// ... all React lifecycle methods
});
// MyBlock_myMod.js
import MyBlock from 'bem:MyBlock'
export default MyBlock.decl({
block : 'MyBlock',
mod : ({ myMod }) => myMod /* some predicate */,
tag : 'span',
// ... any other methods will be guarded by modifier predicate
});
setMod, getMod, delMod, getMods, toggleMod
propsTypes
is the static field and plain object. Now we can extend only functions :(
// block.js
import 'm:mod';
// require('block_mod.js').applyDecl();
export default decl({
block: 'name',
content: 'hello '
});
// block_mod.js
export default declMod({
block: 'name',
content() {
return this.__base(...arguments) + 'world';
}
})
Here we enter in block.js,
then require block_mod.js and apply it's decl.
but at this moment block's decl
wasn't executed, so ./lib/decls.js
fails here:
https://github.com/bem/bem-react-core/blob/master/lib/decls.js#L47
declMod
propTypes
and defaultProps
inherit #13Sometimes we need extend base component. Yes, I know about the base property, but it'll look like copy and paste of code for baseComponent for one or two new methods.
Guys didn't you think about replace
mod?
It will be useful when I want to return array of nodes:
// App.react.js
import React from 'react';
import {decl} from 'bem';
import AppContent from 'e:Content';
export default decl({
block: 'App',
content: (<AppContent />)
})
// App__Content.react.js
import React from 'react';
import {decl} from 'bem';
export default decl({
block: 'App',
elem: 'Content',
content: (
<div class="Stupid-Wrapper>
<span>One</span>
<span>Two</span>
<span>Three</span>
</div>
})
With replace()
mod I could return array so there is no need to wrap it in unnecessary <div>
.
You mentioned a few more libraries in this section: https://github.com/bem/bem-react-core#css-classes-generation
It would be nice to mention dumb-bem as well
Full reload needed :(
При миксировании сущности в JSX, происходит дублирование микса.
Пример:
payment-scenario.react.js
import React from 'react';
import { decl } from 'bem-react-core';
export default decl({
block: 'payment-scenario'
});
Вызов
<PaymentScenario mix={{ block: 'island', elem: 'section' }} />
=>
Получаемый HTML
<div class="payment-scenario island__section island__section"></div>
We can use it as "interfaces".
TypeError: Cannot read property 'prototype' of null
at Object.applyEntityDecls [as applyDecls] (lib/decls.js:48:32)
at Object.<anonymous> (__tests__/fixtures1.blocks/BlockWithRequiredMod/BlockWithRequiredMod.js:3:132)
at Object.<anonymous> (__tests__/orderOfMod.spec.js:3:57)
at process._tickCallback (internal/process/next_tick.js:103:7)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.