Material UI - 在 AppBar 点击打开 LeftNav/Drawer
Material UI - Open LeftNav / Drawer on AppBar click
我发现了 ReactJS 和 material-ui (http://material-ui.com/)。
我尝试为我的应用程序创建一个默认模板。
我想在分离的组件中使用 AppBar 和 LeftNav(在新版本的抽屉中重命名)。
默认情况下,AppBar 上有一个菜单按钮。我想用它来打开 LeftNav 但我不知道如何调用我的 LeftBarComponent 组件函数来打开它。
我几乎了解了如何在组件之间进行通信,但就我而言,我不知道该怎么做,因为没有相关文档。
我唯一知道打开 LeftNav 元素的方法是使用 LeftNav.toggle()
http://material-ui.com/#/components/left-nav
感谢您的帮助。
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;
在这种情况下,您需要通过组件向上传递事件,然后再向下传递。
<MainNavbar onClickMenu=this.onClickMenu/>
<LeftNavbar isOpen=this.state.leftNavIsOpen/>
但是,将其与 Reactjs 结合使用并不是最佳选择,因为 LeftNav material 组件不会对属性做出反应,而是像您所说的那样对方法调用做出反应。
要解决此问题,您可以检查 LeftNav 渲染方法,检查当前状态,并在需要时调用 toggle()。原则上这违背了 React 的思维方式,因为状态包含在特定的子组件中,而不是在处理它的 DefaultComponent 中。
render:function(){
if(this.props.isOpen){
LeftNav.open();
}
return ...
为了澄清steinso所说的,你需要使用Flux架构将事件发送到一个Action,然后在一个Store中改变它。然后使用 EventEmitter 发送一个 emit change 事件。这将在具有更新状态的受影响组件上触发渲染。
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 一起使用,并且我在 AppBar 中使用 onLeftIconButtonTouchTap={this.handleToggle} 事件完成了此操作。更详细的可以参考官方文档 http://www.material-ui.com/#/components/app-bar
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;
我想它会对你有所帮助。
我发现了 ReactJS 和 material-ui (http://material-ui.com/)。
我尝试为我的应用程序创建一个默认模板。 我想在分离的组件中使用 AppBar 和 LeftNav(在新版本的抽屉中重命名)。
默认情况下,AppBar 上有一个菜单按钮。我想用它来打开 LeftNav 但我不知道如何调用我的 LeftBarComponent 组件函数来打开它。
我几乎了解了如何在组件之间进行通信,但就我而言,我不知道该怎么做,因为没有相关文档。 我唯一知道打开 LeftNav 元素的方法是使用 LeftNav.toggle()
http://material-ui.com/#/components/left-nav
感谢您的帮助。
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;
在这种情况下,您需要通过组件向上传递事件,然后再向下传递。
<MainNavbar onClickMenu=this.onClickMenu/>
<LeftNavbar isOpen=this.state.leftNavIsOpen/>
但是,将其与 Reactjs 结合使用并不是最佳选择,因为 LeftNav material 组件不会对属性做出反应,而是像您所说的那样对方法调用做出反应。
要解决此问题,您可以检查 LeftNav 渲染方法,检查当前状态,并在需要时调用 toggle()。原则上这违背了 React 的思维方式,因为状态包含在特定的子组件中,而不是在处理它的 DefaultComponent 中。
render:function(){
if(this.props.isOpen){
LeftNav.open();
}
return ...
为了澄清steinso所说的,你需要使用Flux架构将事件发送到一个Action,然后在一个Store中改变它。然后使用 EventEmitter 发送一个 emit change 事件。这将在具有更新状态的受影响组件上触发渲染。
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 一起使用,并且我在 AppBar 中使用 onLeftIconButtonTouchTap={this.handleToggle} 事件完成了此操作。更详细的可以参考官方文档 http://www.material-ui.com/#/components/app-bar
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;
我想它会对你有所帮助。