Material-ui: [рдлреНрд▓реИрдЯрдмрдЯрди] рдлрд╝рд╛рдЗрд▓ рдЗрдирдкреБрдЯ рдмрдЯрди рдХреЗ рд╕рд╛рде рдХрд╛рдо рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛ рд╣реИред

рдХреЛ рдирд┐рд░реНрдорд┐рдд 15 рдордИ 2015  ┬╖  27рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: mui-org/material-ui

рдЗрд╕ рдХреЗ рд╕рд╛рде...

<FlatButton primary={true} label="Choose an Image">
  <input type="file" id="imageButton"></input>
</FlatButton>

рдореИрдВ рдПрдХ рдмрдЯрди рдХреЗ рд╕рд╛рде рд╕рдорд╛рдкреНрдд рд╣реЛрддрд╛ рд╣реВрдВ рдЬреЛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдбреЛрдо рдореЗрдВ рдлрд╝рд╛рдЗрд▓ рдЗрдирдкреБрдЯ рдлрд╝реАрд▓реНрдб рдкреНрд░рд╕реНрддреБрдд рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ (рдмрдЯрди рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рдиреЗ рд╕реЗ рдлрд╝рд╛рдЗрд▓ рд╕рдВрд╡рд╛рдж рдирд╣реАрдВ рдЦреБрд▓рддрд╛ рд╣реИ)ред

рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА

рдЕрдЧрд░ рдХреЛрдИ рдФрд░ рдЗрд╕ рдореБрджреНрджреЗ рдкрд░ рдЖрддрд╛ рд╣реИ рддреЛ рдореИрдВрдиреЗ рдкрд╛рдпрд╛ рдХрд┐ рдЖрдк containerElement рдХреЛ RaisedButton $ рдкрд░ рд╕реЗрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рддрд╛рдХрд┐ рдмрдЪреНрдЪреЗ рдХреЗ рд░реВрдк рдореЗрдВ рдЗрдирдкреБрдЯ рддрддреНрд╡ рд░рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдФрд░ рдЙрдкрдпреБрдХреНрдд рд╣реЛред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдПрдХ рд▓реЗрдмрд▓ ;-)

<RaisedButton
  containerElement='label' // <-- Just add me!
  label='My Label'>
    <input type="file" />
</RaisedButton>

рд╕рднреА 27 рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

рд╕рдВрд╕реНрдХрд░рдг 0.7.5 рдкрд░ред

@nschaubeck рдХреНрдпрд╛ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рд╕рд╛рдЗрдЯ рдкрд░ рдмрдЯрди рдЖрдкрдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ?

@ hai-cea рд╣рд╛рдБ рдпрд╣ рдХрд░рддрд╛ рд╣реИред рдРрд╕рд╛ рд▓рдЧ рд░рд╣рд╛ рдерд╛ рдХрд┐ <input> рддрддреНрд╡ _in_ DOM рднреА рдирд╣реАрдВ рдерд╛, рдЬреИрд╕реЗ рдмрдЯрди рддрддреНрд╡ рдЕрдкрдиреЗ рдмрдЪреНрдЪреЛрдВ рдХреЛ рдкреНрд░рд╕реНрддреБрдд рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛ рдерд╛ред

рдореБрдЭреЗ рднреА рдпрд╣ рд╕рдорд╕реНрдпрд╛ рд╣реЛ рд░рд╣реА рд╣реИред @nschaubeck рдХреНрдпрд╛ рдЖрдкрдХреЛ рдХрднреА рдХреЛрдИ рд╕рдорд╛рдзрд╛рди рдорд┐рд▓рд╛?

@ рдИ-рдореЛрдирд╕рди рдореИрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╕рдорд╛рдзрд╛рди рдЦреЛрдЬрдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдирд╣реАрдВ рдерд╛ред

рдпрд╣ рдХрд╛рдо!
рдЪрд▓реЛ рд╢реИрд▓рд┐рдпреЛрдВ = {
рдЙрджрд╛рд╣рд░рдг рдЫрд╡рд┐ рдЗрдирдкреБрдЯ: {
рдХрд░реНрд╕рд░: 'рдкреЙрдЗрдВрдЯрд░',
рд╕реНрдерд┐рддрд┐: 'рдкреВрд░реНрдг',
рд╢реАрд░реНрд╖: '0',
рдиреАрдЪреЗ: '0',
рджрд╛рдПрдВ: '0',
рдмрд╛рдПрдВ: '0',
рдЪреМрдбрд╝рд╛рдИ: '100%',
рдЕрд╕реНрдкрд╖реНрдЯрддрд╛: '0'
}
}

      <FlatButton label="Choose an Image" primary={true}>
        <input id="imageButton" style={styles.exampleImageInput} type="file"></input>
      </FlatButton>

@nihildaga рдЬреЛ рдХреЗрд╡рд▓ рдХреНрд░реЛрдо рдкрд░ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдЗрдирдкреБрдЯ рдлрд╝реАрд▓реНрдб рдХреЛ рдмрдЯрди рдореЗрдВ рд░рдЦрдирд╛ W3C рдпреБрдХреНрддрд┐ рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рдирд╣реАрдВ рд╣реИред

рдПрдХ рдЕрд▓рдЧ рд╕рдорд╛рдзрд╛рди рдпрд╣ рд╣реИ рдХрд┐ рдмрдЯрди рдХреЛ рдЫрд┐рдкреЗ рд╣реБрдП рдЗрдирдкреБрдЯ рдлрд╝реАрд▓реНрдб рдХреЗ рдХреНрд▓рд┐рдХ рдИрд╡реЗрдВрдЯ рдХреЛ рдХреЗрд╡рд▓ рдЖрдЧ рд▓рдЧрд╛рдирд╛ рд╣реИред

handleChange: function(e){
  console.log(e.target.value)
},
_openFileDialog: function(){
  var fileUploadDom = React.findDOMNode(this.refs.fileUpload);
  fileUploadDom.click();
},
render: function() {
  return (
    <FlatButton
      label="Upload file"
      onClick={this._openFileDialog}/>
    <input
      ref="fileUpload"
      type="file" 
      style={{"display" : "none"}}
      onChange={this._handleChange}/>
  );
}

рдореИрдВ рджреЗрдЦ рд░рд╣рд╛ рд╣реВрдВ рдХрд┐ рдпрд╣ рд╕рдорд╕реНрдпрд╛ рдЕрднреА рднреА рдареАрдХ рдирд╣реАрдВ рд╣реБрдИ рд╣реИ ...
рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдореЗрдВ рдкреНрд░рд╕реНрддрд╛рд╡рд┐рдд рд╕рдорд╛рдзрд╛рди рдХреЗрд╡рд▓ рдХреНрд░реЛрдо рдореЗрдВ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдЬреИрд╕рд╛ @Wofiel рдиреЗ рдХрд╣рд╛ред (рдЕрднреА рднреА рдмреАрдЯрд╛ 15-0.2 рдореЗрдВ рдорд╛рдорд▓рд╛)

рдХреНрдпрд╛ htmlFor рдХреА рддрд░рд╣ <FlatButton> (рдпрд╛ <RaisedButton> ) рдкрд░ рд╕реЗрдЯ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдмреЗрд╣рддрд░ рдирд╣реАрдВ рд╣реЛрдЧрд╛, рдЗрдирдкреБрдЯ рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдПрдХ рдЖрдИрдбреА рд╕реЗрдЯ рдХрд░реЗрдВ рдФрд░ рдмрд╕ рдЗрддрдирд╛ рд╣реА? рдЖрдкрдХреЛ рдХреНрд▓рд┐рдХ рдХреЛ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдЯреНрд░рд┐рдЧрд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реЛрдЧреА...
рдореИрдВрдиреЗ рд▓реЗрдмрд▓ рдореЗрдВ рдмрдЯрди рд▓рдкреЗрдЯрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА, рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, рдпрд╣ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ :(

рдЕрднреА @Wofiel рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рд╕рдорд╛рдзрд╛рди рдкреНрд░рддреАрдд рд╣реЛрддрд╛ рд╣реИред

рдЬрдм рдореВрд▓ рд╕рдорд╛рдзрд╛рди рдирд╣реАрдВ рд╣реИ рддреЛ рдЗрд╕реЗ рдмрдВрдж рдХреНрдпреЛрдВ рдХрд░реЗрдВ

рд╣рд╛рдп @Wofiel рдЖрдк рдПрдХ рд╕реНрдЯреЗрдЯрд▓реЗрд╕ рдШрдЯрдХ рдореЗрдВ рд░реЗрдлрд░реА рдХреЗ рдмрд┐рдирд╛ рдЗрд╕ рддрдХрдиреАрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рд╕реБрдЭрд╛рд╡ рдХреИрд╕реЗ рджреЗрддреЗ рд╣реИрдВ?

@excalliburbd рдЖрдк рдЖрдИрдбреА рдФрд░ jQuery рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП

рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдореЗрдВ @ рдмрд┐рд░рд╕рди рдбреЛрдо рд╣реЗрд░рдлреЗрд░? рдХреНрдпрд╛ рдпреЗ рдареАрдХ рд╣реИ?

рдореИрдВ рдЖрдорддреМрд░ рдкрд░ рдЗрд╕рдХреА рдЕрдиреБрд╢рдВрд╕рд╛ рдирд╣реАрдВ рдХрд░рддрд╛, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдПрдХ рдХреНрд▓рд┐рдХ рдИрд╡реЗрдВрдЯ рдЯреНрд░рд┐рдЧрд░ рдХрд░рдирд╛ рд╣реИ рдЬреЛ рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдареАрдХ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП

@Wofiel рдЬреИрд╕рд╛ рд╕рдВрд╕реНрдХрд░рдг 15 рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЗ рд╕рд╛рде рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ?

@Wofiel рдЗрд╕ рд╕рдорд╛рдзрд╛рди рдХреЗ рд╕рд╛рде console.log(e.target.value) рдПрдХ рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИ
рд╕реА:\рдирдХрд▓реАрдкрде\imagefilename.png
рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рд╕рдорд╛рдзрд╛рди рд╣реИ
e.target.files[0]

рдЕрдЧрд░ рдХреЛрдИ рдФрд░ рдЗрд╕ рдореБрджреНрджреЗ рдкрд░ рдЖрддрд╛ рд╣реИ рддреЛ рдореИрдВрдиреЗ рдкрд╛рдпрд╛ рдХрд┐ рдЖрдк containerElement рдХреЛ RaisedButton $ рдкрд░ рд╕реЗрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рддрд╛рдХрд┐ рдмрдЪреНрдЪреЗ рдХреЗ рд░реВрдк рдореЗрдВ рдЗрдирдкреБрдЯ рддрддреНрд╡ рд░рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдФрд░ рдЙрдкрдпреБрдХреНрдд рд╣реЛред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдПрдХ рд▓реЗрдмрд▓ ;-)

<RaisedButton
  containerElement='label' // <-- Just add me!
  label='My Label'>
    <input type="file" />
</RaisedButton>

@ рдереЙрдорд╕ 101 рдзрдиреНрдпрд╡рд╛рдж! рдореБрдЭреЗ рдЕрднреА рдЗрд╕ рдореБрджреНрджреЗ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рдирд╛ рдкрдбрд╝рд╛ рд╣реИ рдФрд░ рдЖрдкрдХрд╛ рд╕рдорд╛рдзрд╛рди рдХрд╛рдо рдХрд░рддрд╛ рдкреНрд░рддреАрдд рд╣реЛрддрд╛ рд╣реИред
рдмрд╣реБрдд рдмрдврд╝рд┐рдпрд╛ :)

@ рдереЙрдорд╕ 101 рдЯрд┐рдк рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред рдЗрд╕рд╕реЗ рдореЗрд░реА рд╕рдорд╕реНрдпрд╛ рднреА рд╣рд▓ рд╣реЛ рдЧрдИред рд╡рд╛рд╕реНрддрд╡рд┐рдХ

рдмрд╕ @ рдереЙрдорд╕ 101 рдЙрддреНрддрд░ рдХрд╛ рдкреВрд░рдХ, рдЬрдм рдореИрдВ рдШрдЯрдХреЛрдВ рдХреЛ рдЙрдирдХреЗ рдЙрджрд╛рд╣рд░рдг рдХреА рддрд░рд╣ рдШреЛрд╖рд┐рдд рдХрд░рддрд╛ рд╣реВрдВ, рддреЛ рдореЗрд░рд╛ рдЙрдард╛рдпрд╛ рдмрдЯрди рдлрд╝рд╛рдЗрд▓ рдЗрдирдкреБрдЯ рдХреЗ рд╕рд╛рде рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕реЗ рд░реЛрдХрдиреЗ рдХреЗ рд▓рд┐рдП, рдмрд╕ рдлрд╝рд╛рдЗрд▓ рдЗрдирдкреБрдЯ рд╢реИрд▓реА рдХреЛ display: none рдкрд░ рд╕реЗрдЯ рдХрд░реЗрдВред :)

<RaisedButton
  containerElement='label' // <-- Just add me!
  label='My Label'>
    <input type="file" style={{ display: 'none' }} />
</RaisedButton>

@andreyluiz рдХрд┐рди рдкрд░рд┐рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдореЗрдВ рдпрд╣ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ:

<RaisedButton label='My Label'>
    <input type="file" />
</RaisedButton>

рдореБрдЭреЗ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рд╕рд╛рдЗрдЯ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд╕рд╛рде рдХреЛрдИ рд╕рдорд╕реНрдпрд╛ рдирд╣реАрдВ рдорд┐рд▓реА рд╣реИ, рд▓реЗрдХрд┐рди рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдХрдИ рдЕрдиреНрдп рд▓реЛрдЧреЛрдВ рдХреЗ рдкрд╛рд╕ рдпрд╣ рд╕рдорд╕реНрдпрд╛ рд╣реИ!

рдХреНрдпрд╛ рдпрд╣ рдЖрдкрдХреЗ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рджрд╛рди рдХрд┐рдП рдЧрдП рдХреЛрдб рдХреЗ рд╕рд╛рде рдирд╣реАрдВ рджрд┐рдЦрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдлрд╝рд╛рдЗрд▓ рдЗрдирдкреБрдЯ рдХреЗ рдЕрдиреБрд░реВрдк рд╣реИ?

рд╡рд╣ рдЕрдЬреАрдм рд╣реИред рдореЗрд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдпрд╣ рд╕рд╛рдордЧреНрд░реА-рдпреВрдЖрдИ рдмрдЯрди рдХреЗ рдЕрдВрджрд░ рдПрдХ рдлрд╝рд╛рдЗрд▓ рдЗрдирдкреБрдЯ рдкреНрд░рд╕реНрддреБрдд рдХрд░рддрд╛ рд╣реИред

@andreyluiz рд╣рд╛рдВ, рдбреЙрдХреНрд╕ рд╕рд╛рдЗрдЯ рдЙрджрд╛рд╣рд░рдг (http://www.material-ui.com/#/components/raised-button) рдХреЗ рд╕рд╛рде рдХреЛрдИ рджреГрд╢реНрдпрдорд╛рди <input> рдирд╣реАрдВ рд╣реИред рдЖрдк рдХрд┐рд╕ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдФрд░ рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд╕рд╛рде рдкрд░реАрдХреНрд╖рдг рдХрд░ рд░рд╣реЗ рд╣реИрдВ?

рдирд╡реАрдирддрдо рдХреНрд░реЛрдо рд╕рдВрд╕реНрдХрд░рдгред

рдореИрдВ @andreyluiz рд╕реЗ рд╕рд╣рдордд рд╣реВрдВ, the рд╕рд╛рде рд╣реА рджрд┐рдЦрд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди style={{display: 'none'}} рдХреЗ рд╕рд╛рде, рдпрд╣ рдПрдХ рдЖрдХрд░реНрд╖рдг рдХреА рддрд░рд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ!

рдЯреАрдПрд▓; рдбреЙ

<RaisedButton
  containerElement="label"
  icon={<Icons.FileUpload />} // material-ui-icons
  labelColor="white"
  primary
  style={{ minWidth: 40, width: 40 }}>
  <input
    onChange={e => this.upload(e.target.files[0])}
    style={{ display: 'none' }}
    type="file"
  />
</RaisedButton>

рдЙрдкрд░реЛрдХреНрдд рд╕рдорд╛рдзрд╛рди рдЕрдм рдФрд░ рдХрд╛рдо рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛ рд╣реИред рдореИрдВ рдирдИ v1 рдмреАрдЯрд╛ рд╢рд╛рдЦрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдФрд░ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдореЗрд░реЗ рд▓рд┐рдП рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ

                        <Button dense
                                containerElement="label"
                                label="label">
                            <input
                                onChange={e => this.upload(e.target.files[0])}
                                style={{display: 'none'}}
                                type="file"
                            />
                        </Button>

рдореБрдЭреЗ рдХрдВрд╕реЛрд▓ рдореЗрдВ рдирд┐рдореНрди рддреНрд░реБрдЯрд┐ рдорд┐рд▓рддреА рд╣реИ:

Warning: React does not recognize the `containerElement` prop on a DOM element.
If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase `containerelement` instead.
If you accidentally passed it from a parent component, remove it from the DOM element.

рдХрд┐рд╕реА рдХреЛ рдЙрдкрд╛рдп рдкрддрд╛ рд╣реИ? рд╡реИрд╕реЗ рднреА рдЗрд╕ рддрд░рд╣ рдХреЗ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЗ рдХреЛ рдореВрд▓ рд░реВрдк рд╕реЗ рд╕рдорд░реНрдерд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП? (рдЧреИрд░-рд╣реИрдХреА рддрд░реАрдХреЗ рд╕реЗ)

@ рдЖрджрд┐рддреНрдп рдЖрдирдВрдж 1 рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЛрдб рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП

<Button
            raised
            component="label" <---- use component instead of containerElement
            color="primary"
            className={buttonClassname}
            disabled={this.state.loading}
            onClick={this.handleButtonClick}
          >
            {'Upload'}
            <FileUpload className={classes.rightIcon} />
            <input
              onChange={e => console.log(e.target.files[0])}
              style={{ display: 'none' }}
              type="file"
            />
</Button>
рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕

рд╕рдВрдмрдВрдзрд┐рдд рдореБрджреНрджреЛрдВ

sys13 picture sys13  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

rbozan picture rbozan  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

ericraffin picture ericraffin  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

anthony-dandrea picture anthony-dandrea  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

zabojad picture zabojad  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ