【问题标题】:Custom ReactJS component that respects 'valueLink'尊重“valueLink”的自定义 ReactJS 组件
【发布时间】:2014-11-17 02:45:14
【问题描述】:

我正在构建一个自定义 ReactJS 组件(一个“Select2”下拉库包装器)并希望使用“valueLink”参数实现对标准双向绑定助手的支持。

但是,处理“valueLink”参数的 mixin 似乎只适用于标准组件,而不适用于自定义组件。

有没有办法让我的组件自动实现标准 valueLink 行为,或者我需要自己显式解析和实现这种支持(可能会引入基础库中不存在的错误或奇怪行为)

【问题讨论】:

    标签: data-binding reactjs


    【解决方案1】:

    使用LinkedStateMixin 时从this.linkState 返回的对象有两个相关属性:valuerequestChange()。只需将这两个属性分别用作您的值和更改处理程序,就好像它们已通过valueonChange 传递给您的自定义组件一样。

    这是一个包装a jQuery color picker的复合组件示例;它适用于valueLink 和标准valueonChange 属性。 (要运行示例,请展开“显示代码 sn-p”,然后单击底部的“运行代码 sn-p”。)

    var ColorPicker = React.createClass({
      render: function() {
        return <div />;
      },
    
      getValueLink: function(props) {
        // Create an object that works just like the one
        // returned from `this.linkState` if we weren't passed
        // one; that way, we can always behave as if we're using
        // `valueLink`, even if we're using plain `value` and `onChange`.
        return props.valueLink || {
          value: props.value,
          requestChange: props.onChange
        };
      },
    
      componentDidMount: function() {
        var valueLink = this.getValueLink(this.props);
    
        jQuery(this.getDOMNode()).colorPicker({
          pickerDefault: valueLink.value,
          onColorChange: this.onColorChange
        });
      },
    
      componentWillReceiveProps: function(nextProps) {
        var valueLink = this.getValueLink(nextProps);
        var node = jQuery(this.getDOMNode());
        node.val(valueLink.value);
        node.change();
      },
    
      onColorChange: function(id, color) {
        this.getValueLink(this.props).requestChange(color);
      }
    });
    

    div.colorPicker-picker {
      height: 16px;
      width: 16px;
      padding: 0 !important;
      border: 1px solid #ccc;
      background: url(https://raw.github.com/laktek/really-simple-color-picker/master/arrow.gif) no-repeat top right;
      cursor: pointer;
      line-height: 16px;
    }
    
    div.colorPicker-palette {
      width: 110px;
      position: absolute;
      border: 1px solid #598FEF;
      background-color: #EFEFEF;
      padding: 2px;
      z-index: 9999;
    }
      div.colorPicker_hexWrap {width: 100%; float:left }
      div.colorPicker_hexWrap label {font-size: 95%; color: #2F2F2F; margin: 5px 2px; width: 25%}
      div.colorPicker_hexWrap input {margin: 5px 2px; padding: 0; font-size: 95%; border: 1px solid #000; width: 65%; }
    
    div.colorPicker-swatch {
      height: 12px;
      width: 12px;
      border: 1px solid #000;
      margin: 2px;
      float: left;
      cursor: pointer;
      line-height: 12px;
    }
    <script src="http://fb.me/react-with-addons-0.11.2.js"></script>
    <script src="http://fb.me/JSXTransformer-0.11.2.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
    <script src="https://dl.dropboxusercontent.com/u/113308/dnd/jsfiddle/jquery.colorPicker.min.js"></script>
    
    <p><strong>With valueLink</strong></p>
    <div id="app1"></div>
    <hr>
    <p><strong>With value and onChange</strong></p>
    <div id="app2"></div>
    
    <script type="text/jsx">
    /** @jsx React.DOM */
    
    var ApplicationWithValueLink = React.createClass({
      mixins: [React.addons.LinkedStateMixin],
    
      getInitialState: function() {
        return { color: "#FF0000" }
      },
      
      render: function() {
        return (
          <div>
            <div>
              <span style={{color: this.state.color}}>My Color Picker</span>
              <button onClick={this.changeColor.bind(null, "#FF0000")}>Red</button>
              <button onClick={this.changeColor.bind(null, "#00FF00")}>Green</button>
              <button onClick={this.changeColor.bind(null, "#0000FF")}>Blue</button>
              <input type="text" valueLink={this.linkState("color")} />
            </div>
            <div>
              <ColorPicker valueLink={this.linkState("color")} />
            </div>
          </div>
        );
      },
      
      changeColor: function(color) {
        this.setState({color: color});
      }
    });
    
    var ApplicationWithoutValueLink = React.createClass({
      getInitialState: function() {
        return { color: "#FF0000" }
      },
      
      render: function() {
        return (
          <div>
            <div>
              <span style={{color: this.state.color}}>My Color Picker</span>
              <button onClick={this.changeColor.bind(null, "#FF0000")}>Red</button>
              <button onClick={this.changeColor.bind(null, "#00FF00")}>Green</button>
              <button onClick={this.changeColor.bind(null, "#0000FF")}>Blue</button>
              <input type="text" value={this.state.color} onChange={this.changeColorText} />
            </div>
            <div>
              <ColorPicker value={this.state.color} onChange={this.changeColor} />
            </div>
          </div>
        );
      },
      
      changeColor: function(color) {
        this.setState({color: color});
      },
      
      changeColorText: function(evt) {
        this.changeColor(evt.target.value);
      }
    });
    
    var ColorPicker = React.createClass({
      render: function() {
        return (
          <div />
        );
      },
      
      getValueLink: function(props) {
        return props.valueLink || {
          value: props.value,
          requestChange: props.onChange
        };
      },
      
      componentDidMount: function() {
        var valueLink = this.getValueLink(this.props);
    
        jQuery(this.getDOMNode()).colorPicker({
          pickerDefault: valueLink.value,
          onColorChange: this.onColorChange
        });
      },
      
      componentWillReceiveProps: function(nextProps) {
        var valueLink = this.getValueLink(nextProps);
        var node = jQuery(this.getDOMNode());
        node.val(valueLink.value);
        node.change();
      },
      
      onColorChange: function(id, color) {
        this.getValueLink(this.props).requestChange(color);
      }
    });
    
    React.renderComponent(<ApplicationWithValueLink />, document.getElementById("app1"));
    React.renderComponent(<ApplicationWithoutValueLink />, document.getElementById("app2"));
    </script>

    【讨论】:

      猜你喜欢
      • 2014-11-17
      • 1970-01-01
      • 2020-09-16
      • 1970-01-01
      • 2021-04-03
      • 1970-01-01
      • 1970-01-01
      • 2018-07-06
      • 2017-01-14
      相关资源
      最近更新 更多