【问题标题】:Is there a way to traverse tree built by React?有没有办法遍历 React 构建的树?
【发布时间】:2014-12-19 08:15:14
【问题描述】:

我需要为 HTML 页面构建可视化编辑器。看来 ReactJS 是一个不错的选择。目前我面临以下问题:

我为我的数据建模:

var Model = {
    title: 'Hello',
    description: 'Pellentesque eleifend urna ac purus tempus...',
    date: new Date().toString()
};

并构建了将其数据存储在上述结构中的组件:

var App = React.createClass({
    getInitialState: function () {
        return {
            value: Model
        }
    },
    handleMouseEnter: function (event) {
        $(event.target).css('outline', '1px solid red').attr('contenteditable', true);
    },
    handleMouseLeave: function (event) {
        var t = $(event.target), v = this.state.value;
        t.css('outline', 'none').attr('contenteditable', false);
        v[t.attr('property')] = t.text();
        this.setState({value: v});
    },
    render: function () {
        var v = this.state.value;
        return (
            <div>
                <pre style={{whiteSpace: 'normal'}}>{JSON.stringify(this.state)}</pre>
                <h1 onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} property="title">{v.title}</h1>
                <p onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} property="description">{v.description}</p>
                <p onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} property="date">{v.date}</p>
            </div>
        );
    }
});

React.renderComponent(<App />, document.getElementById('app'));

在这种特殊情况下,它可以工作。但我想摆脱onMouseEnteronMouseLeave 属性,只保留property 字段。像这样:

<pre style={{whiteSpace: 'normal'}}>{JSON.stringify(this.state)}</pre>
<h1 property="title">{v.title}</h1>
<p property="description">{v.description}</p>
<p property="date">{v.date}</p>

我考虑过创建 mixin。然后,在componentDidMount 事件中,将处理程序附加到具有property 属性的所有元素。但是我发现没有办法做到这一点。

我的问题是:有没有办法遍历 React 构建的树?我注意到 React 开发者工具(Chrome 扩展)可以做到这一点。

类似问题:React.js component creating parent child relations and iterating

【问题讨论】:

  • 那么你需要一种方法来遍历父组件生成的子组件吗?在您的父母中,有一个存储模型数组的状态。然后在渲染中,您可以使用array.map 遍历数组中的每个模型,并返回一个子组件,并从父组件传递事件处理程序和模型数据
  • @trekforever 不好的解决方案。有了它,我需要再有一个模型——用于视图,从中将生成 DOM 节点。 jsfiddle.net/kb3gN/6684
  • 我很困惑为什么你会想要做你所描述的事情 - 也许进一步详细说明你正在尝试做的事情不能仅仅通过 array.map 来实现?
  • 在我看来,你正在尝试做一些 React 可以为你做的事情。如果你想遍历这个组件的所有 children,你只需使用 @987654334 @ 财产。更好的方法,IMO,对你来说只是在 componentDidMount 上的 mixin 中的普通 DOM 方法,你可以在其中说类似 document.querySelectorAll('*[property]') (非 jquery ex)的内容。不知道选择器是否真的正确..
  • 为什么你用 jquery 改变 CSS 而不是在你的 CSS 文件中只包含 h1.someClass:hover { outline: 1px solid red; }?另外我听说contentEditable 不能很好地与 React 配合使用,你可能想在这里阅读它 stackoverflow.com/questions/22677931/… 例如,然后再继续

标签: javascript reactjs


【解决方案1】:

所以你想要:

<h1 onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} property="title">{v.title}</h1>

作为

<h1 property="title">{v.title}</h1>

我会为此使用另一个 Component,它负责渲染特定类型的组件,就像 redux-form 所做的那样。

实现您想要做的最简单的方法是:

class MyField extends Component {
  constructor(props) { 
    super(props); 
    this.handleMouseEnter = this.handleMouseEnter.bind(this); 
  }
  handleMouseEnter() { ... }
  render() {
    const { property, children } = this.props;
    if (property === 'title') {
      return (
        <h1 onMouseEnter...>{children}</h1>
      );
    }
  }
}

然后你可以在任何其他组件上这样调用它:

<MyField property="title">Stackoverflow</MyField>

更专业但也更困难的方法是Field 的redux-form 实现,他们甚至使用React.createElement 生成HTML(我在上面的示例中使用if-else)。

如果你需要访问它之外的任何数据,要么通过属性传递一个函数,要么将 MyField 组件连接到 redux(redux-form 也这样做)。

我还将通过 props 传递您想要应用于 MyField 组件的任何特定一次性样式。

【讨论】:

    猜你喜欢
    • 2021-09-06
    • 1970-01-01
    • 2010-11-20
    • 2016-01-16
    • 2016-05-03
    • 1970-01-01
    • 2020-06-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多