ReactJS + Flux:如何从 HTML 传递数据属性?

ReactJS + Flux: How to pass data attribute from HTML?

我正在使用 ReactJS(Flux) 和 Laravel 框架。我需要将一个变量从 blade 模板传递给 React 组件。我正在尝试使用 data-x 属性。

我的问题是..

  1. 如何获取React(或Flux架构)中的数据?

  2. 您是否有将数据存储在 Flux 中的最佳实践。 app.js 是最好的地方吗?

谢谢,

index.blade.php

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>ReactJS</title>
  </head>
  <body>
    <section id="react" data-domain="{{env("DOMAIN")}}"></section>
    <script src="{{ elixir('js/bundle.js') }}"></script>
  </body>
</html>

/app.js

var React = require('react');
var SampleApp = require('./components/SampleApp.react');

React.render(
  <SampleApp />,
  document.getElementById('react')
);

/components/SampleApp.反应

var React = require('react');
var SampleApp = React.createClass({
  render: function() {
    return (
      <div>
        Hello
      </div>
    );
  }
});
module.exports = SampleApp;

============================================= ======

编辑 1

我可以使用 {this.props.domain} 传递数据。下一步是如何将数据存储为 Flux 方式。

/app.js

var React = require('react');
var SampleApp = require('./components/SampleApp.react');

var react = document.getElementById('react');

React.render(
  <SampleApp domain={react.dataset.domain}/>,
  react
);

/components/SampleApp.反应

var React = require('react');
var SampleApp = React.createClass({
  render: function() {
    return (
      <div>
        Hello {this.props.domain}
      </div>
    );
  }
});
module.exports = SampleApp;

============================================= ======

编辑 2

固定

/index.blade.php
/app.js
/components/SampleApp.react.js
/actions/SampleActionCreators.js
/constans/SampleConstants.js
/dispatcher/SampleAppDispatcher.js
/stores/SampleStore.js

index.blade.php

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>ReactJS</title>
  </head>
  <body>
    <section id="react" data-domain="test.example.com"></section>
    <script src="{{ elixir('js/bundle.js') }}"></script>
  </body>
</html>

/app.js

var React = require('react');
var SampleApp = require('./components/SampleApp.react');

React.render(
  <SampleApp />,
  document.getElementById('react')
);

/components/SampleApp.react.js

var React = require('react');
var SampleActionCreators = require('../actions/SampleActionCreators');
var SampleStore = require('../stores/SampleStore');

function getSampleState() {
  return {
    domain: SampleStore.getDomain()
  };
}

var SampleApp = React.createClass({
  getInitialState: function() {
    return getSampleState();
  },

  componentDidMount: function() {
    SampleStore.addChangeListener(this._onChange);

    var domain = document.querySelector('#react').dataset.domain;
    SampleActionCreators.initData(domain);
  },

  componentWillUnmount: function() {
    SampleStore.removeChangeListener(this._onChange);
  },

  render: function() {
    return (
      <div>
        Hello {this.state.domain}
      </div>
    );
  },

  _onChange: function() {
    this.setState(getSampleState());
  }

});
module.exports = SampleApp;

/actions/SampleActionCreators.js

var SampleAppDispatcher = require('../dispatcher/SampleAppDispatcher');
var SampleConstants = require('../constants/SampleConstants');

var ActionTypes = SampleConstants.ActionTypes;

module.exports = {

    initData: function(domain) {
        SampleAppDispatcher.dispatch({
            type: ActionTypes.SAMPLE_INIT_DATA,
            domain: domain
        });
    },

};

/constans/SampleConstants.js

var keyMirror = require('keymirror');

module.exports = keyMirror({
  ActionTypes: keyMirror({
    SAMPLE_INIT_DATA: null
  })
});

/dispatcher/SampleAppDispatcher.js

var Dispatcher = require('flux').Dispatcher;

module.exports = new Dispatcher();

/stores/SampleStore.js

var SampleAppDispatcher = require('../dispatcher/SampleAppDispatcher');
var SampleConstants = require('../constants/SampleConstants');
var EventEmitter = require('events').EventEmitter;
var assign = require('object-assign');

var CHANGE_EVENT = "change";

var _domain = "";

var SampleStore = assign({}, EventEmitter.prototype, {

    getDomain: function() {
        return _domain;
    },

    emitChange: function() {
        this.emit(CHANGE_EVENT);
    },

    addChangeListener: function(callback) {
        this.on(CHANGE_EVENT, callback);
    },

    removeChangeListener: function(callback) {
        this.removeListener(CHANGE_EVENT, callback);
    }
});

SampleAppDispatcher.register(function(action) {

    switch (action.actionType) {
        case SampleConstants.SAMPLE_INIT_DATA:
            _domain = action.domain;
            SampleStore.emitChange();
            break;

        default:
            // no op
    }
});

module.exports = SampleStore;

您的第二次编辑是 "correct" Flux 方式,与我在多个大型项目中使用的方式相同。

更简单的替代方法是在 app.js 中获取域并将其作为 prop 传递给您的 SampleApp。这需要在 JS 执行之前加载 blade 模板中的 DOM。既然你已经把你的 JS 放在底部,你应该很好,但我添加了 window.onload 事件只是为了确保它。

var React = require('react');
var SampleApp = require('./components/SampleApp.react');

function getDomain() {
    return document.getElementById('react').dataset.domain;
}

function initReact() {

    var params = {
        domain: getDomain()
    };

    React.render(
        <SampleApp {...params} />,
        document.getElementById('react')
    );

}

window.onload = function() {
    initReact();
};

现在您可以使用 {this.props.domain} 访问您在 SampleApp.reatc.js

中的域值