有没有办法遍历由React构建的树?

时间:2014-10-23 15:38:16

标签: javascript reactjs

我需要为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 Developer Tools (Chrome扩展程序)可以做到这一点。

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

1 个答案:

答案 0 :(得分:0)

所以你想要:

<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中使用if-else)上文)。

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

我还会将要应用于MyField组件的任何特定一次性样式传递给道具。