【问题标题】:General structure when using React.js使用 React.js 时的一般结构
【发布时间】:2014-08-05 14:07:24
【问题描述】:

查看the Virtual DOM in React.js 并通过一些性能测试,我对这个库非常感兴趣。它似乎是 Backbone 出色的模型、路由器和集合结构的完美插件。

但是,由于缺乏高质量的教程和课程,我有几个问题希望这里的人能够回答:

HTML 模板

React 是否完全摒弃了 HTML 模板的概念?我说的是把你的视图标记放在一个单独的 HTML 文件中(或者在同一页面上的 <script type=text/template> 标记中)。你知道,就像你对 underscore.js Handlebars 等所做的那样......

Starter kit examples 似乎都在您的视图类中包含 JSX 或 React.DOM 函数,这对我来说似乎有点混乱,我可以看到这有点失控,因为您的视图变得越来越复杂.

这是一个使用带有嵌套表的基本 Twitter Bootstrap 面板元素呈现 2 个值及其总和的示例。

var CustomView = React.createClass({
    render: function() {
        var x = this.props.x;
        var y = this.props.y;

        return (
            <div className="panel panel-primary">
                <div className="panel-heading">
                    <h1 className="panel-title">Should I put all this markup somewhere else?</h1>
                </div>
                <div className="panel-body">
                    <table className="table">
                        <thead>
                            <tr>
                                <th>X</th>
                                <th>Y</th>
                                <th>Combined val</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td>{x}</td>
                                <td>{y}</td>
                                <td>{x + y}</td>
                            </tr>
                        </tbody>
                    </table>
                </div>
            </div>
        );
    }
});

我不想知道是否可以将这些东西移动到单独的文件中,而是想了解在使用 React 时什么被认为是最佳实践。

更新和设置数据

Why React page 声明如下:

简单地表达您的应用在任何给定时间点的外观,当您的基础数据发生变化时,React 将自动管理所有 UI 更新。

我不完全理解这是如何工作的。例如,使用 &lt;CustomView x="20" y="10"&gt; 之前的 React 组件。最初我会这样渲染它:

var x = 20;
var y = 10;

React.renderComponent(
    <CustomView x={x} y={y} />,
    document.getElementById('view-container')
);

现在,当我想随时更新 CustomView x 更改时,我应该如何进行? React 应该是您在 Angular 和 Ember 中找到的数据绑定的替代方案,无需进行 2 路绑定,那么我该如何实现呢?我如何告诉CustomView 关注x 并在它发生变化时自动重新渲染?

当然,只是为 x 分配一个新值没有任何作用。

我知道有 setState 方法,但我仍然必须手动调用它,对吗?因此,如果我使用 React 视图和 Backbone 模型,代码可能如下所示:

// Data model: Backbone.js
var model = new Backbone.Model({text: "Please help! :)"});

// Create view class
var View = React.CreateClass({
    render: function() {
        return (
            <p>{this.props.text}</p>
        );
    }
});

// Instantiate new view
var view = React.renderComponent(
    <View text={model.get("text")}>,
    document.getElementById('view-container')
);

// Update view
model.on("change:text", function(model, newValue) {
    view.setState({
        text: newValue
    });
});

// Change data
model.set("text", "I do not understand this ...");

这似乎是一个非常奇怪的设置,我几乎可以肯定这不可能是你应该这样做的方式。

我希望得到一些建议来帮助我朝着正确的方向前进。

提前感谢您的任何反馈和帮助。

【问题讨论】:

  • 我自己没有使用过,但可能值得一看 react-bootstrap。它似乎是将 Bootstrap 组件分解为 React 组件,因此您可以使用 &lt;Panel header="foo bar"&gt;... table ...&lt;/Panel&gt; 代替 CustomView 中的一大块面板 html。

标签: javascript backbone.js mvvm view reactjs


【解决方案1】:

谢谢大家的回复,

那么,如果我希望视图观察数据模型,我最终得到的实际上非常接近 Backbone 视图代码,我在 intialize 方法中连接事件侦听器的假设是否正确?这是一个有效的简单示例:

var model = new Backbone.Model({
    text: "Hey there :)"
});

var TextBox = React.createClass({
    getInitialState: function() {
        return this.props.model.toJSON();
    },
    componentWillMount: function() {
        this.props.model.on("change:text", function(model, newText) {
            this.setState({
                text: newText
            });
        }, this);
    },
    render: function() {
        return (
            <p>{this.state.text}</p>
        );
    }
});

React.renderComponent(
    <TextBox model={model} />,
    document.getElementById('view-holder')
);

正如我所说,这确实按预期工作。每当模型的文本属性更改时,视图就会重新呈现。这会被认为是“好”的 React 代码,还是我应该以不同的方式连接它?

【讨论】:

  • 我会听取 Shane 的建议并在您的主干视图代码中调用 React.renderComponent。这里的数据不是组件的状态,而是主干模型的状态。如果需要更改模型,您可以将 onChange 属性传递给组件,这样您就可以将所有模型代码保留在主干视图中。如果您保持组件的纯净,它会使测试和重用组件等事情变得更容易。
  • @FakeRainBrigand 哦,所以您实际上不会替换主干视图,您会在其中构建反应组件吗?这是一个非常有趣的方法!这样我仍然可以使用this.listonTo 而不是旧的model.on(...) 进行事件观察。我还获得了事件委托,并且可以只转发我想要 React 的部分。这实际上非常出色。谢谢!
【解决方案2】:

React 是否完全摒弃了 HTML 模板的概念?

是的,赞成使用 JavaScript 声明您的视图。它还允许 Virtual DOM 结构有效地工作。

Starter 工具包示例似乎都在您的视图类中包含 JSX 或 React.DOM 函数,这对我来说似乎有点乱,我可以看到这有点失控,作为您的视图越来越复杂

您不应该让您的视图变得越来越复杂。用小组件制造大组件,你不会有问题。如果您觉得它变得复杂,您可以随时重新组织它。

我知道有 setState 方法,但我仍然必须手动调用它,对吗?因此,如果我使用 React 视图和 Backbone 模型 [...]

您应该搜索“反应主干”,您会找到一些博客文章和代码示例。它们经常一起使用。随意在此处添加您认为有帮助的任何链接。

【讨论】:

  • Javascript 也比 HTML 模板更易于组合。您可以使用任何用于构建 javascript 的工具/库来构建组件。例如。我经常使用 underscorejs 中的函数从数据数组构建我的组件数组。
  • 谢谢 FakeRainBrigand!这确实让事情变得更清楚了,虽然我有点难以将自己的想法包裹在丢弃 HTML 模板上,但我想这只是我必须习惯的事情...... :)
【解决方案3】:

您走在正确的道路上,但是有两件事需要解决。一个是错误,另一个是首选模式。

错误:在视图中,您使用this.props.text(好!),但您在模型侦听器中使用setState。这将设置您未使用的 this.state.text 值,因此它不起作用。 setState 应该“仅”从组件本身内部使用 - 出于所有意图和目的,将其视为受保护的方法。取而代之的是 setProps 函数,它只能在组件外部使用。

首选模式:setProps 的使用将很快被弃用,因为它会导致许多微妙的问题。更好的做法是每次都重新渲染整个组件。在您的情况下,正确的代码是:

// Data model: Backbone.js
var model = new Backbone.Model({text: "Please help! :)"});

// Create view class
var View = React.CreateClass({
    render: function() {
        return (
            <p>{this.props.text}</p>
        );
    }
});

function rerender() {
  React.renderComponent(
    <View text={model.get("text")}>,
    document.getElementById('view-container')
  );
}

// Update view
model.on("change:text", function(model, newValue) {
    rerender();
});

rerender();

【讨论】:

  • 问题:如果你有一个父 React 组件有很多 model.get 调用,你是否必须在每次对其中一个进行轻微更新时调用所有这些组件。例如,假设您是 Facebook 并且您删除了一个朋友,它是否必须重新渲染并再次获取整个父 React 组件的所有数据?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多