设计模式帮助:如何从单个控制器组件呈现动态视图



我目前有一个保存业务逻辑的组件,根据页面的不同,我想呈现不同的视图。我遇到了麻烦,因为我不确定如何将控件组件的功能和道具优雅地传递到视图组件中。

现在,我的解决方案是:

<Controller viewComponent={ViewComponent} />

然后在控制器中渲染:

<this.props.viewComponent function1={this.func} function2={this.func2} />

有效,但它令人困惑,我几乎可以肯定它不是最优雅的解决方案。克隆还有一个解决方案,但这似乎也是一个黑客。

有人对如何解决这个问题有任何见解吗?

您可能有兴趣使用类似 react-router 的东西。 您可以使用 react-router 来执行客户端路由,该路由将根据访问的 URL 呈现不同的 React 组件。

例如,此组件将用于定义路由以及将使用哪些组件来表示它们:

索引.js

import {render} from 'react-dom';
import {Router, Route, IndexRoute, hashHistory} from 'react-router';
import App from './app';
import Home from './home';
import Account from './account';
render((
    <Router history={hashHistory}>
        <Route path='/' component={App}>
            <IndexRoute component={Home}/>
            <Route path='/account:username' component={Account}/>
        </Route>
    </Router>
), document.getElementById('react-root'));
此组件将

用于将 props(例如函数列表)传递给任何动态渲染的组件(通过 React.Children 渲染):

应用.js

import React from 'react';
function getFunctionList() {
    return {
        someFunction() {
            //do something
        },
        someOtherFunction() {
            //do something
        }
    };
}
function renderComponent() {
    return React.Children.map(this.props.children, child =>
        React.cloneElement(child, ...getFunctionList())
    );
}
export default class extends React.Component {
    render() {
        return (
            <div className='wrapper'>
                <nav>
                    <ul>
                        <li><Link to={'/home'}>Home</Link></li>
                        <li><Link to={`/account/foo`}>foo's Account</Link></li>
                    </ul>
                </nav>
                {renderComponent.call(this)}
                <footer></footer>
            </div>
        );
    }
};

下面是访问路由时向用户显示的一些组件的简单示例:

首页.js

import React from 'react';
export default class extends React.Component {
    render() {
        //you could call this.props.someFunction() here
        return (
            <div className='home'>
                Home Page
            </div>
        );
    }
};

帐户.js

import React from 'react';
export default class extends React.Component {
    const {username} = this.props.params;
    render() {
        return (
            <div className='account'>
                Viewing account for {username}
            </div>
        );
    }
};

我真的认为你最好的选择就是做这样的事情。 你的问题听起来完全像 react-router 就是为了解决的问题而构建的那种问题。

如果需要,可以将其扩展为使用 Redux 跟踪可以管理应用程序状态的单个store。 为了使其与 react-router 保持同步,您也可以使用此库。

如果您对此有任何疑问,请告诉我。

为什么不直接做:

<Controller> <ViewComponent ... /> </Controller>

在控制器的渲染函数中:

<div> {this.props.children} </div>

更新:如果你想将父函数和状态/道具传递给子项,请使用React.Children.map函数。

renderChildren = () => {
  React.Children.map(this.props.children, (c) => {
    <c.type
      {...this.props}
      {...c.props}
      someFunction={this.someFunction}
    />
  }
}
<div>
{ this.renderChildren() }
</div>

最新更新