Пользовательский интерфейс материала - Открыть LeftNav / Drawer на панели инструментов нажмите

Я открываю ReactJS и материал-интерфейс ( http://material-ui.com/).

Я пытаюсь создать шаблон по умолчанию для моего приложения. Я хочу использовать AppBar и LeftNav (переименованный в Drawer в новых версиях) в отдельных компонентах.

По умолчанию на панели приложений есть кнопка меню. Я хочу использовать его, чтобы открыть LeftNav, но я не знаю, как я могу вызвать функцию компонента LeftBarComponent, чтобы открыть его.

Я почти понял, как общаться между компонентами, но в моем случае я не знаю, как я мог бы это сделать, потому что нет документации об этом. Единственное, что я знаю, чтобы открыть элемент LeftNav, это использовать LeftNav.toggle ()

http://material-ui.com/

Спасибо за вашу помощь.

Default.jsx

use strict';

var React = require('react');
var pageStore = require('../../stores/page');

var MainNavbar = require('../modules/navbar.jsx');
var LeftNavbar = require('../modules/leftbar.jsx');

var getState = function() {
  return {
    title: pageStore.get().title
  };
};

var DefaultComponent = React.createClass({
  mixins: [pageStore.mixin],
  componentDidMount: function() {
    pageStore.emitChange();
  },
  getInitialState: function() {
    return getState();
  },
  render: function() {
    return (
      /* jshint ignore:start */
      <div className="main-container">
        <MainNavbar />
        <LeftNavbar />
        <div className="content">
          {this.props.children}
        </div>
      </div>
      /* jshint ignore:end */
    );
  },
  // Event handler for 'change' events coming from store mixins.
  _onChange: function() {
    this.setState(getState());
  }
});

module.exports = DefaultComponent;

navbar.jsx

'use strict';

var React = require('react');
var routeActions = require('../../actions/routes');

var MUI = require('material-ui');
var AppBar = MUI.AppBar;

// Navbar Component
// Application main menu
// Usage: <Navbar />
var NavbarComponent = React.createClass({
  render: function() {
    return (
      /* jshint ignore:start */
      <AppBar title="MyApp" onMenuIconButtonTouchTap={ this._handleClick }>
        <div className="clear"></div>
      </AppBar>
      /* jshint ignore:end */
    );
  },
  _handleClick: function()
  {
    console.log('ok');
  }
});

module.exports = NavbarComponent;

leftbar.jsx

'use strict';

var React = require('react');
var routeActions = require('../../actions/routes');

var MUI = require('material-ui');
var LeftNav = MUI.LeftNav;
var MenuItem = MUI.MenuItem;

var menuItems = [
  { route: 'home', text: 'Home' },
  { route: 'about', text: 'About' },
];

// LeftBar Component
// Application left menu
// Usage: <LeftBar />
var LeftBarComponent = React.createClass({
  render: function() {
    return (
      /* jshint ignore:start */
      <LeftNav menuItems={menuItems} docked={false} />
      /* jshint ignore:end */
    );
  },
  _handleClick: function()
  {
    console.log('ok');
  }
});

module.exports = LeftBarComponent;

3 ответа

Решение

В этом случае вам нужно передать событие вверх через ваши компоненты, а затем снова вниз.

    <MainNavbar onClickMenu=this.onClickMenu/>
    <LeftNavbar isOpen=this.state.leftNavIsOpen/>

Однако использование этого в сочетании с Reactjs не оптимально, так как компонент материала LeftNav реагирует не на атрибуты, а на вызовы методов, как вы говорили.

Чтобы обойти это, вы можете поставить проверку в методе рендеринга LeftNav, который проверяет текущее состояние и вызывает toggle() при необходимости. В принципе это противоречит образу мышления React, так как состояние содержится внутри определенного дочернего компонента, а не в DefaultComponent, который его обрабатывает.

render:function(){
  if(this.props.isOpen){
     LeftNav.open();
  }
  return ...

Чтобы уточнить, что сказал Стейнсо, вам нужно отправить событие в действие с использованием архитектуры Flux, а затем изменить его в магазине. Затем отправьте событие emit change с EventEmitter. Это запустит рендеринг на задействованных компонентах с обновленным состоянием.

https://facebook.github.io/flux/

Если вы должны разделить их, это будет лучшим способом. Однако, если вы можете использовать их в одном и том же компоненте, например "Main", вы можете просто использовать атрибут ref и ссылаться на компонент.

module.exports = React.createClass({

  childContextTypes: {
    muiTheme: React.PropTypes.object
  },

  getChildContext: function() {
    return {
      muiTheme: ThemeManager.getCurrentTheme()
    };
  },

  _toggleNav: function(){
    this.refs.leftNav.toggle();
  },

  render: function() {
    return (
      <div>
        <mui.LeftNav
          ref='leftNav'
          menuItems={menuItems}
          docked={false} />
        <mui.AppBar
          title='Default'
          onLeftIconButtonTouchTap={this._toggleNav} />
      </div>
    );
  }

});

Вот так.

Я использую React с Material-UI, и я сделал это с помощью события onLeftIconButtonTouchTap={this.handleToggle} в AppBar. Для более подробной информации, вы можете обратиться к официальной документации http://www.material-ui.com/

App.js

import React from 'react';
import AppBar from 'material-ui/AppBar';
import Drawer from 'material-ui/Drawer';
import MenuItem from 'material-ui/MenuItem';  
import { BrowserRouter as Router, Route, Link } from 'react-router-dom'; 
import Dashboard from './Dashboard/dashboard.js';
import Information from './Information/information.js';
import './App.css';

class App extends React.Component {

  constructor(props) {
    super(props);
    this.state = {open: false};
  }

  handleToggle = (event) => this.setState({open: !this.state.open});

  render() {

    const {styleFromProps} = this.props;
    const contentStyle = {  ...styleFromProps, transition: 'margin-left 450ms cubic-bezier(0.23, 1, 0.32, 1)' };

    if (this.state.open) {
      contentStyle.marginLeft = 256;
    }

    return (
        <Router>
          <div>
          <AppBar title="AppTitle" onLeftIconButtonTouchTap={this.handleToggle} />

            <Drawer containerStyle={{height: 'calc(100% - 64px)', top: 64}} docked={true} width={200} open={this.state.open} zDepth={2}>
              <Link to="/dashboard" style={{ textDecoration: 'none' }}><MenuItem>Dashboard</MenuItem></Link>
              <Link to="/information" style={{ textDecoration: 'none' }}><MenuItem>Information</MenuItem></Link>
            </Drawer>

            <Route path="/dashboard" component={(props) => <Dashboard {...props} open={this.state.open}/>} />
            <Route path="/information" component={(props) => <Information {...props} open={this.state.open}/>} />
          </div>
        </Router>
    );
  }
}

export default App;

Я думаю, что это поможет вам.

Другие вопросы по тегам